summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/daemon/CMakeLists.txt2
-rw-r--r--src/daemon/dlt-daemon.c29
-rw-r--r--src/daemon/dlt-daemon.h1
-rw-r--r--src/daemon/dlt.conf3
-rw-r--r--src/daemon/dlt_daemon_offline_logstorage.c32
-rw-r--r--src/daemon/dlt_daemon_offline_logstorage.h19
-rw-r--r--src/offlinelogstorage/dlt_offline_logstorage.c630
-rw-r--r--src/offlinelogstorage/dlt_offline_logstorage.h57
-rw-r--r--src/offlinelogstorage/dlt_offline_logstorage_behavior.c868
-rw-r--r--src/offlinelogstorage/dlt_offline_logstorage_behavior.h91
10 files changed, 1224 insertions, 508 deletions
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index f665a4d..128dbe8 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -20,7 +20,7 @@ if(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD)
message( STATUS "Added ${systemd_SRCS} to dlt-daemon")
endif(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD)
-set(dlt_daemon_SRCS dlt-daemon.c dlt_daemon_common.c dlt_daemon_connection.c dlt_daemon_event_handler.c dlt_daemon_socket.c dlt_daemon_unix_socket.c dlt_daemon_serial.c dlt_daemon_client.c dlt_daemon_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_offline_trace.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_config_file_parser.c)
+set(dlt_daemon_SRCS dlt-daemon.c dlt_daemon_common.c dlt_daemon_connection.c dlt_daemon_event_handler.c dlt_daemon_socket.c dlt_daemon_unix_socket.c dlt_daemon_serial.c dlt_daemon_client.c dlt_daemon_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_offline_trace.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_config_file_parser.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage_behavior.c)
add_executable(dlt-daemon ${dlt_daemon_SRCS} ${systemd_SRCS})
target_link_libraries(dlt-daemon rt ${CMAKE_THREAD_LIBS_INIT})
diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c
index 61aca56..02e42ec 100644
--- a/src/daemon/dlt-daemon.c
+++ b/src/daemon/dlt-daemon.c
@@ -84,6 +84,8 @@ static int dlt_daemon_log_internal(DltDaemon *daemon, DltDaemonLocal *daemon_loc
static uint32_t watchdog_trigger_interval; // watchdog trigger interval in [s]
#endif
+/* used in main event loop and signal handler */
+int g_exit = 0;
/**
* Print usage information of tool.
@@ -238,6 +240,9 @@ int option_file_parser(DltDaemonLocal *daemon_local)
daemon_local->flags.offlineLogstorageDelimiter = '_';
daemon_local->flags.offlineLogstorageMaxCounter = UINT_MAX;
daemon_local->flags.offlineLogstorageMaxCounterIdx = 0;
+ daemon_local->flags.offlineLogstorageCacheSize = 30000; /* 30MB */
+ dlt_daemon_logstorage_set_logstorage_cache_size(
+ daemon_local->flags.offlineLogstorageCacheSize);
strncpy(daemon_local->flags.ctrlSockPath,
DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH,
sizeof(daemon_local->flags.ctrlSockPath) - 1);
@@ -459,6 +464,13 @@ int option_file_parser(DltDaemonLocal *daemon_local)
daemon_local->flags.offlineLogstorageMaxCounter = atoi(value);
daemon_local->flags.offlineLogstorageMaxCounterIdx = strlen(value);
}
+ else if(strcmp(token, "OfflineLogstorageCacheSize") == 0)
+ {
+ daemon_local->flags.offlineLogstorageCacheSize =
+ (unsigned int)atoi(value);
+ dlt_daemon_logstorage_set_logstorage_cache_size(
+ daemon_local->flags.offlineLogstorageCacheSize);
+ }
else if(strcmp(token,"ControlSocketPath") == 0)
{
memset(
@@ -499,7 +511,7 @@ int main(int argc, char* argv[])
char version[DLT_DAEMON_TEXTBUFSIZE];
DltDaemonLocal daemon_local;
DltDaemon daemon;
- int back;
+ int back = 0;
/* Command line option handling */
if ((back = option_handling(&daemon_local,argc,argv))<0)
@@ -637,7 +649,7 @@ int main(int argc, char* argv[])
dlt_daemon_log_internal(&daemon, &daemon_local, "Daemon launched. Starting to output traces...", daemon_local.flags.vflag);
/* Even handling loop. */
- while (back >= 0)
+ while ((back >= 0) && (g_exit >= 0))
{
back = dlt_daemon_handle_event(&daemon_local.pEvent,
&daemon,
@@ -647,7 +659,13 @@ int main(int argc, char* argv[])
dlt_daemon_log_internal(&daemon, &daemon_local, "Exiting Daemon...", daemon_local.flags.vflag);
- dlt_daemon_local_cleanup(&daemon, &daemon_local, daemon_local.flags.vflag);
+ /* disconnect all logstorage devices */
+ dlt_daemon_logstorage_cleanup(&daemon,
+ &daemon_local,
+ daemon_local.flags.vflag);
+
+
+// dlt_daemon_local_cleanup(&daemon, &daemon_local, daemon_local.flags.vflag);
dlt_log(LOG_NOTICE, "Leaving DLT daemon\n");
@@ -1167,9 +1185,8 @@ void dlt_daemon_signal_handler(int sig)
tmp[PATH_MAX] = 0;
unlink(tmp);
-
- /* Terminate program */
- exit(0);
+ /* stop event loop */
+ g_exit = -1;
break;
}
default:
diff --git a/src/daemon/dlt-daemon.h b/src/daemon/dlt-daemon.h
index 503a98f..02a55b3 100644
--- a/src/daemon/dlt-daemon.h
+++ b/src/daemon/dlt-daemon.h
@@ -118,6 +118,7 @@ typedef struct
char offlineLogstorageDelimiter; /**< (char) Append delimeter character in offline logstorage filename */
unsigned int offlineLogstorageMaxCounter; /**< (int) Maximum offline logstorage file counter index until wraparound */
unsigned int offlineLogstorageMaxCounterIdx; /**< (int) String len of offlineLogstorageMaxCounter*/
+ unsigned int offlineLogstorageCacheSize; /**< Max cache size offline logstorage cache */
char userPipesDir[NAME_MAX + 1]; /**< (String: Directory) directory where dltpipes reside (Default: /tmp/dltpipes) */
char daemonFifoName[NAME_MAX + 1]; /**< (String: Filename) name of local fifo (Default: /tmp/dlt) */
unsigned int port; /**< port number */
diff --git a/src/daemon/dlt.conf b/src/daemon/dlt.conf
index 72377e5..5deec60 100644
--- a/src/daemon/dlt.conf
+++ b/src/daemon/dlt.conf
@@ -145,3 +145,6 @@ ControlSocketPath = /tmp/dlt-ctrl.sock
# Wrap around value for log file count in file name (Default: UINT_MAX)
# OfflineLogstorageMaxCounter = 999
+
+# Maximal used memory for Logstorage Cache in KB (Default: 30000 KB)
+# OfflineLogstorageCacheSize = 30000 \ No newline at end of file
diff --git a/src/daemon/dlt_daemon_offline_logstorage.c b/src/daemon/dlt_daemon_offline_logstorage.c
index bc8817c..66f9ec8 100644
--- a/src/daemon/dlt_daemon_offline_logstorage.c
+++ b/src/daemon/dlt_daemon_offline_logstorage.c
@@ -565,3 +565,35 @@ int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, char *path,
return ret;
}
+
+void dlt_daemon_logstorage_set_logstorage_cache_size(unsigned int size)
+{
+ /* store given [KB] size in [Bytes] */
+ g_logstorage_cache_max = size * 1000;
+}
+
+int dlt_daemon_logstorage_cleanup(DltDaemon *daemon,
+ DltDaemonLocal *daemon_local,
+ int verbose)
+{
+ int i = 0;
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if (daemon == NULL || daemon_local == NULL)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++)
+ {
+ /* call disconnect on all currently connected devices */
+ if (daemon->storage_handle[i].connection_type ==
+ DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED)
+ {
+ dlt_logstorage_device_disconnected(&daemon->storage_handle[i]);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/daemon/dlt_daemon_offline_logstorage.h b/src/daemon/dlt_daemon_offline_logstorage.h
index 621bd59..cb7698a 100644
--- a/src/daemon/dlt_daemon_offline_logstorage.h
+++ b/src/daemon/dlt_daemon_offline_logstorage.h
@@ -126,4 +126,23 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, DltDaemonFlags user_config,
* @param verbose If set to true verbose information is printed out
*/
int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, char *path, int verbose);
+
+/**
+ * Set max size of logstorage cache. Stored internally in bytes
+ *
+ * @param size Size of logstorage cache [in KB]
+ */
+void dlt_daemon_logstorage_set_logstorage_cache_size(unsigned int size);
+
+/**
+ * Cleanup dlt logstorage
+ *
+ * @param daemon Pointer to Dlt Daemon structure
+ * @param daemon_local Pointer to Dlt Daemon Local structure
+ * @param verbose If set to true verbose information is printed out
+ */
+int dlt_daemon_logstorage_cleanup(DltDaemon *daemon,
+ DltDaemonLocal *daemon_local,
+ int verbose);
+
#endif /* DLT_DAEMON_OFFLINE_LOGSTORAGE_H */
diff --git a/src/offlinelogstorage/dlt_offline_logstorage.c b/src/offlinelogstorage/dlt_offline_logstorage.c
index 682fe55..d1efbb5 100644
--- a/src/offlinelogstorage/dlt_offline_logstorage.c
+++ b/src/offlinelogstorage/dlt_offline_logstorage.c
@@ -32,6 +32,7 @@
#include <time.h>
#include "dlt_offline_logstorage.h"
+#include "dlt_offline_logstorage_behavior.h"
#include "dlt_config_file_parser.h"
@@ -312,6 +313,41 @@ int dlt_logstorage_read_number(unsigned int *number, char *value)
return 0;
}
+/**
+ * dlt_logstorage_set_sync_strategy
+ *
+ * Evaluate sync strategy. The sync strategy is an optional filter
+ * configuration parameter.
+ * If the given value cannot be associated with a sync strategy, the default
+ * sync strategy will be assigned.
+ *
+ * @param file_name int to store the sync strategy
+ * @param value string given in config file
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_set_sync_strategy(int *strategy, char *value)
+{
+ if (value == NULL || strategy == NULL)
+ {
+ return -1;
+ }
+
+ if (strncasecmp(value, "ON_MSG", strlen(value)) == 0)
+ {
+ *strategy = DLT_LOGSTORAGE_SYNC_ON_MSG;
+ }
+ else if (strncasecmp(value, "ON_DAEMON_EXIT", strlen(value)) == 0)
+ {
+ *strategy = DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT;
+ }
+ else
+ {
+ dlt_log(LOG_WARNING, "Unknown sync strategy. Set default ON_MSG\n");
+ *strategy = DLT_LOGSTORAGE_SYNC_ON_MSG;
+ }
+
+ return 0;
+}
/**
* dlt_logstorage_create_keys
@@ -518,10 +554,23 @@ void dlt_logstorage_free(DltLogStorage *handle)
for(i=0; i<handle->num_filter_keys; i++)
{
+ /* sync data if necessary */
+ /* ignore return value */
+ handle->config_data[i].data.dlt_logstorage_sync(
+ &(handle->config_data[i].data),
+ DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT);
+
free(handle->config_data[i].data.file_name);
if (handle->config_data[i].data.log != NULL)
- fclose(handle->config_data[i].data.log);
+ {
+ fclose(handle->config_data[i].data.log);
+ }
+
+ if (handle->config_data[i].data.cache != NULL)
+ {
+ free(handle->config_data[i].data.cache);
+ }
DltLogStorageFileList *n = handle->config_data[i].data.records;
while(n)
@@ -624,6 +673,8 @@ int dlt_logstorage_prepare_table(DltLogStorage *handle, char *appid, char *ctxid
memcpy(&p_node->data, tmp_data, sizeof(DltLogStorageConfigData));
p_node->data.file_name = strdup(tmp_data->file_name);
p_node->data.records = NULL;
+ p_node->data.log = NULL;
+ p_node->data.cache = NULL;
if(dlt_logstorage_hash_add(p_node->key, &p_node->data, &(handle->config_htab)) != 0)
{
@@ -703,6 +754,14 @@ int dlt_logstorage_validate_filter_value(char *filter_key, char *filter_value,
if (ret == 0)
ret = DLT_OFFLINE_LOGSTORAGE_NUM_INIT;
}
+ else if (strncmp(filter_key, "SyncBehavior", strlen ("SyncBehavior")) == 0)
+ {
+ ret = dlt_logstorage_set_sync_strategy(&(tmp_data->sync), filter_value);
+ if (ret == 0)
+ {
+ return DLT_OFFLINE_LOGSTORAGE_SYNC_BEHAVIOR;
+ }
+ }
else
{
/* Invalid filter key */
@@ -754,6 +813,29 @@ int dlt_logstorage_validate_filter_name(char *name)
return -1;
}
+void dlt_logstorage_filter_set_strategy(DltLogStorageConfigData *config,
+ int strategy)
+{
+ if (config == NULL)
+ {
+ return;
+ }
+
+ switch(strategy)
+ {
+ case DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT:
+ config->dlt_logstorage_prepare = &dlt_logstorage_prepare_on_daemon_exit;
+ config->dlt_logstorage_write = &dlt_logstorage_write_on_daemon_exit;
+ config->dlt_logstorage_sync = &dlt_logstorage_sync_on_daemon_exit;
+ break;
+ case DLT_LOGSTORAGE_SYNC_ON_MSG: /* ON_MSG is the default strategy */
+ default:
+ config->dlt_logstorage_prepare = &dlt_logstorage_prepare_on_msg;
+ config->dlt_logstorage_write = &dlt_logstorage_write_on_msg;
+ config->dlt_logstorage_sync = &dlt_logstorage_sync_on_msg;
+ }
+}
+
/**
* dlt_logstorage_store_filters
*
@@ -783,7 +865,8 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name)
"LogLevel",
"File",
"FileSize",
- "NOFiles"
+ "NOFiles",
+ "SyncBehavior"
};
config_file = dlt_config_file_init(config_file_name);
@@ -805,6 +888,7 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name)
int j = 0;
int ret = -1;
memset(&tmp_data, 0, sizeof(DltLogStorageConfigData));
+
for (i = 0; i < num_filters; i++)
{
if (tmp_data.file_name != NULL)
@@ -841,7 +925,9 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name)
{
/* Get filter value for filter keys */
ret = dlt_config_file_get_value(config_file, filter_name, filter_key[j], filter_value);
- if (ret != 0)
+ if (ret != 0 &&
+ strncmp(filter_key[j], "SyncBehavior", strlen(filter_key[j]))
+ != 0)
{
is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT;
dlt_log(LOG_ERR, "dlt_logstorage_store_filters Error : Reading filter value failed\n");
@@ -849,20 +935,35 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name)
}
/* Validate filter value */
- ret = dlt_logstorage_validate_filter_value(filter_key[j], filter_value, &appid, &ctxid, &tmp_data);
- if ((ret != -1) && DLT_OFFLINE_LOGSTORAGE_IS_FILTER_PRESENT(is_filter_set))
+ if (ret == 0)
{
- is_filter_set |= ret;
+ ret = dlt_logstorage_validate_filter_value(filter_key[j], filter_value, &appid, &ctxid, &tmp_data);
+ if ((ret != -1) && DLT_OFFLINE_LOGSTORAGE_IS_FILTER_PRESENT(is_filter_set))
+ {
+ is_filter_set |= ret;
+ }
+ else
+ {
+ is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT;
+ break;
+ }
}
else
{
- is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT;
- break;
+ dlt_log(LOG_INFO,
+ "Sync strategy not given. Use default ON_MSG\n");
+ /* set default sync strategy */
+ tmp_data.sync = DLT_LOGSTORAGE_SYNC_ON_MSG;
}
}
+
/* If all items of the filter is populated store them */
if (DLT_OFFLINE_LOGSTORAGE_FILTER_INITIALIZED(is_filter_set))
{
+ /* depending on the specified strategy set function pointers for
+ * prepare, write and sync */
+ dlt_logstorage_filter_set_strategy(&tmp_data, tmp_data.sync);
+
ret = dlt_logstorage_prepare_table(handle, appid, ctxid, &tmp_data);
if (ret != 0)
{
@@ -1088,469 +1189,6 @@ DltLogStorageConfigData **dlt_logstorage_filter(DltLogStorage *handle, char *app
}
/**
- * dlt_logstorage_log_file_name
- *
- * Create log file name in the form configured by the user
- * <filename><delimeter><index><delimeter><timestamp>.dlt
- *
- * filename: given in configuration file
- * delimeter: Punctuation characters (configured in dlt.conf)
- * timestamp: yyyy-mm-dd-hh-mm-ss (enabled/disabled in dlt.conf)
- * index: Index len depends on wrap around value in dlt.conf
- * ex: wrap around = 99, index will 01..99
- *
- * @param log_file_name contains complete logfile name
- * @param file_config User configurations for log file
- * @param name file name given in configuration file
- * @param idx continous index of log files
- * @ return None
- */
-void dlt_logstorage_log_file_name(char *log_file_name, DltLogStorageUserConfig file_config, char *name, int idx)
-{
- char file_index[10] = {0};
-
- // create log file name
- memset(log_file_name, 0, PATH_MAX * sizeof(char));
- strcat(log_file_name, name);
- strcat(log_file_name, &file_config.logfile_delimiter);
-
- sprintf(file_index,"%d",idx);
- if(file_config.logfile_maxcounter != UINT_MAX)
- {
- /* Setup 0's to be appended in file index until max index len*/
- unsigned int digit_idx = 0;
- unsigned int i = 0;
- sprintf(file_index,"%d",idx);
- digit_idx = strlen(file_index);
- for(i=0; i<(file_config.logfile_counteridxlen - digit_idx); i++) {
- strcat(log_file_name, "0");
- }
- }
- strcat(log_file_name, file_index);
-
- /* Add time stamp if user has configured */
- if(file_config.logfile_timestamp)
- {
- char stamp[DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1] = {0};
- time_t t = time(NULL);
- struct tm *tm_info = localtime(&t);
- sprintf(stamp, "%c%04d%02d%02d-%02d%02d%02d", file_config.logfile_delimiter, 1900 + tm_info->tm_year, 1 + tm_info->tm_mon,
- tm_info->tm_mday, tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
- strcat(log_file_name, stamp);
- }
-
- strcat(log_file_name, ".dlt");
-}
-
-/**
- * dlt_logstorage_sort_file_name
- *
- * Sort the filenames with index based ascending order (bubble sort)
- *
- * @param head Log filename list
- * @ return None
- */
-void dlt_logstorage_sort_file_name(DltLogStorageFileList **head)
-{
- int done = 0;
-
- if (*head == NULL || (*head)->next == NULL)
- return;
-
- while (!done)
- {
- DltLogStorageFileList **pv = head; // "source" of the pointer to the current node in the list struct
- DltLogStorageFileList *nd = *head; // local iterator pointer
- DltLogStorageFileList *nx = (*head)->next; // local next pointer
-
- done = 1;
-
- while (nx)
- {
- if (nd->idx > nx->idx)
- {
- nd->next = nx->next;
- nx->next = nd;
- *pv = nx;
-
- done = 0;
- }
- pv = &nd->next;
- nd = nx;
- nx = nx->next;
- }
- }
-}
-
-/**
- * dlt_logstorage_rearrange_file_name
- *
- * Rearrange the filenames in the order of latest and oldest
- *
- * @param head Log filename list
- * @ return None
- */
-void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head)
-{
- DltLogStorageFileList *n_prev = NULL;
- DltLogStorageFileList *tail = NULL;
- DltLogStorageFileList *wrap_pre = NULL;
- DltLogStorageFileList *wrap_post = NULL;
- DltLogStorageFileList *n = NULL;
-
- if (*head == NULL || (*head)->next == NULL)
- return;
-
- for (n = *head; n != NULL; n = n->next )
- {
- if (n && n_prev)
- {
- if ((n->idx - n_prev->idx) != 1)
- {
- wrap_post = n;
- wrap_pre = n_prev;
- }
- }
- n_prev = n;
- }
- tail = n_prev;
-
- if (wrap_post && wrap_pre)
- {
- wrap_pre->next = NULL;
- tail->next = *head;
- *head = wrap_post;
- }
-}
-
-/**
- * dlt_logstorage_get_idx_of_log_file
- *
- * Extract index of log file name passed as input argument
- *
- * @param file file name to extract the index from
- * @param file_config User configurations for log file
- * @return index on success, -1 if no index is found
- */
-unsigned int dlt_logstorage_get_idx_of_log_file(DltLogStorageUserConfig file_config, char *file)
-{
- unsigned int idx = -1;
- char *endptr;
- char *filename;
- unsigned int filename_len = 0 ;
- unsigned int fileindex_len = 0;
-
- /* Calculate actual file name length */
- filename=strchr(file,file_config.logfile_delimiter);
- filename_len = strlen(file)- strlen(filename);
-
- /* index is retrived from file name */
- if(file_config.logfile_timestamp)
- {
- fileindex_len = strlen(file)-(DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN
- + DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + filename_len + 1);
- idx = (int) strtol(&file[strlen(file)-
- (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN+fileindex_len
- +DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN)],
- &endptr, 10);
- }
- else
- {
- fileindex_len = strlen(file)-(DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + filename_len + 1);
- idx = (int) strtol(&file[strlen(file)-
- (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN
- +fileindex_len)], &endptr, 10);
- }
-
- if(endptr == file || idx == 0)
- dlt_log(LOG_ERR, "Unable to calculate index from log file name. Reset index to 001.\n");
-
- return idx;
-}
-
-/**
- * dlt_logstorage_storage_dir_info
- *
- * Read file names of storage directory.
- * Update the file list, arrange it in order of latest and oldest
- *
- * @param file_config User configurations for log file
- * @param path Path to storage directory
- * @param config DltLogStorageConfigData
- * @return 0 on success, -1 on error
- */
-int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig file_config, char *path, DltLogStorageConfigData *config)
-{
- int i = 0;
- int cnt = 0;
- int ret = 0;
- struct dirent **files = {0};
- unsigned int current_idx = 0;
-
- if (path == NULL || config->file_name == NULL)
- return -1;
-
- cnt = scandir(path, &files, 0, alphasort);
- if (cnt < 0)
- {
- dlt_log(LOG_ERR, "dlt_logstorage_storage_dir_info: Unable to scan storage directory.\n");
- return -1;
- }
-
- for (i = 0; i < cnt; i++)
- {
- int len = 0;
- len = strlen(config->file_name);
- if ((strncmp(files[i]->d_name, config->file_name, len) == 0) && (files[i]->d_name[len] == file_config.logfile_delimiter))
- {
- DltLogStorageFileList **tmp = NULL;
- current_idx = dlt_logstorage_get_idx_of_log_file(file_config, files[i]->d_name);
-
- if(config->records == NULL)
- {
- config->records = malloc(sizeof(DltLogStorageFileList));
- if (config->records == NULL)
- {
- ret = -1;
- dlt_log(LOG_ERR, "Memory allocation failure while preparing file list \n");
- break;
- }
- tmp = &config->records;
- }
- else
- {
- tmp = &config->records;
- while(*(tmp) != NULL)
- {
- tmp = &(*tmp)->next;
- }
- *tmp = malloc(sizeof(DltLogStorageFileList));
- if (*tmp == NULL)
- {
- ret = -1;
- dlt_log(LOG_ERR, "Memory allocation failure while preparing file list \n");
- break;
- }
- }
- (*tmp)->name = strdup(files[i]->d_name);
- (*tmp)->idx = current_idx;
- (*tmp)->next = NULL;
- }
- }
-
- if (ret == 0)
- {
- dlt_logstorage_sort_file_name(&config->records);
- dlt_logstorage_rearrange_file_name(&config->records);
- }
-
- /* free scandir result */
- for (i = 0; i < cnt; i++)
- {
- free(files[i]);
- }
- free(files);
-
- return ret;
-}
-
-/**
- * dlt_logstorage_open_log_file
- *
- * Open a log file. Check storage directory for already created files and open the oldest if
- * there is enough space to store at least msg_size.
- * Otherwise create a new file, but take configured max number of files into account and remove
- * the oldest file if needed.
- *
- * @param config DltLogStorageConfigData
- * @param file_config User configurations for log file
- * @param dev_path Storage device path
- * @param msg_size Size of incoming message
- * @return 0 on succes, -1 on error
- */
-int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, DltLogStorageUserConfig file_config,
- char *dev_path, int msg_size)
-{
- int ret = 0;
- char absolute_file_path[PATH_MAX + 1] = {0};
- char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN] = {0};
- unsigned int num_log_files = 0;
- struct stat s;
- DltLogStorageFileList **tmp = NULL;
- DltLogStorageFileList **newest = NULL;
- char file_name[PATH_MAX + 1] = {0};
-
- if (config == NULL)
- return -1;
-
- sprintf(storage_path, "%s/", dev_path);
-
- /* check if there are already files stored */
- if (config->records == NULL)
- {
- if (dlt_logstorage_storage_dir_info(file_config, storage_path, config) != 0)
- return -1;
- }
-
- /* obtain locations of newest, current file names, file count */
- tmp = &config->records;
- while(*(tmp) != NULL)
- {
- num_log_files += 1;
- if((*tmp)->next == NULL)
- newest = tmp;
-
- tmp = &(*tmp)->next;
- }
-
- /* need new file*/
- if (num_log_files == 0)
- {
- dlt_logstorage_log_file_name(file_name, file_config, config->file_name, 1);
-
- /* concatenate path and file and open absolute path */
- strcat(absolute_file_path, storage_path);
- strcat(absolute_file_path, file_name);
- config->log = fopen(absolute_file_path, "a+");
-
- /* Add file to file list */
- *tmp = malloc(sizeof(DltLogStorageFileList));
- if (*tmp == NULL)
- {
- dlt_log(LOG_ERR, "Memory allocation failure while adding file name to file list \n");
- return -1;
- }
- (*tmp)->name = strdup(file_name);
- (*tmp)->idx = 1;
- (*tmp)->next = NULL;
- }
- else /* newest file available*/
- {
- strcat(absolute_file_path, storage_path);
- strcat(absolute_file_path, (*newest)->name);
-
- ret = stat(absolute_file_path, &s);
-
- /* if size is enough, open it */
- if (ret == 0 && s.st_size + msg_size < (int)config->file_size)
- {
- config->log = fopen(absolute_file_path, "a+");
- }
- else /* no space in file or file stats cannot be read */
- {
- unsigned int idx = 0;
-
- /* get index of newest log file */
- idx = dlt_logstorage_get_idx_of_log_file(file_config, (*newest)->name);
- idx += 1;
-
- /* wrap around if max index is reached or an error occured
- * while calculating index from file name */
- if (idx > file_config.logfile_maxcounter || idx == 0)
- idx = 1;
-
- dlt_logstorage_log_file_name(file_name, file_config, config->file_name, idx);
-
- /* concatenate path and file and open absolute path */
- memset(absolute_file_path, 0, sizeof(absolute_file_path)/sizeof(char));
- strcat(absolute_file_path, storage_path);
- strcat(absolute_file_path, file_name);
- config->log = fopen(absolute_file_path, "a+");
-
- /* Add file to file list */
- *tmp = malloc(sizeof(DltLogStorageFileList));
- if (*tmp == NULL)
- {
- dlt_log(LOG_ERR, "Memory allocation failure while adding file name to file list \n");
- return -1;
- }
- (*tmp)->name = strdup(file_name);
- (*tmp)->idx = idx;
- (*tmp)->next = NULL;
-
- num_log_files += 1;
-
- /* check if number of log files exceeds configured max value */
- if (num_log_files > config->num_files)
- {
- /* delete oldest */
- DltLogStorageFileList **head = &config->records;
- DltLogStorageFileList *n = *head;
- memset(absolute_file_path, 0, sizeof(absolute_file_path)/sizeof(char));
- strcat(absolute_file_path, storage_path);
- strcat(absolute_file_path, (*head)->name);
- remove(absolute_file_path);
- free((*head)->name);
- *head = n->next;
- n->next = NULL;
- free(n);
- }
- }
- }
-
- if (config->log == NULL)
- {
- dlt_log(LOG_ERR, "dlt_logstorage_create_log_file: Unable to open log file.\n");
- return -1;
- }
-
- return ret;
-}
-
-/**
- * dlt_logstorage_prepare_log_file
- *
- * Prepare the log file for a certain filer. If log file not open or log files max size reached,
- * open a new file.
- *
- * @param config DltLogStorageConfigData
- * @param file_config User configurations for log file
- * @param dev_path Storage device path
- * @param log_msg_size Size of log message
- * @return 0 on success, -1 on error
- */
-int dlt_logstorage_prepare_log_file(DltLogStorageConfigData *config,
- DltLogStorageUserConfig file_config,
- char *dev_path, int log_msg_size)
-{
- int ret = 0;
- struct stat s;
-
- if (config == NULL)
- {
- return -1;
- }
-
- if (config->log == NULL) /* open a new log file */
- {
- ret = dlt_logstorage_open_log_file(config, file_config, dev_path, log_msg_size);
- }
- else /* already open, check size and create a new file if needed */
- {
- ret = fstat(fileno(config->log), &s);
- if (ret == 0) {
- /* check if adding new data do not exceed max file size */
- if (s.st_size + log_msg_size >= (int)config->file_size)
- {
- fclose(config->log);
- config->log = NULL;
- ret = dlt_logstorage_open_log_file(config, file_config, dev_path, log_msg_size);
- }
- else /*everything is prepared */
- {
- ret = 0;
- }
- }
- else
- {
- dlt_log(LOG_ERR, "dlt_logstorage_prepare_log_file: Unable to determine file stats.\n");
- ret = -1;
- }
- }
- return ret;
-}
-
-/**
* dlt_logstorage_write
*
* Write a message to one or more configured log files, based on filter configuration.
@@ -1582,7 +1220,8 @@ int dlt_logstorage_write(DltLogStorage *handle, DltLogStorageUserConfig file_con
return 0;
}
- /* check if log message need to be stored in a certain device based on filter config */
+ /* check if log message need to be stored in a certain device based on
+ * filter configuration */
config = dlt_logstorage_filter(handle, appid, ctxid, log_level, &num);
if (config != NULL)
@@ -1593,39 +1232,48 @@ int dlt_logstorage_write(DltLogStorage *handle, DltLogStorageUserConfig file_con
if(config[i] != NULL)
{
/* prepare logfile (create and/or open)*/
- ret = dlt_logstorage_prepare_log_file(config[i], file_config,
- handle->device_mount_point,
- size1 + size2 + size3);
+ ret = config[i]->dlt_logstorage_prepare(config[i],
+ &file_config,
+ handle->device_mount_point,
+ size1 + size2 + size3);
if (ret == 0) /* log data (write) */
{
- fwrite(data1, 1, size1, config[i]->log);
- fwrite(data2, 1, size2, config[i]->log);
- fwrite(data3, 1, size3, config[i]->log);
- ret = ferror(config[i]->log);
-
- if (ret != 0)
+ ret = config[i]->dlt_logstorage_write(config[i],
+ data1,
+ size1,
+ data2,
+ size2,
+ data3,
+ size3);
+
+ if (ret == 0)
{
- handle->write_errors += 1;
- if (handle->write_errors >= DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS)
+ /* flush to be sure log is stored on device */
+ ret = config[i]->dlt_logstorage_sync(config[i],
+ DLT_LOGSTORAGE_SYNC_ON_MSG);
+ if (ret != 0)
{
- err = -1;
+ dlt_log(LOG_ERR,
+ "dlt_logstorage_write: Unable to sync.\n");
}
-
- dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to write log to file.\n");
}
else
{
- /* flush to be sure log is stored on device */
- ret = fflush(config[i]->log);
- if (ret != 0)
+ handle->write_errors += 1;
+ if (handle->write_errors >=
+ DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS)
{
- dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to flush log to file.\n");
+ err = -1;
}
+
+ dlt_log(LOG_ERR,
+ "dlt_logstorage_write: Unable to write.\n");
}
}
else
{
- dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to prepare log file.\n");
+ dlt_log(LOG_ERR,
+ "dlt_logstorage_write: Unable to prepare.\n");
}
}
i++;
diff --git a/src/offlinelogstorage/dlt_offline_logstorage.h b/src/offlinelogstorage/dlt_offline_logstorage.h
index 80a75e8..01427a1 100644
--- a/src/offlinelogstorage/dlt_offline_logstorage.h
+++ b/src/offlinelogstorage/dlt_offline_logstorage.h
@@ -81,16 +81,18 @@
DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + 1)
#define DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT 0
-#define DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT (1<<6)
-#define DLT_OFFLINE_LOGSTORAGE_APP_INIT (1<<5)
-#define DLT_OFFLINE_LOGSTORAGE_CTX_INIT (1<<4)
-#define DLT_OFFLINE_LOGSTORAGE_LOG_LVL_INIT (1<<3)
-#define DLT_OFFLINE_LOGSTORAGE_NAME_INIT (1<<2)
-#define DLT_OFFLINE_LOGSTORAGE_SIZE_INIT (1<<1)
+#define DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT (1<<7)
+#define DLT_OFFLINE_LOGSTORAGE_APP_INIT (1<<6)
+#define DLT_OFFLINE_LOGSTORAGE_CTX_INIT (1<<5)
+#define DLT_OFFLINE_LOGSTORAGE_LOG_LVL_INIT (1<<4)
+#define DLT_OFFLINE_LOGSTORAGE_NAME_INIT (1<<3)
+#define DLT_OFFLINE_LOGSTORAGE_SIZE_INIT (1<<2)
+#define DLT_OFFLINE_LOGSTORAGE_SYNC_BEHAVIOR (1<<1)
#define DLT_OFFLINE_LOGSTORAGE_NUM_INIT 1
-#define DLT_OFFLINE_LOGSTORAGE_FILTER_INIT 0x7F
+/* Sync behavior is optional */
+#define DLT_OFFLINE_LOGSTORAGE_FILTER_INIT 0xFD
-#define DLT_OFFLINE_LOGSTORAGE_FILTER_INITIALIZED(A) ((A) == DLT_OFFLINE_LOGSTORAGE_FILTER_INIT)
+#define DLT_OFFLINE_LOGSTORAGE_FILTER_INITIALIZED(A) ((A) >= DLT_OFFLINE_LOGSTORAGE_FILTER_INIT)
#define DLT_OFFLINE_LOGSTORAGE_IS_FILTER_PRESENT(A) ((A) & DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT)
@@ -105,10 +107,26 @@
#define DLT_OFFLINE_LOGSTORAGE_MIN(A, B) ((A) < (B) ? (A) : (B))
#define DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS 5
-#define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_NUM 6
+#define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_NUM 7
#define DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION "FILTER"
+/* Offline Logstorage sync strategies */
+#define DLT_LOGSTORAGE_SYNC_ON_MSG 0x00 /* default, on message sync */
+#define DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT 0x01 /* sync on daemon exit */
+
+
+/* logstorage max cache */
+unsigned int g_logstorage_cache_max;
+/* current logstorage cache size */
+unsigned int g_logstorage_cache_size;
+
+typedef struct
+{
+ int offset; /* current write offset */
+ unsigned int wrap_around_cnt; /* wrap around counter */
+}DltLogStorageCacheFooter;
+
typedef struct
{
/* File name user configurations */
@@ -126,14 +144,33 @@ typedef struct DltLogStorageFileList
struct DltLogStorageFileList *next;
}DltLogStorageFileList;
-typedef struct
+typedef struct DltLogStorageConfigData DltLogStorageConfigData;
+
+typedef struct DltLogStorageConfigData
{
/* filter section */
int log_level; /* Log level number configured for filter */
char *file_name; /* File name for log storage configured for filter */
unsigned int file_size; /* MAX File size of storage file configured for filter */
unsigned int num_files; /* MAX number of storage files configured for filters */
+ int sync; /* Sync strategy */
+ /* callback function for filter configurations */
+ int (*dlt_logstorage_prepare)(DltLogStorageConfigData *config,
+ DltLogStorageUserConfig *file_config,
+ char *dev_path,
+ int log_msg_size);
+ int (*dlt_logstorage_write)(DltLogStorageConfigData *config,
+ unsigned char *data1,
+ int size1,
+ unsigned char *data2,
+ int size2,
+ unsigned char *data3,
+ int size3);
+ /* status is strategy, e.g. DLT_LOGSTORAGE_SYNC_ON_MSG is used when callback
+ * is called on message received */
+ int (*dlt_logstorage_sync)(DltLogStorageConfigData *config, int status);
FILE *log; /* current open log file */
+ void *cache; /* log data cache */
DltLogStorageFileList *records; /* File name list */
}DltLogStorageConfigData;
diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior.c b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c
new file mode 100644
index 0000000..77823ee
--- /dev/null
+++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c
@@ -0,0 +1,868 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * DLT offline log storage functionality source file.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2015
+ *
+ * \file: dlt_offline_logstorage_behavior.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#include <syslog.h>
+#include <limits.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "dlt_offline_logstorage.h"
+#include "dlt_offline_logstorage_behavior.h"
+
+/**
+ * dlt_logstorage_log_file_name
+ *
+ * Create log file name in the form configured by the user
+ * <filename><delimiter><index><delimiter><timestamp>.dlt
+ *
+ * filename: given in configuration file
+ * delimiter: Punctuation characters (configured in dlt.conf)
+ * timestamp: yyyy-mm-dd-hh-mm-ss (enabled/disabled in dlt.conf)
+ * index: Index len depends on wrap around value in dlt.conf
+ * ex: wrap around = 99, index will 01..99
+ *
+ * @param log_file_name contains complete logfile name
+ * @param file_config User configurations for log file
+ * @param name file name given in configuration file
+ * @param idx continous index of log files
+ * @ return None
+ */
+void dlt_logstorage_log_file_name(char *log_file_name,
+ DltLogStorageUserConfig *file_config,
+ char *name,
+ int idx)
+{
+ if (log_file_name == NULL || file_config == NULL)
+ {
+ return;
+ }
+
+ char file_index[10] = {'\0'};
+
+ // create log file name
+ memset(log_file_name, 0, DLT_MOUNT_PATH_MAX * sizeof(char));
+ strcat(log_file_name, name);
+ strncat(log_file_name, &file_config->logfile_delimiter, 1);
+
+ snprintf(file_index, 10, "%d",idx);
+ if (file_config->logfile_maxcounter != UINT_MAX)
+ {
+ /* Setup 0's to be appended in file index until max index len*/
+ unsigned int digit_idx = 0;
+ unsigned int i = 0;
+ snprintf(file_index, 10, "%d",idx);
+ digit_idx = strlen(file_index);
+ for(i=0; i<(file_config->logfile_counteridxlen - digit_idx); i++)
+ {
+ strcat(log_file_name, "0");
+ }
+ }
+
+ strcat(log_file_name, file_index);
+
+ /* Add time stamp if user has configured */
+ if (file_config->logfile_timestamp)
+ {
+ char stamp[DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1] = {0};
+ time_t t = time(NULL);
+ struct tm *tm_info = localtime(&t);
+ sprintf(stamp,
+ "%c%04d%02d%02d-%02d%02d%02d",
+ file_config->logfile_delimiter,
+ 1900 + tm_info->tm_year,
+ 1 + tm_info->tm_mon,
+ tm_info->tm_mday,
+ tm_info->tm_hour,
+ tm_info->tm_min,
+ tm_info->tm_sec);
+ strcat(log_file_name, stamp);
+ }
+
+ strcat(log_file_name, ".dlt");
+}
+
+/**
+ * dlt_logstorage_sort_file_name
+ *
+ * Sort the filenames with index based ascending order (bubble sort)
+ *
+ * @param head Log filename list
+ * @ return None
+ */
+void dlt_logstorage_sort_file_name(DltLogStorageFileList **head)
+{
+ int done = 0;
+
+ if (head == NULL || *head == NULL || (*head)->next == NULL)
+ {
+ return;
+ }
+
+ while (!done)
+ {
+ /* "source" of the pointer to the current node in the list struct */
+ DltLogStorageFileList **pv = head;
+ DltLogStorageFileList *nd = *head; /* local iterator pointer */
+ DltLogStorageFileList *nx = (*head)->next; /* local next pointer */
+
+ done = 1;
+
+ while (nx)
+ {
+ if (nd->idx > nx->idx)
+ {
+ nd->next = nx->next;
+ nx->next = nd;
+ *pv = nx;
+
+ done = 0;
+ }
+ pv = &nd->next;
+ nd = nx;
+ nx = nx->next;
+ }
+ }
+}
+
+/**
+ * dlt_logstorage_rearrange_file_name
+ *
+ * Rearrange the filenames in the order of latest and oldest
+ *
+ * @param head Log filename list
+ * @ return None
+ */
+void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head)
+{
+ DltLogStorageFileList *n_prev = NULL;
+ DltLogStorageFileList *tail = NULL;
+ DltLogStorageFileList *wrap_pre = NULL;
+ DltLogStorageFileList *wrap_post = NULL;
+ DltLogStorageFileList *n = NULL;
+
+ if (head == NULL || *head == NULL || (*head)->next == NULL)
+ {
+ return;
+ }
+
+ for (n = *head; n != NULL; n = n->next)
+ {
+ if (n && n_prev)
+ {
+ if ((n->idx - n_prev->idx) != 1)
+ {
+ wrap_post = n;
+ wrap_pre = n_prev;
+ }
+ }
+ n_prev = n;
+ }
+ tail = n_prev;
+
+ if (wrap_post && wrap_pre)
+ {
+ wrap_pre->next = NULL;
+ tail->next = *head;
+ *head = wrap_post;
+ }
+}
+
+/**
+ * dlt_logstorage_get_idx_of_log_file
+ *
+ * Extract index of log file name passed as input argument
+ *
+ * @param file file name to extract the index from
+ * @param file_config User configurations for log file
+ * @return index on success, -1 if no index is found
+ */
+unsigned int dlt_logstorage_get_idx_of_log_file(
+ DltLogStorageUserConfig *file_config,
+ char *file)
+{
+ unsigned int idx = -1;
+ char *endptr;
+ char *filename;
+ unsigned int filename_len = 0 ;
+ unsigned int fileindex_len = 0;
+
+ if (file_config == NULL || file == NULL)
+ {
+ return -1;
+ }
+
+ /* Calculate actual file name length */
+ filename=strchr(file, file_config->logfile_delimiter);
+ filename_len = strlen(file) - strlen(filename);
+
+ /* index is retrived from file name */
+ if(file_config->logfile_timestamp)
+ {
+ fileindex_len = strlen(file) -
+ (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN +
+ DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN +
+ filename_len + 1);
+
+ idx = (int) strtol(&file[strlen(file) -
+ (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN +
+ fileindex_len +
+ DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN)],
+ &endptr,
+ 10);
+ }
+ else
+ {
+ fileindex_len = strlen(file) -
+ (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN +
+ filename_len + 1);
+
+ idx = (int) strtol(&file[strlen(file)-
+ (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN
+ +fileindex_len)], &endptr, 10);
+ }
+
+ if (endptr == file || idx == 0)
+ {
+ dlt_log(LOG_ERR,
+ "Unable to calculate index from log file name. Reset to 001.\n");
+ }
+
+ return idx;
+}
+
+/**
+ * dlt_logstorage_storage_dir_info
+ *
+ * Read file names of storage directory.
+ * Update the file list, arrange it in order of latest and oldest
+ *
+ * @param file_config User configurations for log file
+ * @param path Path to storage directory
+ * @param config DltLogStorageConfigData
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config,
+ char *path,
+ DltLogStorageConfigData *config)
+{
+ int i = 0;
+ int cnt = 0;
+ int ret = 0;
+ struct dirent **files = {0};
+ unsigned int current_idx = 0;
+
+ if (config == NULL ||
+ file_config == NULL ||
+ path == NULL ||
+ config->file_name == NULL)
+ {
+ return -1;
+ }
+
+ cnt = scandir(path, &files, 0, alphasort);
+ if (cnt < 0)
+ {
+ dlt_log(LOG_ERR,
+ "dlt_logstorage_storage_dir_info: Failed to scan directory\n");
+ return -1;
+ }
+
+ for (i = 0; i < cnt; i++)
+ {
+ int len = 0;
+ len = strlen(config->file_name);
+ if ((strncmp(files[i]->d_name,
+ config->file_name,
+ len) == 0) &&
+ (files[i]->d_name[len] == file_config->logfile_delimiter))
+ {
+ DltLogStorageFileList **tmp = NULL;
+ current_idx = dlt_logstorage_get_idx_of_log_file(file_config,
+ files[i]->d_name);
+
+ if(config->records == NULL)
+ {
+ config->records = malloc(sizeof(DltLogStorageFileList));
+ if (config->records == NULL)
+ {
+ ret = -1;
+ dlt_log(LOG_ERR,
+ "Memory allocation failed\n");
+ break;
+ }
+ tmp = &config->records;
+ }
+ else
+ {
+ tmp = &config->records;
+ while(*(tmp) != NULL)
+ {
+ tmp = &(*tmp)->next;
+ }
+ *tmp = malloc(sizeof(DltLogStorageFileList));
+ if (*tmp == NULL)
+ {
+ ret = -1;
+ dlt_log(LOG_ERR,
+ "Memory allocation failed\n");
+ break;
+ }
+ }
+ (*tmp)->name = strdup(files[i]->d_name);
+ (*tmp)->idx = current_idx;
+ (*tmp)->next = NULL;
+ }
+ }
+
+ if (ret == 0)
+ {
+ dlt_logstorage_sort_file_name(&config->records);
+ dlt_logstorage_rearrange_file_name(&config->records);
+ }
+
+ /* free scandir result */
+ for (i = 0; i < cnt; i++)
+ {
+ free(files[i]);
+ }
+ free(files);
+
+ return ret;
+}
+
+/**
+ * dlt_logstorage_open_log_file
+ *
+ * Open a log file. Check storage directory for already created files and open
+ * the oldest if there is enough space to store at least msg_size.
+ * Otherwise create a new file, but take configured max number of files into
+ * account and remove the oldest file if needed.
+ *
+ * @param config DltLogStorageConfigData
+ * @param file_config User configurations for log file
+ * @param dev_path Storage device path
+ * @param msg_size Size of incoming message
+ * @return 0 on succes, -1 on error
+ */
+int dlt_logstorage_open_log_file(DltLogStorageConfigData *config,
+ DltLogStorageUserConfig *file_config,
+ char *dev_path,
+ int msg_size)
+{
+ int ret = 0;
+ char absolute_file_path[DLT_MOUNT_PATH_MAX + 1] = {'\0'};
+ char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN] = {'\0'};
+ unsigned int num_log_files = 0;
+ struct stat s;
+ DltLogStorageFileList **tmp = NULL;
+ DltLogStorageFileList **newest = NULL;
+ char file_name[DLT_MOUNT_PATH_MAX + 1] = {'\0'};
+
+ if (config == NULL)
+ {
+ return -1;
+ }
+
+ sprintf(storage_path, "%s/", dev_path);
+
+ /* check if there are already files stored */
+ if (config->records == NULL)
+ {
+ if (dlt_logstorage_storage_dir_info(file_config, storage_path, config)
+ != 0)
+ return -1;
+ }
+
+ /* obtain locations of newest, current file names, file count */
+ tmp = &config->records;
+ while(*(tmp) != NULL)
+ {
+ num_log_files += 1;
+ if((*tmp)->next == NULL)
+ newest = tmp;
+
+ tmp = &(*tmp)->next;
+ }
+
+ /* need new file*/
+ if (num_log_files == 0)
+ {
+ dlt_logstorage_log_file_name(file_name,
+ file_config,
+ config->file_name,
+ 1);
+
+ /* concatenate path and file and open absolute path */
+ strcat(absolute_file_path, storage_path);
+ strcat(absolute_file_path, file_name);
+ config->log = fopen(absolute_file_path, "a+");
+
+ /* Add file to file list */
+ *tmp = malloc(sizeof(DltLogStorageFileList));
+ if (*tmp == NULL)
+ {
+ dlt_log(LOG_ERR,
+ "Memory allocation for file name failed\n");
+ return -1;
+ }
+ (*tmp)->name = strdup(file_name);
+ (*tmp)->idx = 1;
+ (*tmp)->next = NULL;
+ }
+ else /* newest file available*/
+ {
+ strcat(absolute_file_path, storage_path);
+ strcat(absolute_file_path, (*newest)->name);
+
+ ret = stat(absolute_file_path, &s);
+
+ /* if size is enough, open it */
+ if (ret == 0 && s.st_size + msg_size < (int)config->file_size)
+ {
+ config->log = fopen(absolute_file_path, "a+");
+ }
+ else /* no space in file or file stats cannot be read */
+ {
+ unsigned int idx = 0;
+
+ /* get index of newest log file */
+ idx = dlt_logstorage_get_idx_of_log_file(file_config,
+ (*newest)->name);
+ idx += 1;
+
+ /* wrap around if max index is reached or an error occurred
+ * while calculating index from file name */
+ if (idx > file_config->logfile_maxcounter || idx == 0)
+ {
+ idx = 1;
+ }
+
+ dlt_logstorage_log_file_name(file_name,
+ file_config,
+ config->file_name,
+ idx);
+
+ /* concatenate path and file and open absolute path */
+ memset(absolute_file_path,
+ 0,
+ sizeof(absolute_file_path)/sizeof(char));
+ strcat(absolute_file_path, storage_path);
+ strcat(absolute_file_path, file_name);
+ config->log = fopen(absolute_file_path, "a+");
+
+ /* Add file to file list */
+ *tmp = malloc(sizeof(DltLogStorageFileList));
+ if (*tmp == NULL)
+ {
+ dlt_log(LOG_ERR,
+ "Memory allocation for file name failed\n");
+ return -1;
+ }
+
+ (*tmp)->name = strdup(file_name);
+ (*tmp)->idx = idx;
+ (*tmp)->next = NULL;
+
+ num_log_files += 1;
+
+ /* check if number of log files exceeds configured max value */
+ if (num_log_files > config->num_files)
+ {
+ /* delete oldest */
+ DltLogStorageFileList **head = &config->records;
+ DltLogStorageFileList *n = *head;
+ memset(absolute_file_path,
+ 0,
+ sizeof(absolute_file_path)/sizeof(char));
+ strcat(absolute_file_path, storage_path);
+ strcat(absolute_file_path, (*head)->name);
+ remove(absolute_file_path);
+ free((*head)->name);
+ *head = n->next;
+ n->next = NULL;
+ free(n);
+ }
+ }
+ }
+
+ if (config->log == NULL)
+ {
+ dlt_log(LOG_ERR,
+ "dlt_logstorage_create_log_file: Unable to open log file.\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+/**
+ * dlt_logstorage_prepare_on_msg
+ *
+ * Prepare the log file for a certain filer. If log file not open or log
+ * files max size reached, open a new file.
+ *
+ * @param config DltLogStorageConfigData
+ * @param file_config User configurations for log file
+ * @param dev_path Storage device path
+ * @param log_msg_size Size of log message
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config,
+ DltLogStorageUserConfig *file_config,
+ char *dev_path,
+ int log_msg_size)
+{
+ int ret = 0;
+ struct stat s;
+
+ if (config == NULL || file_config == NULL || dev_path == NULL)
+ {
+ return -1;
+ }
+
+ if (config->log == NULL) /* open a new log file */
+ {
+ ret = dlt_logstorage_open_log_file(config,
+ file_config,
+ dev_path,
+ log_msg_size);
+ }
+ else /* already open, check size and create a new file if needed */
+ {
+ ret = fstat(fileno(config->log), &s);
+ if (ret == 0) {
+ /* check if adding new data do not exceed max file size */
+ if (s.st_size + log_msg_size >= (int)config->file_size)
+ {
+ fclose(config->log);
+ config->log = NULL;
+ ret = dlt_logstorage_open_log_file(config,
+ file_config,
+ dev_path,
+ log_msg_size);
+ }
+ else /*everything is prepared */
+ {
+ ret = 0;
+ }
+ }
+ else
+ {
+ dlt_log(LOG_ERR,
+ "dlt_logstorage_prepare_log_file: stat() failed.\n");
+ ret = -1;
+ }
+ }
+ return ret;
+}
+
+/**
+ * dlt_logstorage_write_on_msg
+ *
+ * Write the log message.
+ *
+ * @param config DltLogStorageConfigData
+ * @param data1 header
+ * @param size1 header size
+ * @param data2 storage header
+ * @param size2 storage header size
+ * @param data3 payload
+ * @param size3 payload size
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_write_on_msg(DltLogStorageConfigData *config,
+ unsigned char *data1,
+ int size1,
+ unsigned char *data2,
+ int size2,
+ unsigned char *data3,
+ int size3)
+{
+ int ret;
+
+ if (config == NULL || data1 == NULL || data2 == NULL || data3 == NULL)
+ {
+ return -1;
+ }
+
+ ret = fwrite(data1, 1, size1, config->log);
+ if (ret != size1)
+ {
+ dlt_log(LOG_WARNING, "Wrote less data than specified\n");
+ }
+ ret = fwrite(data2, 1, size2, config->log);
+ if (ret != size2)
+ {
+ dlt_log(LOG_WARNING, "Wrote less data than specified\n");
+ }
+ ret = fwrite(data3, 1, size3, config->log);
+ if (ret != size3)
+ {
+ dlt_log(LOG_WARNING, "Wrote less data than specified\n");
+ }
+
+ return ferror(config->log);
+}
+
+/**
+ * dlt_logstorage_sync_on_msg
+ *
+ * sync data to disk.
+ *
+ * @param config DltLogStorageConfigData
+ * @param status Strategy flag
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status)
+{
+ int ret;
+
+ if (config == NULL)
+ {
+ return -1;
+ }
+
+ if (status == DLT_LOGSTORAGE_SYNC_ON_MSG) /* sync on every message */
+ {
+ ret = fflush(config->log);
+
+ if (ret != 0)
+ {
+ dlt_log(LOG_ERR, "fflush failed\n");
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * dlt_logstorage_prepare_on_daemon_exit
+ *
+ * Prepare the log file for a certain filer. If log file not open or log
+ * files max size reached, open a new file.
+ * Create a memory area to cache data.
+ *
+ * @param config DltLogStorageConfigData
+ * @param file_config User configurations for log file
+ * @param dev_path Storage device path
+ * @param log_msg_size Size of log message
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_prepare_on_daemon_exit(DltLogStorageConfigData *config,
+ DltLogStorageUserConfig *file_config,
+ char *dev_path,
+ int log_msg_size)
+{
+ if (config == NULL || file_config == NULL || dev_path == NULL)
+ {
+ return -1;
+ }
+
+ log_msg_size = log_msg_size; /* satisfy compiler */
+
+ /* open log file */
+ if (config->cache == NULL)
+ {
+ /* get always a new file */
+ if (dlt_logstorage_prepare_on_msg(config,
+ file_config,
+ dev_path,
+ config->file_size) != 0)
+ {
+ dlt_log(LOG_ERR,
+ "Cannot prepare log file for ON_DAEMON_EXIT sync\n");
+ return -1;
+ }
+
+ /* check total logstorage cache size */
+ if ((g_logstorage_cache_size +
+ config->file_size +
+ sizeof(DltLogStorageCacheFooter)) >
+ g_logstorage_cache_max)
+ {
+ dlt_log(LOG_ERR, "Max size of Logstorage Cache already used.");
+ return -1;
+ }
+
+ config->cache = calloc(1,
+ config->file_size +
+ sizeof(DltLogStorageCacheFooter));
+
+ /* update current used cache size */
+ g_logstorage_cache_size = config->file_size +
+ sizeof(DltLogStorageCacheFooter);
+
+ if (config->cache == NULL)
+ {
+ dlt_log(LOG_CRIT,
+ "Cannot allocate memory for filter ring buffer\n");
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * dlt_logstorage_write_on_daemon_exit
+ *
+ * Write the log message.
+ *
+ * @param config DltLogStorageConfigData
+ * @param data1 header
+ * @param size1 header size
+ * @param data2 storage header
+ * @param size2 storage header size
+ * @param data3 payload
+ * @param size3 payload size
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_write_on_daemon_exit(DltLogStorageConfigData *config,
+ unsigned char *data1,
+ int size1,
+ unsigned char *data2,
+ int size2,
+ unsigned char *data3,
+ int size3)
+{
+ DltLogStorageCacheFooter *footer = NULL;
+ int msg_size;
+ int remain_cache_size;
+ void *curr_write_addr = NULL;
+
+ if (config == NULL || data1 == NULL || size1 < 0 || data2 == NULL ||
+ size2 < 0 || data3 == NULL || size3 < 0 || config->cache == NULL)
+ {
+ return -1;
+ }
+
+ footer = (DltLogStorageCacheFooter *)(config->cache + config->file_size);
+ if (footer == NULL)
+ {
+ dlt_log(LOG_ERR, "Cannot retrieve cache footer. Address is NULL\n");
+ return -1;
+ }
+
+ msg_size = size1 + size2 + size3;
+ remain_cache_size = config->file_size - footer->offset;
+
+ if (msg_size < remain_cache_size) /* add at current position */
+ {
+ curr_write_addr = (void *)(config->cache + footer->offset);
+ footer->offset += msg_size;
+ }
+ else if (msg_size > remain_cache_size)
+ {
+ if ((unsigned int) msg_size > config->file_size)
+ {
+ dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n");
+ return -1;
+ }
+
+ /* start writing from beginning */
+ curr_write_addr = config->cache;
+ footer->offset = msg_size;
+ footer->wrap_around_cnt += 1;
+ }
+ else /* message just fits into cache */
+ {
+ curr_write_addr = (void *)(config->cache + footer->offset);
+ footer->offset = 0;
+ footer->wrap_around_cnt += 1;
+ }
+
+ /* write data to cache */
+ memcpy(curr_write_addr, data1, size1);
+ curr_write_addr += size1;
+ memcpy(curr_write_addr, data2, size2);
+ curr_write_addr += size2;
+ memcpy(curr_write_addr, data3, size3);
+
+ return 0;
+}
+
+/**
+ * dlt_logstorage_sync_on_daemon_exit
+ *
+ * sync data to disk.
+ *
+ * @param config DltLogStorageConfigData
+ * @param status Strategy flag
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_sync_on_daemon_exit(DltLogStorageConfigData *config,
+ int status)
+{
+ int ret = 0;
+ DltLogStorageCacheFooter *footer = NULL;
+
+ if (config == NULL)
+ {
+ return -1;
+ }
+
+ if (status == config->sync) /* only sync on exit */
+ {
+ if (config->log == NULL || config->cache == NULL)
+ {
+ dlt_log(LOG_ERR,
+ "Cannot copy cache to file. One of both is NULL\n");
+ return -1;
+ }
+
+ /* TODO: write only what is needed */
+ /* write ring buffer into file */
+ footer = (DltLogStorageCacheFooter *)(config->cache +
+ config->file_size);
+
+ if (footer == NULL)
+ {
+ dlt_log(LOG_ERR, "Cannot retrieve cache information\n");
+ return -1;
+ }
+
+ /* TODO: check if really the whole cache need to be written */
+ /* write cache to file */
+ ret = fwrite(config->cache, config->file_size, 1, config->log);
+
+ if (ret <= 0)
+ {
+ if (ferror(config->log) != 0)
+ {
+ dlt_log(LOG_CRIT, "Failed to write cache into log file\n");
+ }
+ }
+ else
+ {
+ /* force sync */
+ if (fsync(fileno(config->log)) != 0)
+ {
+ dlt_log(LOG_ERR, "Failed to sync log file\n");
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior.h b/src/offlinelogstorage/dlt_offline_logstorage_behavior.h
new file mode 100644
index 0000000..16394be
--- /dev/null
+++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior.h
@@ -0,0 +1,91 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * DLT offline log storage functionality header file.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ *
+ * \file: dlt_offline_logstorage_behavior.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt_offline_logstorage_behavior.h **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com **
+** **
+** PURPOSE : **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** cl Christoph Lipka ADIT **
+*******************************************************************************/
+
+
+#ifndef DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_
+#define DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_
+
+/* ON_MSG behavior */
+int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config,
+ DltLogStorageUserConfig *file_config,
+ char *dev_path,
+ int log_msg_size);
+int dlt_logstorage_write_on_msg(DltLogStorageConfigData *config,
+ unsigned char *data1,
+ int size1,
+ unsigned char *data2,
+ int size2,
+ unsigned char *data3,
+ int size3);
+
+/* status is strategy, e.g. DLT_LOGSTORAGE_SYNC_ON_MSG is used when callback
+ * is called on message received */
+int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status);
+
+/* ON_DAEMON_EXIT behavior */
+int dlt_logstorage_prepare_on_daemon_exit(DltLogStorageConfigData *config,
+ DltLogStorageUserConfig *file_config,
+ char *dev_path,
+ int log_msg_size);
+
+int dlt_logstorage_write_on_daemon_exit(DltLogStorageConfigData *config,
+ unsigned char *data1,
+ int size1,
+ unsigned char *data2,
+ int size2,
+ unsigned char *data3,
+ int size3);
+
+/* status is strategy, e.g. DLT_LOGSTORAGE_SYNC_ON_MSG is used when callback
+ * is called on message received */
+int dlt_logstorage_sync_on_daemon_exit(DltLogStorageConfigData *config,
+ int status);
+
+#endif /* DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ */