automotive-dlt
dlt_offline_logstorage_behavior.c
Go to the documentation of this file.
1 
23 #include <syslog.h>
24 #include <limits.h>
25 #include <dirent.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 
32 #include "dlt_offline_logstorage.h"
34 
53 void dlt_logstorage_log_file_name(char *log_file_name,
54  DltLogStorageUserConfig *file_config,
55  char *name,
56  int idx)
57 {
58  if (log_file_name == NULL || file_config == NULL)
59  {
60  return;
61  }
62 
63  char file_index[10] = {'\0'};
64 
65  // create log file name
66  memset(log_file_name, 0, DLT_MOUNT_PATH_MAX * sizeof(char));
67  strcat(log_file_name, name);
68  strncat(log_file_name, &file_config->logfile_delimiter, 1);
69 
70  snprintf(file_index, 10, "%d",idx);
71 
72  if (file_config->logfile_maxcounter != UINT_MAX)
73  {
74  /* Setup 0's to be appended in file index until max index len*/
75  unsigned int digit_idx = 0;
76  unsigned int i = 0;
77  snprintf(file_index, 10, "%d",idx);
78  digit_idx = strlen(file_index);
79  for(i=0; i<(file_config->logfile_counteridxlen - digit_idx); i++)
80  {
81  strcat(log_file_name, "0");
82  }
83  }
84 
85  strcat(log_file_name, file_index);
86 
87  /* Add time stamp if user has configured */
88  if (file_config->logfile_timestamp)
89  {
90  char stamp[DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1] = {0};
91  time_t t = time(NULL);
92  struct tm *tm_info = localtime(&t);
93  sprintf(stamp,
94  "%c%04d%02d%02d-%02d%02d%02d",
95  file_config->logfile_delimiter,
96  1900 + tm_info->tm_year,
97  1 + tm_info->tm_mon,
98  tm_info->tm_mday,
99  tm_info->tm_hour,
100  tm_info->tm_min,
101  tm_info->tm_sec);
102  strcat(log_file_name, stamp);
103  }
104 
105  strcat(log_file_name, ".dlt");
106 }
107 
117 {
118  int done = 0;
119 
120  if (head == NULL || *head == NULL || (*head)->next == NULL)
121  {
122  return;
123  }
124 
125  while (!done)
126  {
127  /* "source" of the pointer to the current node in the list struct */
128  DltLogStorageFileList **pv = head;
129  DltLogStorageFileList *nd = *head; /* local iterator pointer */
130  DltLogStorageFileList *nx = (*head)->next; /* local next pointer */
131 
132  done = 1;
133 
134  while (nx)
135  {
136  if (nd->idx > nx->idx)
137  {
138  nd->next = nx->next;
139  nx->next = nd;
140  *pv = nx;
141 
142  done = 0;
143  }
144  pv = &nd->next;
145  nd = nx;
146  nx = nx->next;
147  }
148  }
149 }
150 
160 {
161  DltLogStorageFileList *n_prev = NULL;
162  DltLogStorageFileList *tail = NULL;
163  DltLogStorageFileList *wrap_pre = NULL;
164  DltLogStorageFileList *wrap_post = NULL;
166 
167  if (head == NULL || *head == NULL || (*head)->next == NULL)
168  {
169  return;
170  }
171 
172  for (n = *head; n != NULL; n = n->next)
173  {
174  if (n && n_prev)
175  {
176  if ((n->idx - n_prev->idx) != 1)
177  {
178  wrap_post = n;
179  wrap_pre = n_prev;
180  }
181  }
182  n_prev = n;
183  }
184  tail = n_prev;
185 
186  if (wrap_post && wrap_pre)
187  {
188  wrap_pre->next = NULL;
189  tail->next = *head;
190  *head = wrap_post;
191  }
192 }
193 
204  DltLogStorageUserConfig *file_config,
205  char *file)
206 {
207  unsigned int idx = -1;
208  char *endptr;
209  char *filename;
210  unsigned int filename_len = 0 ;
211  unsigned int fileindex_len = 0;
212 
213  if (file_config == NULL || file == NULL)
214  {
215  return -1;
216  }
217 
218  /* Calculate actual file name length */
219  filename=strchr(file, file_config->logfile_delimiter);
220  filename_len = strlen(file) - strlen(filename);
221 
222  /* index is retrived from file name */
223  if(file_config->logfile_timestamp)
224  {
225  fileindex_len = strlen(file) -
228  filename_len + 1);
229 
230  idx = (int) strtol(&file[strlen(file) -
232  fileindex_len +
234  &endptr,
235  10);
236  }
237  else
238  {
239  fileindex_len = strlen(file) -
241  filename_len + 1);
242 
243  idx = (int) strtol(&file[strlen(file)-
245  +fileindex_len)], &endptr, 10);
246  }
247 
248  if (endptr == file || idx == 0)
249  {
250  dlt_log(LOG_ERR,
251  "Unable to calculate index from log file name. Reset to 001.\n");
252  }
253 
254  return idx;
255 }
256 
269  char *path,
271 {
272  int i = 0;
273  int cnt = 0;
274  int ret = 0;
275  struct dirent **files = {0};
276  unsigned int current_idx = 0;
277 
278  if (config == NULL ||
279  file_config == NULL ||
280  path == NULL ||
281  config->file_name == NULL)
282  {
283  return -1;
284  }
285 
286  cnt = scandir(path, &files, 0, alphasort);
287  if (cnt < 0)
288  {
289  dlt_log(LOG_ERR,
290  "dlt_logstorage_storage_dir_info: Failed to scan directory\n");
291  return -1;
292  }
293 
294  for (i = 0; i < cnt; i++)
295  {
296  int len = 0;
297  len = strlen(config->file_name);
298  if ((strncmp(files[i]->d_name,
299  config->file_name,
300  len) == 0) &&
301  (files[i]->d_name[len] == file_config->logfile_delimiter))
302  {
303  DltLogStorageFileList **tmp = NULL;
304  current_idx = dlt_logstorage_get_idx_of_log_file(file_config,
305  files[i]->d_name);
306 
307  if(config->records == NULL)
308  {
309  config->records = malloc(sizeof(DltLogStorageFileList));
310  if (config->records == NULL)
311  {
312  ret = -1;
313  dlt_log(LOG_ERR,
314  "Memory allocation failed\n");
315  break;
316  }
317  tmp = &config->records;
318  }
319  else
320  {
321  tmp = &config->records;
322  while(*(tmp) != NULL)
323  {
324  tmp = &(*tmp)->next;
325  }
326  *tmp = malloc(sizeof(DltLogStorageFileList));
327  if (*tmp == NULL)
328  {
329  ret = -1;
330  dlt_log(LOG_ERR,
331  "Memory allocation failed\n");
332  break;
333  }
334  }
335  (*tmp)->name = strdup(files[i]->d_name);
336  (*tmp)->idx = current_idx;
337  (*tmp)->next = NULL;
338  }
339  }
340 
341  if (ret == 0)
342  {
345  }
346 
347  /* free scandir result */
348  for (i = 0; i < cnt; i++)
349  {
350  free(files[i]);
351  }
352  free(files);
353 
354  return ret;
355 }
356 
372  DltLogStorageUserConfig *file_config,
373  char *dev_path,
374  int msg_size)
375 {
376  int ret = 0;
377  char absolute_file_path[DLT_MOUNT_PATH_MAX + 1] = {'\0'};
378  char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN] = {'\0'};
379  unsigned int num_log_files = 0;
380  struct stat s;
381  DltLogStorageFileList **tmp = NULL;
382  DltLogStorageFileList **newest = NULL;
383  char file_name[DLT_MOUNT_PATH_MAX + 1] = {'\0'};
384 
385  if (config == NULL)
386  {
387  return -1;
388  }
389 
390  if(snprintf(storage_path, DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN,
391  "%s/", dev_path) >= DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN)
392  {
393  dlt_log(LOG_ERR, "Mount point path name too long\n");
394  return -1;
395  }
396 
397  /* check if there are already files stored */
398  if (config->records == NULL)
399  {
400  if (dlt_logstorage_storage_dir_info(file_config, storage_path, config)
401  != 0)
402  return -1;
403  }
404 
405  /* obtain locations of newest, current file names, file count */
406  tmp = &config->records;
407  while(*(tmp) != NULL)
408  {
409  num_log_files += 1;
410  if((*tmp)->next == NULL)
411  newest = tmp;
412 
413  tmp = &(*tmp)->next;
414  }
415 
416  /* need new file*/
417  if (num_log_files == 0)
418  {
420  file_config,
421  config->file_name,
422  1);
423 
424  /* concatenate path and file and open absolute path */
425  strcat(absolute_file_path, storage_path);
426  strcat(absolute_file_path, file_name);
427  config->log = fopen(absolute_file_path, "a+");
428 
429  /* Add file to file list */
430  *tmp = malloc(sizeof(DltLogStorageFileList));
431  if (*tmp == NULL)
432  {
433  dlt_log(LOG_ERR,
434  "Memory allocation for file name failed\n");
435  return -1;
436  }
437  (*tmp)->name = strdup(file_name);
438  (*tmp)->idx = 1;
439  (*tmp)->next = NULL;
440  }
441  else /* newest file available*/
442  {
443  strcat(absolute_file_path, storage_path);
444  strcat(absolute_file_path, (*newest)->name);
445 
446  ret = stat(absolute_file_path, &s);
447 
448  /* if size is enough, open it */
449  if (ret == 0 && s.st_size + msg_size < (int)config->file_size)
450  {
451  config->log = fopen(absolute_file_path, "a+");
452  }
453  else /* no space in file or file stats cannot be read */
454  {
455  unsigned int idx = 0;
456 
457  /* get index of newest log file */
458  idx = dlt_logstorage_get_idx_of_log_file(file_config,
459  (*newest)->name);
460  idx += 1;
461 
462  /* wrap around if max index is reached or an error occurred
463  * while calculating index from file name */
464  if (idx > file_config->logfile_maxcounter || idx == 0)
465  {
466  idx = 1;
467  }
468 
470  file_config,
471  config->file_name,
472  idx);
473 
474  /* concatenate path and file and open absolute path */
475  memset(absolute_file_path,
476  0,
477  sizeof(absolute_file_path)/sizeof(char));
478  strcat(absolute_file_path, storage_path);
479  strcat(absolute_file_path, file_name);
480  config->log = fopen(absolute_file_path, "a+");
481 
482  /* Add file to file list */
483  *tmp = malloc(sizeof(DltLogStorageFileList));
484  if (*tmp == NULL)
485  {
486  dlt_log(LOG_ERR,
487  "Memory allocation for file name failed\n");
488  return -1;
489  }
490 
491  (*tmp)->name = strdup(file_name);
492  (*tmp)->idx = idx;
493  (*tmp)->next = NULL;
494 
495  num_log_files += 1;
496 
497  /* check if number of log files exceeds configured max value */
498  if (num_log_files > config->num_files)
499  {
500  /* delete oldest */
501  DltLogStorageFileList **head = &config->records;
502  DltLogStorageFileList *n = *head;
503  memset(absolute_file_path,
504  0,
505  sizeof(absolute_file_path)/sizeof(char));
506  strcat(absolute_file_path, storage_path);
507  strcat(absolute_file_path, (*head)->name);
508  remove(absolute_file_path);
509  free((*head)->name);
510  *head = n->next;
511  n->next = NULL;
512  free(n);
513  }
514  }
515  }
516 
517  if (config->log == NULL)
518  {
519  dlt_log(LOG_ERR,
520  "dlt_logstorage_create_log_file: Unable to open log file.\n");
521  return -1;
522  }
523 
524  return ret;
525 }
526 
540  DltLogStorageUserConfig *file_config,
541  char *dev_path,
542  int log_msg_size)
543 {
544  int ret = 0;
545  struct stat s;
546 
547  if (config == NULL || file_config == NULL || dev_path == NULL)
548  {
549  return -1;
550  }
551 
552  if (config->log == NULL) /* open a new log file */
553  {
554  ret = dlt_logstorage_open_log_file(config,
555  file_config,
556  dev_path,
557  log_msg_size);
558  }
559  else /* already open, check size and create a new file if needed */
560  {
561  ret = fstat(fileno(config->log), &s);
562  if (ret == 0) {
563  /* check if adding new data do not exceed max file size */
564  if (s.st_size + log_msg_size >= (int)config->file_size)
565  {
566  fclose(config->log);
567  config->log = NULL;
568  ret = dlt_logstorage_open_log_file(config,
569  file_config,
570  dev_path,
571  log_msg_size);
572  }
573  else /*everything is prepared */
574  {
575  ret = 0;
576  }
577  }
578  else
579  {
580  dlt_log(LOG_ERR,
581  "dlt_logstorage_prepare_log_file: stat() failed.\n");
582  ret = -1;
583  }
584  }
585  return ret;
586 }
587 
603  unsigned char *data1,
604  int size1,
605  unsigned char *data2,
606  int size2,
607  unsigned char *data3,
608  int size3)
609 {
610  int ret;
611 
612  if (config == NULL || data1 == NULL || data2 == NULL || data3 == NULL)
613  {
614  return -1;
615  }
616 
617  ret = fwrite(data1, 1, size1, config->log);
618  if (ret != size1)
619  {
620  dlt_log(LOG_WARNING, "Wrote less data than specified\n");
621  }
622  ret = fwrite(data2, 1, size2, config->log);
623  if (ret != size2)
624  {
625  dlt_log(LOG_WARNING, "Wrote less data than specified\n");
626  }
627  ret = fwrite(data3, 1, size3, config->log);
628  if (ret != size3)
629  {
630  dlt_log(LOG_WARNING, "Wrote less data than specified\n");
631  }
632 
633  return ferror(config->log);
634 }
635 
646 {
647  int ret;
648 
649  if (config == NULL)
650  {
651  return -1;
652  }
653 
654  if (status == DLT_LOGSTORAGE_SYNC_ON_MSG) /* sync on every message */
655  {
656  ret = fflush(config->log);
657 
658  if (ret != 0)
659  {
660  dlt_log(LOG_ERR, "fflush failed\n");
661  }
662  }
663 
664  return 0;
665 }
666 
681  DltLogStorageUserConfig *file_config,
682  char *dev_path,
683  int log_msg_size)
684 {
685  if (config == NULL || file_config == NULL || dev_path == NULL)
686  {
687  return -1;
688  }
689 
690  log_msg_size = log_msg_size; /* satisfy compiler */
691 
692  /* create file to sync cache into later */
693  if (config->log == NULL)
694  {
695  /* get always a new file */
697  file_config,
698  dev_path,
699  config->file_size) != 0)
700  {
701  dlt_log(LOG_ERR,
702  "Cannot prepare log file for ON_DAEMON_EXIT sync\n");
703  return -1;
704  }
705  }
706 
707  /* create cache */
708  if (config->cache == NULL)
709  {
710  /* check total logstorage cache size */
712  config->file_size +
713  sizeof(DltLogStorageCacheFooter)) >
715  {
716  dlt_log(LOG_ERR, "Max size of Logstorage Cache already used.");
717  return -1;
718  }
719 
720  config->cache = calloc(1,
721  config->file_size +
722  sizeof(DltLogStorageCacheFooter));
723 
724  /* update current used cache size */
726  sizeof(DltLogStorageCacheFooter);
727 
728  if (config->cache == NULL)
729  {
730  dlt_log(LOG_CRIT,
731  "Cannot allocate memory for filter ring buffer\n");
732  }
733  }
734 
735  return 0;
736 }
737 
753  unsigned char *data1,
754  int size1,
755  unsigned char *data2,
756  int size2,
757  unsigned char *data3,
758  int size3)
759 {
760  DltLogStorageCacheFooter *footer = NULL;
761  int msg_size;
762  int remain_cache_size;
763  void *curr_write_addr = NULL;
764 
765  if (config == NULL || data1 == NULL || size1 < 0 || data2 == NULL ||
766  size2 < 0 || data3 == NULL || size3 < 0 || config->cache == NULL)
767  {
768  return -1;
769  }
770 
771  footer = (DltLogStorageCacheFooter *)(config->cache + config->file_size);
772  if (footer == NULL)
773  {
774  dlt_log(LOG_ERR, "Cannot retrieve cache footer. Address is NULL\n");
775  return -1;
776  }
777 
778  msg_size = size1 + size2 + size3;
779  remain_cache_size = config->file_size - footer->offset;
780 
781  if (msg_size < remain_cache_size) /* add at current position */
782  {
783  curr_write_addr = (void *)(config->cache + footer->offset);
784  footer->offset += msg_size;
785  }
786  else if (msg_size > remain_cache_size)
787  {
788  if ((unsigned int) msg_size > config->file_size)
789  {
790  dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n");
791  return -1;
792  }
793 
794  /* start writing from beginning */
795  curr_write_addr = config->cache;
796  footer->offset = msg_size;
797  footer->wrap_around_cnt += 1;
798  }
799  else /* message just fits into cache */
800  {
801  curr_write_addr = (void *)(config->cache + footer->offset);
802  footer->offset = 0;
803  footer->wrap_around_cnt += 1;
804  }
805 
806  /* write data to cache */
807  memcpy(curr_write_addr, data1, size1);
808  curr_write_addr += size1;
809  memcpy(curr_write_addr, data2, size2);
810  curr_write_addr += size2;
811  memcpy(curr_write_addr, data3, size3);
812 
813  return 0;
814 }
815 
826  int status)
827 {
828  int ret = 0;
829  DltLogStorageCacheFooter *footer = NULL;
830 
831  if (config == NULL)
832  {
833  return -1;
834  }
835 
836  /* sync only, if given strategy is set */
837  if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, status) > 0)
838  {
839  if (config->log == NULL || config->cache == NULL)
840  {
841  dlt_log(LOG_ERR,
842  "Cannot copy cache to file. One of both is NULL\n");
843  return -1;
844  }
845 
846  /* TODO: write only what is needed */
847  /* write ring buffer into file */
848  footer = (DltLogStorageCacheFooter *)(config->cache +
849  config->file_size);
850 
851  if (footer == NULL)
852  {
853  dlt_log(LOG_ERR, "Cannot retrieve cache information\n");
854  return -1;
855  }
856 
857  /* TODO: check if really the whole cache need to be written */
858  /* write cache to file */
859  ret = fwrite(config->cache, config->file_size, 1, config->log);
860 
861  if (ret <= 0)
862  {
863  if (ferror(config->log) != 0)
864  {
865  dlt_log(LOG_CRIT, "Failed to write cache into log file\n");
866  }
867  }
868  else
869  {
870  /* force sync */
871  if (fsync(fileno(config->log)) != 0)
872  {
873  dlt_log(LOG_ERR, "Failed to sync log file\n");
874  }
875  }
876 
877  /* do not reinitialize in case of ON_DAEMON_EXIT */
879  {
880  /* clean ring buffer and reset footer information */
881  memset(config->cache,
882  0,
883  config->file_size + sizeof(DltLogStorageCacheFooter));
884 
885  /* close the file, a new one will be created when prepare is
886  * called again */
887  fclose(config->log);
888  config->log = NULL;
889  }
890  }
891 
892  return 0;
893 }
unsigned int g_logstorage_cache_size
DltKpiConfig config
Definition: dlt-kpi.c:37
void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head)
int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size)
DltReturnValue dlt_log(int prio, char *s)
Definition: dlt_common.c:2029
int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status)
#define DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN
int dlt_logstorage_write_on_msg(DltLogStorageConfigData *config, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3)
DltLogStorageFileList * records
#define DLT_MOUNT_PATH_MAX
Definition: dlt_common.h:332
int dlt_logstorage_sync_msg_cache(DltLogStorageConfigData *config, int status)
int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size)
#define DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(S, s)
void dlt_logstorage_sort_file_name(DltLogStorageFileList **head)
int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3)
int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, char *path, DltLogStorageConfigData *config)
void dlt_logstorage_log_file_name(char *log_file_name, DltLogStorageUserConfig *file_config, char *name, int idx)
int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, DltLogStorageUserConfig *file_config, char *dev_path, int msg_size)
unsigned int g_logstorage_cache_max
struct DltLogStorageFileList * next
#define DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT
#define DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN
unsigned int dlt_logstorage_get_idx_of_log_file(DltLogStorageUserConfig *file_config, char *file)
#define DLT_LOGSTORAGE_SYNC_ON_MSG
#define NULL
Definition: dlt_common.h:232
#define DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN