diff options
Diffstat (limited to 'src/offlinelogstorage')
-rw-r--r-- | src/offlinelogstorage/dlt_offline_logstorage.c | 2377 | ||||
-rw-r--r-- | src/offlinelogstorage/dlt_offline_logstorage.h | 141 | ||||
-rw-r--r-- | src/offlinelogstorage/dlt_offline_logstorage_behavior.c | 886 | ||||
-rw-r--r-- | src/offlinelogstorage/dlt_offline_logstorage_behavior.h | 29 |
4 files changed, 2432 insertions, 1001 deletions
diff --git a/src/offlinelogstorage/dlt_offline_logstorage.c b/src/offlinelogstorage/dlt_offline_logstorage.c index 40dc285..b31238e 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage.c +++ b/src/offlinelogstorage/dlt_offline_logstorage.c @@ -37,70 +37,253 @@ #define DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR 1 #define DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR 2 +#define DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE 3 #define GENERAL_BASE_NAME "General" -/* Hash map functions */ -static int dlt_logstorage_hash_create(int num_entries, struct hsearch_data *htab) +typedef struct { + char *key; /* The configuration key */ + int (*func)(DltLogStorage *handle, char *value); /* conf handler */ + int is_opt; /* If configuration is optional or not */ +} DltLogstorageGeneralConf; + +typedef enum { + DLT_LOGSTORAGE_GENERAL_CONF_COUNT = 0 +} DltLogstorageGeneralConfType; + +typedef struct { + char *key; /* Configuration key */ + int (*func)(DltLogStorageFilterConfig *config, char *value); /* conf handler */ + int is_opt; /* If configuration is optional or not */ +} DltLogstorageFilterConf; + +typedef enum { + DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME = 0, + DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME, + DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL, + DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL, + DLT_LOGSTORAGE_FILTER_CONF_FILE, + DLT_LOGSTORAGE_FILTER_CONF_FILESIZE, + DLT_LOGSTORAGE_FILTER_CONF_NOFILES, + DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR, + DLT_LOGSTORAGE_FILTER_CONF_ECUID, + DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE, + DLT_LOGSTORAGE_FILTER_CONF_COUNT +} DltLogstorageFilterConfType; + +STATIC void dlt_logstorage_filter_config_free(DltLogStorageFilterConfig *data) { - memset(htab, 0, sizeof(*htab)); + DltLogStorageFileList *n = NULL; + DltLogStorageFileList *n1 = NULL; - if (hcreate_r(num_entries, htab) == 0) - return -1; + free(data->apids); + data->apids = NULL; + free(data->ctids); + data->ctids = NULL; + free(data->file_name); + data->file_name = NULL; + + if (data->ecuid != NULL) + { + free(data->ecuid); + data->ecuid = NULL; + } + + if (data->log != NULL) + { + fclose(data->log); + } + + if (data->cache != NULL) + { + free(data->cache); + data->cache = NULL; + } + + n = data->records; + + while (n) + { + n1 = n; + n = n->next; + free(n1->name); + n1->name = NULL; + free(n1); + n1 = NULL; + } +} + +STATIC int dlt_logstorage_list_destroy(DltLogStorageFilterList **list, + int reason) +{ + DltLogStorageFilterList *tmp = NULL; + DltLogStorageUserConfig *uconfig = NULL; + char *dev_path = NULL; + + while (*(list) != NULL) + { + tmp = *list; + *list = (*list)->next; + if (tmp->key != NULL) + { + free(tmp->key); + tmp->key = NULL; + } + if (tmp->data != NULL) + { + /* sync data if necessary */ + /* ignore return value */ + tmp->data->dlt_logstorage_sync(tmp->data, + uconfig, + dev_path, + reason); + + dlt_logstorage_filter_config_free(tmp->data); + + free(tmp->data); + tmp->data = NULL; + } + free(tmp); + tmp = NULL; + } return 0; } -static int dlt_logstorage_hash_destroy(struct hsearch_data *htab) +STATIC int dlt_logstorage_list_add_config(DltLogStorageFilterConfig *data, + DltLogStorageFilterConfig **listdata) { - hdestroy_r(htab); + if (*(listdata) == NULL) + { + return -1; + } + + (*listdata)->apids = NULL; + (*listdata)->ctids = NULL; + (*listdata)->file_name = NULL; + (*listdata)->ecuid = NULL; + (*listdata)->records = NULL; + (*listdata)->log = NULL; + (*listdata)->cache = NULL; + + /* copy the data to list */ + memcpy(*listdata, data, sizeof(DltLogStorageFilterConfig)); + + if (data->apids != NULL) + { + (*listdata)->apids = strdup(data->apids); + } + + if (data->ctids != NULL) + { + (*listdata)->ctids = strdup(data->ctids); + } + + if (data->file_name != NULL) + { + (*listdata)->file_name = strdup(data->file_name); + } + + if (data->ecuid != NULL) + { + (*listdata)->ecuid = strdup(data->ecuid); + } return 0; } -static int dlt_logstorage_hash_add(char *key, void *value, struct hsearch_data *htab) +STATIC int dlt_logstorage_list_add(char *key, + DltLogStorageFilterConfig *data, + DltLogStorageFilterList **list) { - ENTRY e, *ep; + DltLogStorageFilterList *tmp = NULL; + + while (*(list) != NULL) + { + /* if the key is already present then the data should be updated */ + if (strncmp((*list)->key, key, DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) == 0) + { + if (dlt_logstorage_list_add_config(data, &((*list)->data)) != 0) + { + return -1; + } + return 0; + } + list = &(*list)->next; + } - memset(&e, 0, sizeof(ENTRY)); - e.key = key; - e.data = value; + tmp = calloc(1, sizeof(DltLogStorageFilterList)); - if (hsearch_r(e, ENTER, &ep, htab) == 0) + if (tmp == NULL) + { return -1; + } + + tmp->key = strdup(key); + tmp->next = NULL; + tmp->data = calloc(1, sizeof(DltLogStorageFilterConfig)); + + if (tmp->data == NULL) + { + free(tmp->key); + free(tmp); + tmp = NULL; + return -1; + } + + if (dlt_logstorage_list_add_config(data, &(tmp->data)) != 0) + { + free(tmp->key); + free(tmp->data); + free(tmp); + tmp = NULL; + return -1; + } + + *list = tmp; return 0; } -static void *dlt_logstorage_hash_find(char *key, struct hsearch_data *htab) +STATIC void *dlt_logstorage_list_find(char *key, + DltLogStorageFilterList **list) { - ENTRY e, *ep; - - e.key = key; + while (*(list) != NULL) + { + if (strncmp((*list)->key, key, DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) == 0) + { + return (*list)->data; + } + else + { + list = &(*list)->next; + } + } - if (hsearch_r(e, FIND, &ep, htab) != 0) - return ep->data; - else - return NULL; + return NULL; } /* Configuration file parsing helper functions */ -int dlt_logstorage_count_ids(const char *str) +STATIC int dlt_logstorage_count_ids(const char *str) { - if(str == NULL) + if (str == NULL) + { return -1; + } // delimiter is: "," const char *p = str; int i = 0; int num = 1; - while(p[i] != 0) + while (p[i] != 0) { if (p[i] == ',') - num += 1; + { + num++; + } i++; } @@ -109,20 +292,42 @@ int dlt_logstorage_count_ids(const char *str) } /** + * dlt_logstorage_free + * + * Free all allocated memory used in log storage handle + * + * @param handle DLT Logstorage handle + * @param reason Reason for freeing the device + * + */ +void dlt_logstorage_free(DltLogStorage *handle, int reason) +{ + if (handle == NULL) + { + dlt_vlog(LOG_ERR, "%s failed: handle is NULL\n", __func__); + return; + } + + dlt_logstorage_list_destroy(&(handle->config_list), reason); +} + + +/** * dlt_logstorage_read_list_of_names * - * Evaluate app and ctx names given in config file and create a list of names acceptable by DLT Daemon - * When using SET_APPLICATION_NAME and SET_CONTEXT_NAME there is no constraint that these names have max - * 4 characters. Internally, these names are cutted down to max 4 chars. To have create valid keys, - * the internal representation of these names has to be considered. - * Therefore, a given configuration of "AppLogName = App1,Application2,A3" will be stored as - * "App1,Appl,A3". + * Evaluate app and ctx names given in config file and create a list of names + * acceptable by DLT Daemon. When using SET_APPLICATION_NAME and SET_CONTEXT_NAME + * there is no constraint that these names have max 4 characters. Internally, + * these names are cutted down to max 4 chars. To have create valid keys, the + * internal representation of these names has to be considered. + * Therefore, a given configuration of "AppLogName = App1,Application2,A3" will + * be stored as "App1,Appl,A3". * * @param names to store the list of names * @param value string given in config file * @return 0 on success, -1 on error */ -int dlt_logstorage_read_list_of_names(char **names, char *value) +STATIC int dlt_logstorage_read_list_of_names(char **names, char *value) { int i = 0; int y = 0; @@ -130,16 +335,16 @@ int dlt_logstorage_read_list_of_names(char **names, char *value) char *tok; int num = 1; - /* free, alloce'd memory sot store new apid/ctid */ - if (*names != NULL) + if ((names == NULL) || (value == NULL)) { - free(*names); - *names = NULL; + return -1; } - if (value == NULL) + /* free, alloce'd memory to store new apid/ctid */ + if (*names != NULL) { - return -1; + free(*names); + *names = NULL; } len = strlen(value); @@ -153,21 +358,28 @@ int dlt_logstorage_read_list_of_names(char **names, char *value) num = dlt_logstorage_count_ids(value); /* need to alloc space for 5 chars, 4 for the name and "," and "\0" */ - *(names) = (char *)calloc(num * 5, sizeof(char)); + *names = (char *)calloc(num * 5, sizeof(char)); + if (*names == NULL) + { + return -1; + } tok = strtok(value, ","); i = 1; + while (tok != NULL) { len = strlen(tok); len = DLT_OFFLINE_LOGSTORAGE_MIN(len, 4); strncpy((*names + y), tok, len); - if (num > 1 && i < num) + + if ((num > 1) && (i < num)) { strncpy((*names + y + len), ",", 1); } + y += len + 1; i++; @@ -178,108 +390,19 @@ int dlt_logstorage_read_list_of_names(char **names, char *value) } /** - * dlt_logstorage_read_log_level - * - * Evaluate log level given in config file and calculate log level as int - * - * @param log_level to store the log level - * @param value string given in config file - * @return 0 on success, -1 on error - */ -int dlt_logstorage_read_log_level(int *log_level, char *value) -{ - if (value == NULL) - { - *log_level = 0; - return -1; - } - - if (strcmp(value, "DLT_LOG_FATAL") == 0) - { - *log_level = 1; - } - else if (strcmp(value, "DLT_LOG_ERROR") == 0) - { - *log_level = 2; - } - else if (strcmp(value, "DLT_LOG_WARN") == 0) - { - *log_level = 3; - } - else if (strcmp(value, "DLT_LOG_INFO") == 0) - { - *log_level = 4; - } - else if (strcmp(value, "DLT_LOG_DEBUG") == 0) - { - *log_level = 5; - } - else if (strcmp(value, "DLT_LOG_VERBOSE") == 0) - { - *log_level = 6; - } - else - { - *log_level = 0; - dlt_log(LOG_ERR, "Invalid log level \n"); - return -1; - } - return 0; -} - -/** - * dlt_logstorage_read_file_name - * - * Evaluate if file name given in config file contains ".." , if not set file name - * - * @param file_name string to store the file name - * @param value string given in config file - * @return 0 on success, -1 on error - */ -int dlt_logstorage_read_file_name(char **file_name, char *value) -{ - int len; - - if (value == NULL || strcmp(value, "") == 0) - { - return -1; - } - - if (*file_name != NULL) - { - *file_name = NULL; - } - - len = strlen(value); - - /* do not allow the user to change directory by adding a path like ../../logfile */ - if (strstr(value, "..") == NULL) - { - *file_name = calloc((len+1), sizeof(char)); - strncpy(*file_name, value, len); - } - else - { - dlt_log(LOG_ERR, "Invalid filename, .. is not accepted due to security issues \n"); - return -1; - } - - return 0; -} - -/** * dlt_logstorage_read_number * * Evaluate file size and number of files given in config file and set file size * The file number is checked by converting a string to an unsigned integer * width 0 > result < UINT_MAX (excludes 0!) - * Non-digit characters including spaces and out of boundary will lead to an error -1. + * Non-digit characters including spaces and out of boundary will lead to an + * error -1. * * @param file_name string to store the file name * @param value string given in config file * @return 0 on success, -1 on error */ -int dlt_logstorage_read_number(unsigned int *number, char *value) +STATIC int dlt_logstorage_read_number(unsigned int *number, char *value) { int i = 0; int len = 0; @@ -294,7 +417,7 @@ int dlt_logstorage_read_number(unsigned int *number, char *value) len = strlen(value); /* check if string consists of digits only */ - for (i = 0; i < len; i++) + for (i = 0 ; i < len ; i++) { if (isdigit(value[i] == 0)) { @@ -305,7 +428,7 @@ int dlt_logstorage_read_number(unsigned int *number, char *value) size = strtoul(value, NULL, 10); - if (size == 0 || size > UINT_MAX) + if ((size == 0) || (size > UINT_MAX)) { dlt_log(LOG_ERR, "Invalid, is not a number \n"); return -1; @@ -317,84 +440,187 @@ int dlt_logstorage_read_number(unsigned int *number, char *value) } /** - * dlt_logstorage_set_sync_strategy + * dlt_logstorage_get_keys_list * - * 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. + * Obtain key list and number of keys for id list passed + * after splitting it between seperator (,) * - * @param file_name int to store the sync strategy - * @param value string given in config file - * @return 0 on success, -1 on error + * @param ids ID's + * @param sep Seperator + * @param list Prepared key list is stored here + * @param numids Number of keys in the list is stored here + * @return: 0 on success, error on failure* */ -int dlt_logstorage_set_sync_strategy(int *strategy, char *value) +STATIC int dlt_logstorage_get_keys_list(char *ids, char *sep, char **list, + int *numids) { - if (value == NULL || strategy == NULL) + char *token = NULL; + char *tmp_token = NULL; + char *ids_local = NULL; + + *numids = 0; + + /* Duplicate the ids passed for using in strtok_r() */ + ids_local = strdup(ids); + if (ids_local == NULL) { return -1; } - if (strcasestr(value, "ON_MSG") != NULL) + token = strtok_r(ids_local, sep, &tmp_token); + if (token == NULL) { - *strategy = DLT_LOGSTORAGE_SYNC_ON_MSG; - dlt_log(LOG_DEBUG, "ON_MSG found, ignore other if added\n"); + free(ids_local); + return -1; } - else /* ON_MSG not set, combination of cache based strategies possible */ + *list = (char *) calloc(DLT_OFFLINE_LOGSTORAGE_MAXIDS * (DLT_ID_SIZE + 1), + sizeof(char)); + if (*(list) == NULL) { - if (strcasestr(value, "ON_DAEMON_EXIT") != NULL) - { - *strategy |= DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT; - } + free(ids_local); + return -1; + } - if (strcasestr(value, "ON_DEMAND") != NULL) + while (token != NULL ) + { + /* If it reached the max then other ids are ignored */ + if (*numids >= DLT_OFFLINE_LOGSTORAGE_MAXIDS) { - *strategy |= DLT_LOGSTORAGE_SYNC_ON_DEMAND; + free(ids_local); + return 0; } + strncpy(((*list) + ((*numids) * (DLT_ID_SIZE + 1))), token, + DLT_ID_SIZE); + *numids = *numids + 1; + token = strtok_r(NULL, sep, &tmp_token); + } + free(ids_local); - if (strcasestr(value, "ON_DEVICE_DISCONNECT") != NULL) - { - *strategy |= DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT; - } + return 0; +} - if (*strategy == 0) - { - dlt_log(LOG_WARNING, "Unknown sync strategies. Set default ON_MSG\n"); - *strategy = DLT_LOGSTORAGE_SYNC_ON_MSG; - } +/** + * dlt_logstorage_create_keys_only_ctid + * + * Prepares keys with context ID alone, will use ecuid if provided + * (ecuid::ctid) or (::ctid) + * + * @param ecuid ECU ID + * @param ctid Context ID + * @param key Prepared key stored here + * @return None + */ +STATIC void dlt_logstorage_create_keys_only_ctid(char *ecuid, char *ctid, + char *key) +{ + char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; + int curr_len = 0; + + if (ecuid != NULL) + { + strncpy(curr_str, ecuid, strlen(ecuid)); + strncat(curr_str, "::", 2); } - return 0; + else + { + strncpy(curr_str, "::", 2); + } + curr_len = strlen(ctid); + strncat(curr_str, ctid, curr_len); + curr_len = strlen(curr_str); + + strncpy(key, curr_str, curr_len); } /** - * dlt_logstorage_set_ecuid + * dlt_logstorage_create_keys_only_apid * - * Evaluate if ECU idenfifier given in config file + * Prepares keys with application ID alone, will use ecuid if provided + * (ecuid:apid::) or (:apid::) * - * @param ecuid string to store the ecuid name - * @param value string given in config file - * @return 0 on success, -1 on error + * @param ecuid ECU ID + * @param apid Application ID + * @param key Prepared key stored here + * @return None */ -int dlt_logstorage_set_ecuid(char **ecuid, char *value) +STATIC void dlt_logstorage_create_keys_only_apid(char *ecuid, char *apid, + char *key) { - int len; + char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; + int curr_len = 0; - if (ecuid == NULL || value == NULL || value[0] == '\0') + if (ecuid != NULL) { - return -1; + strncpy(curr_str, ecuid, strlen(ecuid)); + strncat(curr_str, ":", 1); + } + else + { + strncpy(curr_str, ":", 1); } + curr_len = strlen(apid); + strncat(curr_str, apid, curr_len); + strncat(curr_str, ":", 1); + curr_len = strlen(curr_str); + + strncpy(key, curr_str, curr_len); +} + +/** + * dlt_logstorage_create_keys_multi + * + * Prepares keys with apid, ctid (ecuid:apid:ctid), will use ecuid if is provided + * (ecuid:apid:ctid) or (:apid:ctid) + * + * @param ecuid ECU ID + * @param apid Application ID + * @param ctid Context ID + * @param key Prepared key stored here + * @return None + */ +STATIC void dlt_logstorage_create_keys_multi(char *ecuid, char *apid, + char *ctid, char *key) +{ + char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; + int curr_len = 0; - if (*ecuid != NULL) + if (ecuid != NULL) { - free(*ecuid); - *ecuid = NULL; + strncpy(curr_str, ecuid, strlen(ecuid)); + strncat(curr_str, ":", 1); } + else + { + strncpy(curr_str, ":", 1); + } + curr_len = strlen(apid); + strncat(curr_str, apid, curr_len); + strncat(curr_str, ":", 1); - len = strlen(value); - *ecuid = calloc((len+1), sizeof(char)); - strncpy(*ecuid, value, len); + curr_len = strlen(ctid); + strncat(curr_str, ctid, curr_len); + curr_len = strlen(curr_str); - return 0; + strncpy(key, curr_str, curr_len); +} + +/** + * dlt_logstorage_create_keys_only_ecu + * + * Prepares keys with only ecuid (ecuid::) + * + * @param ecuid ECU ID + * @param key Prepared key stored here + * @return None + */ +STATIC void dlt_logstorage_create_keys_only_ecu(char *ecuid, char *key) +{ + char curr_str[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; + + strncpy(curr_str, ecuid, strlen(ecuid)); + strncat(curr_str, "::", 2); + + strncpy(key, curr_str, strlen(curr_str)); } /** @@ -402,615 +628,964 @@ int dlt_logstorage_set_ecuid(char **ecuid, char *value) * * Create keys for hash table * - * From each section [filter] in offline logstorage configuration file, we receive - * application and context id strings. + * From each section [filter] in offline logstorage configuration file, we + * receive application and context id strings. * Application and context id can consist of * - a 4char long name * - a comma separated list of ids * - a wildcard: .* * - * Not allowed is the combination of application id and context id set to wildcard. This - * will be rejected. + * Not allowed is the combination of application id and context id set to + * wildcard. This will be rejected. * - * If lists given for application and/or context id, all possible combinations are - * returned as keys in a form "[appid][ctxid], e.g. "APP1:CTX1". If wildcards are used, - * the non-wildcard value becomes the key, e.g. "APP1:" or ":CTX2". + * If lists given for application and/or context id, all possible combinations + * are returned as keys in a form "[apid][ctid], e.g. "APP1:CTX1". + * If wildcards are used, the non-wildcard value becomes the key, e.g. "APP1:" + * or ":CTX2". * - * @param[in]: appids: string given from filter configuration - * @param[in]: ctxids: string given from filter configuration + * @param[in]: apids: string given from filter configuration + * @param[in]: ctids: string given from filter configuration + * @param[in]: ecuid: string given from filter configuration * @param[out]: keys: keys to fill into hash table * @param[out]: num_keys: number of keys * @return: 0 on success, error on failure* */ -int dlt_logstorage_create_keys(char *appids, char* ctxids, char **keys, int *num_keys) +STATIC int dlt_logstorage_create_keys(char *apids, + char *ctids, + char *ecuid, + char **keys, + int *num_keys) { - int i,j; - int curr_key = 0; - int curr_len = 0; - int num_appids = 0; - int num_ctxids = 0; - char *aids = NULL; - char *cids = NULL; - char *save_aids = NULL; - char *save_cids = NULL; - - if ((*keys) != NULL) - { - free((*keys)); - (*keys) = NULL; + int i, j; + int num_apids = 0; + int num_ctids = 0; + char *apid_list = NULL; + char *ctid_list = NULL; + char *curr_apid = NULL; + char *curr_ctid = NULL; + char curr_key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = { 0 }; + int num_currkey = 0; + + /* Handle ecuid alone case here */ + if ((apids == NULL) && (ctids == NULL) && (ecuid != NULL)) + { + dlt_logstorage_create_keys_only_ecu(ecuid, curr_key); + *(num_keys) = 1; + *(keys) = (char *) calloc(*num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN, + sizeof(char)); + if (*(keys) == NULL) + { + return -1; + } + strncpy(*keys, curr_key, strlen(curr_key)); + return 0; } - *num_keys = 0; - - if (appids == NULL || ctxids == NULL) + if ((apids == NULL) || (ctids == NULL)) + { + dlt_log(LOG_ERR,"Required inputs (apid and ctid) are NULL\n"); return -1; + } - /* discard appid=.* and ctxid=.* */ - if ( strncmp(appids, ".*", 2) == 0 && strncmp(ctxids, ".*", 2) == 0 ) + /* obtain key list and number of keys for application ids */ + if (dlt_logstorage_get_keys_list(apids, ",", &apid_list, &num_apids) != 0) { - dlt_log(LOG_ERR,"Error: Not allowed combination of wildcards\n"); + dlt_log(LOG_ERR, "Failed to obtain appid, check configuration file \n"); return -1; } - - aids = strdup(appids); - - cids = (char *) calloc(strlen(ctxids)+1, sizeof(char)); - if (cids == NULL) + /* obtain key list and number of keys for context ids */ + if (dlt_logstorage_get_keys_list(ctids, ",", &ctid_list, &num_ctids) != 0) { - free(aids); + dlt_log(LOG_ERR, "Failed to obtain ctid, check configuration file \n"); + free(apid_list); return -1; } - /* calculate number of keys */ - num_appids = dlt_logstorage_count_ids(appids); - num_ctxids = dlt_logstorage_count_ids(ctxids); - *(num_keys) = num_appids * num_ctxids; + *(num_keys) = num_apids * num_ctids; - /* alloc needed number of keys */ - *(keys) = (char*) calloc(*num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN, sizeof(char)); + /* allocate memory for needed number of keys */ + *(keys) = (char *) calloc(*num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN, + sizeof(char)); if (*(keys) == NULL) { - free(aids); - free(cids); + free(apid_list); + free(ctid_list); return -1; } - /* store all combinations of appid:ctxid in keys */ - for (i = 1; i <= num_appids; i++) + /* store all combinations of apid ctid in keys */ + for (i = 0; i < num_apids; i++) { - char *tok_aids = NULL; - char *tok_cids = NULL; - - if (num_appids > 1 && i == 1) - { - tok_aids = strtok_r(aids,",", &save_aids); - } - else if (num_appids > 1 && i > 0) - { - tok_aids = strtok_r(NULL, ",", &save_aids); - } - else + curr_apid = apid_list + (i * (DLT_ID_SIZE + 1)); + for (j = 0; j < num_ctids; j++) { - tok_aids = aids; - } - - for (j = 1; j <= num_ctxids; j++) - { - if (num_ctxids > 1 && j == 1) + curr_ctid = ctid_list + (j * (DLT_ID_SIZE + 1)); + if (strncmp(curr_apid, ".*", 2) == 0) /* only context id matters */ { - save_cids = NULL; - memcpy(cids, ctxids, strlen(ctxids)); - tok_cids = strtok_r(cids, ",", &save_cids); + dlt_logstorage_create_keys_only_ctid(ecuid, curr_ctid, curr_key); } - else if (num_ctxids > 1 && j > 0) + else if (strncmp(curr_ctid, ".*", 2) == 0) /* only app id matters*/ { - tok_cids = strtok_r(NULL, ",", &save_cids); + dlt_logstorage_create_keys_only_apid(ecuid, curr_apid, curr_key); } - else - { - tok_cids = ctxids; - } - - if (strncmp(tok_aids, ".*", 2) == 0) /* only context id matters */ + else /* key is combination of all */ { - char curr_str[10] = { 0 }; - strncpy(curr_str, ":", 1); - curr_len = strlen(tok_cids); - strncat(curr_str, tok_cids, curr_len); - curr_len = strlen(curr_str); - strncpy((*keys + (curr_key * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), curr_str, curr_len); + dlt_logstorage_create_keys_multi(ecuid, curr_apid, curr_ctid, curr_key); } - else if (strncmp(tok_cids,".*", 2) == 0) /* only application id matters*/ - { - char curr_str[10] = { 0 }; - curr_len = strlen(tok_aids); - strncpy(curr_str, tok_aids, curr_len); - strncat(curr_str, ":", 1); - curr_len = strlen(curr_str); - strncpy((*keys + (curr_key * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), curr_str, curr_len); - } - else /* key is combination of both */ - { - char curr_str[10] = { 0 }; - curr_len = strlen(tok_aids); - strncpy(curr_str, tok_aids, curr_len); - strncat(curr_str, ":", 1); - curr_len = strlen(tok_cids); - strncat(curr_str, tok_cids, curr_len); - curr_len = strlen(curr_str); - strncpy((*keys + (curr_key * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), curr_str, curr_len); - } - curr_key += 1; + strncpy((*keys + (num_currkey * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)), + curr_key, strlen(curr_key)); + num_currkey += 1; + memset(&curr_key[0], 0, sizeof(curr_key)); } } - free(aids); - free(cids); + free(apid_list); + free(ctid_list); return 0; } /** - * dlt_logstorage_device_connected + * dlt_logstorage_prepare_table * - * Initializes DLT Offline Logstorage with respect to device status + * Prepares hash table with keys and data * * @param handle DLT Logstorage handle - * @param mount_point Device mount path + * @param tmp_data Holds all other configuration values * @return 0 on success, -1 on error */ -int dlt_logstorage_device_connected(DltLogStorage *handle, char *mount_point) +STATIC int dlt_logstorage_prepare_table(DltLogStorage *handle, + DltLogStorageFilterConfig *data) { - if((handle == NULL) || (mount_point == NULL)) + int ret = 0; + int num_keys = 0; + char *keys = NULL; + int idx = 0; + + if ((handle == NULL) || (data == NULL)) { - dlt_log(LOG_ERR, "dlt_logstorage_device_connected Error : Handle error \n"); + dlt_vlog(LOG_ERR, "Invalid parameters in %s\n", __func__); return -1; } - if(handle->connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) - { - dlt_log(LOG_ERR, "dlt_logstorage_device_connected Error : Device already connected, \n"); - dlt_log(LOG_ERR, "Send disconnect, connect request \n"); + ret = dlt_logstorage_create_keys(data->apids, + data->ctids, + data->ecuid, + &keys, + &num_keys); - dlt_logstorage_device_disconnected( - handle, - DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); + if (ret != 0) + { + dlt_log(LOG_ERR, "Not able to create keys for hash table\n"); + return -1; } - strncpy(handle->device_mount_point,mount_point,DLT_MOUNT_PATH_MAX); - handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; - handle->config_status = 0; - handle->write_errors = 0; - handle->num_filter_keys = 0; + /* hash_add */ + for (idx = 0 ; idx < num_keys ; idx++) + { + if (dlt_logstorage_list_add(keys + (idx * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN), + data, + &(handle->config_list)) != 0) + { + dlt_log(LOG_ERR, + "Adding to hash table failed, returning failure\n"); + + dlt_logstorage_free(handle, DLT_LOGSTORAGE_SYNC_ON_ERROR); + + free(keys); + return -1; + } - handle->config_data = NULL; - handle->filter_keys = NULL; + /* update filter keys and number of keys */ + handle->num_filter_keys += 1; + } + free(keys); return 0; } /** - * dlt_logstorage_free + * dlt_logstorage_validate_filter_name * - * Free all allocated memory used in log storage handle + * Validates if the provided filter name is as required [FILTER<number>] * - * @param handle DLT Logstorage handle - * @param reason Reason for freeing the device + * @param name Filter name + * @return 0 on success, -1 on error * */ -void dlt_logstorage_free(DltLogStorage *handle, int reason) +STATIC int dlt_logstorage_validate_filter_name(char *name) { - int i=0; - - dlt_logstorage_hash_destroy(&(handle->config_htab)); + int len = 0; + int idx = 0; + int config_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION); + int storage_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION); + int control_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION); - for(i=0; i<handle->num_filter_keys; i++) + if (name == NULL) { - /* sync data if necessary */ - /* ignore return value */ - handle->config_data[i].data.dlt_logstorage_sync( - &(handle->config_data[i].data), - reason); - - free(handle->config_data[i].data.file_name); + return -1; + } - if (handle->config_data[i].data.ecuid != NULL) + len = strlen(name); + + /* Check if section header is of format "FILTER" followed by a number */ + if (strncmp(name, + DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION, + config_sec_len) == 0) + { + for (idx = config_sec_len; idx < len - 1; idx++) { - free(handle->config_data[i].data.ecuid); + if (!isdigit(name[idx])) + { + return -1; + } } - - if (handle->config_data[i].data.log != NULL) + return 0; + } + /* Check if section header is of format "FILTER" followed by a number */ + else if (strncmp(name, + DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION, + storage_sec_len) == 0) + { + for (idx = storage_sec_len; idx < len - 1; idx++) { - fclose(handle->config_data[i].data.log); + if (!isdigit(name[idx])) + { + return -1; + } } - - if (handle->config_data[i].data.cache != NULL) + return 0; + } + /* Check if section header is of format "FILTER" followed by a number */ + else if (strncmp(name, + DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION, + control_sec_len) == 0) + { + for (idx = control_sec_len; idx < len - 1; idx++) { - free(handle->config_data[i].data.cache); + if (!isdigit(name[idx])) + { + return -1; + } } + return 0; + } + else + { + return -1; + } +} - DltLogStorageFileList *n = handle->config_data[i].data.records; - while(n) - { - DltLogStorageFileList *n1 = n; - n = n->next; - free(n1->name); - free(n1); - } +STATIC void dlt_logstorage_filter_set_strategy(DltLogStorageFilterConfig *config, + int strategy) +{ + if (config == NULL) + { + return; } - free(handle->config_data); - handle->config_data = NULL; + /* file based */ + if ((strategy == DLT_LOGSTORAGE_SYNC_ON_MSG) || + (strategy == DLT_LOGSTORAGE_SYNC_UNSET)) + { + 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; + } + else /* cache based */ + { + config->dlt_logstorage_prepare = &dlt_logstorage_prepare_msg_cache; + config->dlt_logstorage_write = &dlt_logstorage_write_msg_cache; + config->dlt_logstorage_sync = &dlt_logstorage_sync_msg_cache; + } +} + +STATIC int dlt_logstorage_check_apids(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + { + dlt_log(LOG_ERR, "Not able to create keys for hash table\n"); + return -1; + } - free(handle->filter_keys); - handle->filter_keys = NULL; + return dlt_logstorage_read_list_of_names(&config->apids, value); } +STATIC int dlt_logstorage_check_ctids(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + { + return -1; + } -/** - * dlt_logstorage_device_disconnected - * - * De-Initializes DLT Offline Logstorage with respect to device status - * - * @param handle DLT Logstorage handle - * @param reason Reason for disconnect - * @return 0 on success, -1 on error - * - */ -int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason) + return dlt_logstorage_read_list_of_names(&config->ctids, value); +} + +STATIC int dlt_logstorage_check_loglevel(DltLogStorageFilterConfig *config, + char *value) { - if (handle == NULL) + if ((config == NULL) || (value == NULL)) + { return -1; + } - /* If configuration loading was done, free it */ - if (handle->config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) + if (value == NULL) { - dlt_logstorage_free(handle, reason); + config->log_level = 0; + return -1; } - /* Reset all device status */ - memset(handle->device_mount_point,'\0', sizeof(char) * DLT_MOUNT_PATH_MAX); - handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED; - handle->config_status = 0; - handle->write_errors = 0; - handle->num_filter_keys = 0; + if (strcmp(value, "DLT_LOG_FATAL") == 0) + { + config->log_level = 1; + } + else if (strcmp(value, "DLT_LOG_ERROR") == 0) + { + config->log_level = 2; + } + else if (strcmp(value, "DLT_LOG_WARN") == 0) + { + config->log_level = 3; + } + else if (strcmp(value, "DLT_LOG_INFO") == 0) + { + config->log_level = 4; + } + else if (strcmp(value, "DLT_LOG_DEBUG") == 0) + { + config->log_level = 5; + } + else if (strcmp(value, "DLT_LOG_VERBOSE") == 0) + { + config->log_level = 6; + } + else + { + config->log_level = -1; + dlt_log(LOG_ERR, "Invalid log level \n"); + return -1; + } return 0; } -/** - * dlt_logstorage_prepare_table - * - * Prepares hash table with keys and data - * - * @param handle DLT Logstorage handle - * @param appid Application ID value provided in configuration file - * @param appid Context ID value provided in configuration file - * @param tmp_data Holds all other configuration values - * @return 0 on success, -1 on error - * - */ -int dlt_logstorage_prepare_table(DltLogStorage *handle, char *appid, char *ctxid, DltLogStorageConfigData *tmp_data) +STATIC int dlt_logstorage_check_reset_loglevel(DltLogStorageFilterConfig *config, + char *value) { - int ret = 0; - int num_keys = 0; - char *keys = NULL; - int idx = 0; + if (config == NULL) + { + return -1; + } - /* Allocate memory for filters */ - if(handle->config_data == NULL) + if (value == NULL) { - handle->config_data = malloc(sizeof(DltLogStorageConfig) * DLT_OFFLINE_LOGSTORAGE_MAXFILTERS); - memset(handle->config_data, 0, (sizeof(DltLogStorageConfig) * DLT_OFFLINE_LOGSTORAGE_MAXFILTERS)); + config->reset_log_level = 0; + return -1; + } - handle->filter_keys = malloc(sizeof(char) * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN * DLT_OFFLINE_LOGSTORAGE_MAXFILTERS); - memset(handle->filter_keys, 0, sizeof(char) * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN * DLT_OFFLINE_LOGSTORAGE_MAXFILTERS); + if (strcmp(value, "DLT_LOG_OFF") == 0) + { + config->reset_log_level = DLT_LOG_OFF; + } + else if (strcmp(value, "DLT_LOG_FATAL") == 0) + { + config->reset_log_level = DLT_LOG_FATAL; + } + else if (strcmp(value, "DLT_LOG_ERROR") == 0) + { + config->reset_log_level = DLT_LOG_ERROR; + } + else if (strcmp(value, "DLT_LOG_WARN") == 0) + { + config->reset_log_level = DLT_LOG_WARN; + } + else if (strcmp(value, "DLT_LOG_INFO") == 0) + { + config->reset_log_level = DLT_LOG_INFO; + } + else if (strcmp(value, "DLT_LOG_DEBUG") == 0) + { + config->reset_log_level = DLT_LOG_DEBUG; + } + else if (strcmp(value, "DLT_LOG_VERBOSE") == 0) + { + config->reset_log_level = DLT_LOG_VERBOSE; + } + else + { + config->reset_log_level = -1; + dlt_log(LOG_ERR, "Invalid log level \n"); + return -1; } - ret = dlt_logstorage_create_keys(appid, ctxid, &keys, &num_keys); - if (ret != 0) + return 0; +} + +STATIC int dlt_logstorage_check_filename(DltLogStorageFilterConfig *config, + char *value) +{ + int len; + + if ((value == NULL) || (strcmp(value, "") == 0)) { - dlt_log(LOG_ERR, "Not able to create keys for hash table\n"); return -1; } - /* hash_add */ - for (idx=0; idx<num_keys; idx++) + if (config->file_name != NULL) { - DltLogStorageConfig *p_node = NULL; + free(config->file_name); + config->file_name = NULL; + } - if (num_keys > (DLT_OFFLINE_LOGSTORAGE_MAXFILTERS - handle->num_filter_keys)) + len = strlen(value); + + /* do not allow the user to change directory by adding a relative path */ + if (strstr(value, "..") == NULL) + { + config->file_name = calloc((len + 1), sizeof(char)); + if (config->file_name == NULL) { - dlt_log(LOG_ERR, "MAX filters reached \n"); - break; + dlt_log(LOG_ERR, + "Cannot allocate memory for filename\n"); + return -1; } + strncpy(config->file_name, value, len); + } + else + { + dlt_log(LOG_ERR, + "Invalid filename, paths not accepted due to security issues\n"); + return -1; + } + + return 0; +} - p_node = &(handle->config_data[handle->num_filter_keys]); +STATIC int dlt_logstorage_check_filesize(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + { + return -1; + } + + return dlt_logstorage_read_number(&config->file_size, value); +} + +STATIC int dlt_logstorage_check_nofiles(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + { + return -1; + } - strcpy(p_node->key, keys+(idx * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN)); - memcpy(&p_node->data, tmp_data, sizeof(DltLogStorageConfigData)); - p_node->data.file_name = strdup(tmp_data->file_name); - if (tmp_data->ecuid != NULL) + return dlt_logstorage_read_number(&config->num_files, value); +} + +STATIC int dlt_logstorage_check_specificsize(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + { + return -1; + } + return dlt_logstorage_read_number(&config->specific_size, value); +} + +/** + * dlt_logstorage_check_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 config DltLogStorageFilterConfig + * @param value string given in config file + * @return 0 on success, -1 on error + */ +STATIC int dlt_logstorage_check_sync_strategy(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + { + return -1; + } + + if (strcasestr(value, "ON_MSG") != NULL) + { + config->sync = DLT_LOGSTORAGE_SYNC_ON_MSG; + dlt_log(LOG_DEBUG, "ON_MSG found, ignore other if added\n"); + } + else /* ON_MSG not set, combination of cache based strategies possible */ + { + if (strcasestr(value, "ON_DAEMON_EXIT") != NULL) { - p_node->data.ecuid = strdup(tmp_data->ecuid); + config->sync |= DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT; } - else + + if (strcasestr(value, "ON_DEMAND") != NULL) { - p_node->data.ecuid = NULL; + config->sync |= DLT_LOGSTORAGE_SYNC_ON_DEMAND; } - 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) + if (strcasestr(value, "ON_DEVICE_DISCONNECT") != NULL) { - dlt_log(LOG_ERR, "Adding to hash table failed, returning failure\n"); + config->sync |= DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT; + } - dlt_logstorage_free(handle, DLT_LOGSTORAGE_SYNC_ON_ERROR); + if (strcasestr(value, "ON_SPECIFIC_SIZE") != NULL) + { + config->sync |= DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE; + } - free(keys); - return -1; + if (strcasestr(value, "ON_FILE_SIZE") != NULL) + { + config->sync |= DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE; + } + + if (config->sync == 0) + { + dlt_log(LOG_WARNING, + "Unknown sync strategies. Set default ON_MSG\n"); + config->sync = DLT_LOGSTORAGE_SYNC_ON_MSG; + return 1; } - /* update filter keys and number of keys */ - strncat(handle->filter_keys + handle->num_filter_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN, keys, strlen(keys)); - handle->num_filter_keys += 1; } - free(keys); + return 0; } /** - * dlt_logstorage_validate_filter_value + * dlt_logstorage_check_ecuid * - * This function analyzes the filter values - * and stores the values into provided input arguments - * Here appid and ctxid are used to hold application name and context name - * values provided in configuration file, all other configuration values - * are stored in tmp_data - * the caller can utilize the return values of this - * function to know when a complete filter set is read - * - * @param filter_key Filter key read from configuration file - * @param filter_value Filter value read from configuration file - * @param appid Application ID value provided in configuration file - * @param ctxid Context ID value provided in configuration file - * @param tmp_data Holds all other configuration values - * @return Configuration value type on success, -1 on error + * Evaluate if ECU idenfifier given in config file * + * @param config DltLogStorageFilterConfig + * @param value string given in config file + * @return 0 on success, -1 on error */ -int dlt_logstorage_validate_filter_value(char *filter_key, char *filter_value, - char **appid, char **ctxid, - DltLogStorageConfigData *tmp_data) +STATIC int dlt_logstorage_check_ecuid(DltLogStorageFilterConfig *config, + char *value) { - int ret = -1; + int len; - if (strncmp(filter_key, "LogAppName", strlen("LogAppName")) == 0) - { - ret = dlt_logstorage_read_list_of_names(appid, filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_APP_INIT; - } - else if (strncmp(filter_key, "ContextName", strlen("ContextName")) == 0) - { - ret = dlt_logstorage_read_list_of_names(ctxid, filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_CTX_INIT; - } - else if (strncmp(filter_key, "LogLevel", strlen("LogLevel")) == 0) + if ((config == NULL) || (value == NULL) || (value[0] == '\0')) { - ret = dlt_logstorage_read_log_level(&(tmp_data->log_level), filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_LOG_LVL_INIT; - } - else if (strncmp(filter_key, "FileSize", strlen("FileSize")) == 0) - { - ret = dlt_logstorage_read_number(&(tmp_data->file_size), filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_SIZE_INIT; - } - else if (strncmp(filter_key, "File", strlen("File")) == 0) - { - ret = dlt_logstorage_read_file_name(&(tmp_data->file_name), filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_NAME_INIT; - } - else if (strncmp(filter_key, "NOFiles", strlen("NOFiles")) == 0) - { - ret = dlt_logstorage_read_number(&(tmp_data->num_files), 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; - } + return -1; } - else if (strncmp(filter_key, "EcuID", strlen("EcuID")) == 0) + + if (config->ecuid != NULL) { - ret = dlt_logstorage_set_ecuid(&(tmp_data->ecuid), filter_value); - if (ret == 0) - { - return DLT_OFFLINE_LOGSTORAGE_ECUID; - } + free(config->ecuid); + config->ecuid = NULL; } - else + + len = strlen(value); + config->ecuid = calloc((len + 1), sizeof(char)); + if (config->ecuid == NULL) { - /* Invalid filter key */ - ret = -1; - dlt_log(LOG_ERR, "Invalid filter key"); + return -1; } + strncpy(config->ecuid, value, len); - if (ret == -1) - dlt_log(LOG_ERR, "Error in configuration file\n"); - - return ret; + return 0; } +STATIC DltLogstorageFilterConf + filter_cfg_entries[DLT_LOGSTORAGE_FILTER_CONF_COUNT] = { + [DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME] = { + .key = "LogAppName", + .func = dlt_logstorage_check_apids, + .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME] = { + .key = "ContextName", + .func = dlt_logstorage_check_ctids, + .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL] = { + .key = "LogLevel", + .func = dlt_logstorage_check_loglevel, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL] = { + .key = NULL, + .func = dlt_logstorage_check_reset_loglevel, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_FILE] = { + .key = "File", + .func = dlt_logstorage_check_filename, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_FILESIZE] = { + .key = "FileSize", + .func = dlt_logstorage_check_filesize, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_NOFILES] = { + .key = "NOFiles", + .func = dlt_logstorage_check_nofiles, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR] = { + .key = "SyncBehavior", + .func = dlt_logstorage_check_sync_strategy, + .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { + .key = "EcuID", + .func = dlt_logstorage_check_ecuid, + .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE] = { + .key = "SpecificSize", + .func = dlt_logstorage_check_specificsize, + .is_opt = 1 + } +}; + +/* */ +STATIC DltLogstorageFilterConf + filter_nonverbose_storage_entries[DLT_LOGSTORAGE_FILTER_CONF_COUNT] = { + [DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME] = { + .key = NULL, + .func = dlt_logstorage_check_apids, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME] = { + .key = NULL, + .func = dlt_logstorage_check_ctids, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL] = { + .key = NULL, + .func = dlt_logstorage_check_loglevel, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL] = { + .key = NULL, + .func = NULL, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_FILE] = { + .key = "File", + .func = dlt_logstorage_check_filename, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_FILESIZE] = { + .key = "FileSize", + .func = dlt_logstorage_check_filesize, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_NOFILES] = { + .key = "NOFiles", + .func = dlt_logstorage_check_nofiles, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR] = { + .key = NULL, + .func = dlt_logstorage_check_sync_strategy, + .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { + .key = "EcuID", + .func = dlt_logstorage_check_ecuid, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE] = { + .key = NULL, + .func = dlt_logstorage_check_specificsize, + .is_opt = 1 + } +}; + +STATIC DltLogstorageFilterConf +filter_nonverbose_control_entries[DLT_LOGSTORAGE_FILTER_CONF_COUNT] = { + [DLT_LOGSTORAGE_FILTER_CONF_LOGAPPNAME] = { + .key = "LogAppName", + .func = dlt_logstorage_check_apids, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_CONTEXTNAME] = { + .key = "ContextName", + .func = dlt_logstorage_check_ctids, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_LOGLEVEL] = { + .key = "LogLevel", + .func = dlt_logstorage_check_loglevel, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_RESET_LOGLEVEL] = { + .key = "ResetLogLevel", + .func = dlt_logstorage_check_reset_loglevel, + .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_FILE] = { + .key = NULL, + .func = dlt_logstorage_check_filename, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_FILESIZE] = { + .key = NULL, + .func = dlt_logstorage_check_filesize, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_NOFILES] = { + .key = NULL, + .func = dlt_logstorage_check_nofiles, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR] = { + .key = NULL, + .func = dlt_logstorage_check_sync_strategy, + .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { + .key = "EcuID", + .func = dlt_logstorage_check_ecuid, + .is_opt = 0 + }, + [DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE] = { + .key = NULL, + .func = dlt_logstorage_check_specificsize, + .is_opt = 1 + } +}; /** - * dlt_logstorage_validate_filter_name - * - * Validates if the provided filter name is as required [FILTER<number>] - * - * @param name Filter name - * @return 0 on success, -1 on error + * Check filter configuration parameter is valid. * + * @param config DltLogStorageFilterConfig + * @param ctype DltLogstorageFilterConfType + * @param value specified property value from configuration file + * @return 0 on success, -1 otherwise */ -int dlt_logstorage_validate_filter_name(char *name) +STATIC int dlt_logstorage_check_param(DltLogStorageFilterConfig *config, + DltLogstorageFilterConfType ctype, + char *value) { - int len = 0; - int idx = 0; - - if (name == NULL) + if ((config == NULL) || (value == NULL)) { return -1; } - len = strlen(name); + if (ctype < DLT_LOGSTORAGE_FILTER_CONF_COUNT) + { + return filter_cfg_entries[ctype].func(config, value); + } - /* Check if section header is of format "FILTER" followed by a number */ - if (strncmp(name, + return -1; +} + + +STATIC int dlt_logstorage_get_filter_value(DltConfigFile *config_file, + char *sec_name, + int index, + char *value) +{ + int ret = 0; + int config_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION); + int storage_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION); + int control_sec_len = strlen(DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION); + + if ((config_file == NULL) || (sec_name == NULL)) + { + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; + } + + /* Branch based on section name, no complete string compare needed */ + if (strncmp(sec_name, DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION, - strlen(DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION)) == 0) + config_sec_len) == 0) { - for (idx=6; idx<len-1; idx++) + if (filter_cfg_entries[index].key != NULL) { - if (!isdigit(name[idx])) + ret = dlt_config_file_get_value(config_file, sec_name, + filter_cfg_entries[index].key, + value); + + if ((ret != 0) && (filter_cfg_entries[index].is_opt == 0)) { - return -1; + dlt_vlog(LOG_WARNING, + "Invalid configuration in section: %s -> %s : %s\n", + sec_name, filter_cfg_entries[index].key, value); + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; + } + + if ((ret != 0) && (filter_cfg_entries[index].is_opt == 1)) + { + dlt_vlog(LOG_DEBUG, "Optional parameter %s not specified\n", + filter_cfg_entries[index].key); + return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; } } - return 0; + else + { + return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; + } } - return -1; -} - -void dlt_logstorage_filter_set_strategy(DltLogStorageConfigData *config, - int strategy) -{ - if (config == NULL) + else if (strncmp(sec_name, + DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION, + storage_sec_len) == 0) { - return; + if (filter_nonverbose_storage_entries[index].key != NULL) + { + if (dlt_config_file_get_value(config_file, sec_name, + filter_nonverbose_storage_entries[index].key, value) != 0) + { + dlt_vlog(LOG_WARNING, + "Invalid configuration in section: %s -> %s : %s\n", + sec_name, filter_nonverbose_storage_entries[index].key, + value); + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; + } + } + else + { + return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; + } } - - if (strategy == DLT_LOGSTORAGE_SYNC_ON_MSG) /* file based */ + else if ((strncmp(sec_name, + DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION, + control_sec_len) == 0)) { - 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; + if (filter_nonverbose_control_entries[index].key != NULL) + { + if (dlt_config_file_get_value(config_file, sec_name, + filter_nonverbose_control_entries[index].key, value) != 0) + { + dlt_vlog(LOG_WARNING, + "Invalid configuration in section: %s -> %s : %s\n", + sec_name, filter_nonverbose_control_entries[index].key, + value); + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; + } + } + else + { + return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; + } } - else /* cache based */ + else { - config->dlt_logstorage_prepare = &dlt_logstorage_prepare_msg_cache; - config->dlt_logstorage_write = &dlt_logstorage_write_msg_cache; - config->dlt_logstorage_sync = &dlt_logstorage_sync_msg_cache; + dlt_log(LOG_ERR, "Error: Section name not valid \n"); + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; } + + return 0; } +STATIC int dlt_logstorage_setup_table(DltLogStorage *handle, + DltLogStorageFilterConfig *tmp_data) +{ + int ret = 0; + + /* 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, tmp_data); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s Error: Storing filter values failed\n", + __func__); + ret = DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR; + } + + return ret; +} /*Return : -DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR - On filter properties or value is not valid -DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR - On error while storing in hash table -*/ + DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR - On filter properties or value is not valid + DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR - On error while storing in hash table + */ -int dlt_daemon_setup_filter_properties(DltLogStorage *handle, DltConfigFile *config_file, char *sec_name) +STATIC int dlt_daemon_offline_setup_filter_properties(DltLogStorage *handle, + DltConfigFile *config_file, + char *sec_name) { - /* Read and store filters */ - int j = 0; - int ret = -1; - int is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT; - char *appid = NULL; - char *ctxid = NULL; - DltLogStorageConfigData tmp_data; - int num_filter_keys = DLT_OFFLINE_LOGSTORAGE_MAX_KEY_NUM; + DltLogStorageFilterConfig tmp_data; char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN + 1] = {'\0'}; - char *filter_section_key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_NUM] = - { - "LogAppName", - "ContextName", - "LogLevel", - "File", - "FileSize", - "NOFiles", - "SyncBehavior", - "EcuID" - }; - - memset(&tmp_data, 0, sizeof(DltLogStorageConfigData)); - - is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT; - - for (j = 0; j < num_filter_keys; j++) - { - /* Get filter value for filter keys */ - ret = dlt_config_file_get_value(config_file, sec_name, filter_section_key[j], value); - - /* only return an error when the failure occurred on a mandatory - * value. */ - if (ret != 0 && - strncmp(filter_section_key[j], "SyncBehavior", strlen(filter_section_key[j])) - != 0 && - strncmp(filter_section_key[j], "EcuID", strlen(filter_section_key[j])) - != 0) + int i = 0; + int ret = 0; + + if ((handle == NULL) || (config_file == NULL) || (sec_name == NULL)) + { + return DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR; + } + + memset(&tmp_data, 0, sizeof(DltLogStorageFilterConfig)); + tmp_data.apids = NULL; + tmp_data.ctids = NULL; + tmp_data.file_name = NULL; + tmp_data.ecuid = NULL; + tmp_data.log_level = DLT_LOG_VERBOSE; + tmp_data.reset_log_level = DLT_LOG_OFF; + tmp_data.records = NULL; + tmp_data.log = NULL; + tmp_data.cache = NULL; + + for (i = 0 ; i < DLT_LOGSTORAGE_FILTER_CONF_COUNT ; i++) + { + ret = dlt_logstorage_get_filter_value(config_file, sec_name, i, value); + if (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR) { - is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT; - ret = DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; - dlt_log(LOG_ERR, "dlt_logstorage_store_filters Error : Reading filter value failed\n"); - break; + return ret; } - /* Validate filter value */ - if (ret == 0) + if (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE) { - ret = dlt_logstorage_validate_filter_value(filter_section_key[j], value, &appid, &ctxid, &tmp_data); - if ((ret != -1) && DLT_OFFLINE_LOGSTORAGE_IS_FILTER_PRESENT(is_filter_set)) + continue; + } + + /* check value and store temporary */ + ret = dlt_logstorage_check_param(&tmp_data, i, value); + if (ret != 0) + { + if (tmp_data.apids != NULL) { - is_filter_set |= ret; + free(tmp_data.apids); + tmp_data.apids = NULL; } - else + + if (tmp_data.ctids != NULL) { - is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT; - ret = DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; - break; + free(tmp_data.ctids); + tmp_data.ctids = NULL; } - } - else - { - if (tmp_data.sync <= DLT_LOGSTORAGE_SYNC_ON_MSG) + + if (tmp_data.file_name != NULL) + { + free(tmp_data.file_name); + tmp_data.file_name = NULL; + } + + if (tmp_data.ecuid != NULL) { - 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; + free(tmp_data.ecuid); + tmp_data.ecuid = NULL; } + + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; } } - - /* If all items of the filter is populated store them */ - if (DLT_OFFLINE_LOGSTORAGE_FILTER_INITIALIZED(is_filter_set)) + /* filter configuration is valid */ + ret = dlt_logstorage_setup_table(handle, &tmp_data); + if (ret != 0) { - /* 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) - { - dlt_log(LOG_ERR, "dlt_logstorage_store_filters Error : Storing filter values failed\n"); - ret = DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR; - } + dlt_vlog(LOG_ERR, "%s Error: Storing filter values failed\n", + __func__); + ret = DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR; } - - if (appid != NULL) - free(appid); - if (ctxid != NULL) - free(ctxid); - if (tmp_data.file_name != NULL) - free(tmp_data.file_name); - - if (tmp_data.ecuid != NULL) + else /* move to next free filter configuration, if no error occurred */ { - free(tmp_data.ecuid); + handle->num_configs += 1; + + /* free tmp_data */ + dlt_logstorage_filter_config_free(&tmp_data); } return ret; @@ -1024,12 +1599,12 @@ int dlt_daemon_setup_filter_properties(DltLogStorage *handle, DltConfigFile *con * * @param handle DLT Logstorage handle * @param config_file_name Configuration file name - * @return 0 on success, -1 on error + * @return 0 on success, -1 on error, 1 on warning * */ -int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name) +STATIC int dlt_logstorage_store_filters(DltLogStorage *handle, + char *config_file_name) { - char error_msg[DLT_DAEMON_TEXTBUFSIZE]; DltConfigFile *config = NULL; int sec = 0; int num_sec = 0; @@ -1038,7 +1613,14 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name) * filter configuration is valid and stored */ int valid = -1; + if (config_file_name == NULL) + { + dlt_vlog(LOG_ERR, "%s unexpected parameter received\n", __func__); + return -1; + } + config = dlt_config_file_init(config_file_name); + if (config == NULL) { dlt_log(LOG_CRIT, "Failed to open filter configuration file\n"); @@ -1047,13 +1629,14 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name) dlt_config_file_get_num_sections(config, &num_sec); - for (sec = 0; sec < num_sec; sec++) + for (sec = 0 ; sec < num_sec ; sec++) { - char sec_name[DLT_CONFIG_FILE_ENTRY_MAX_LEN]; + char sec_name[DLT_CONFIG_FILE_ENTRY_MAX_LEN + 1]; if (dlt_config_file_get_section_name(config, sec, sec_name) == -1) { dlt_log(LOG_CRIT, "Failed to read section name\n"); + dlt_config_file_release(config); return -1; } @@ -1064,29 +1647,33 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name) } else if (dlt_logstorage_validate_filter_name(sec_name) == 0) { - ret = dlt_daemon_setup_filter_properties(handle, config, sec_name); + ret = dlt_daemon_offline_setup_filter_properties(handle, config, sec_name); if (ret == DLT_OFFLINE_LOGSTORAGE_STORE_FILTER_ERROR) { break; } else if (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR) { + valid = 1; + dlt_vlog(LOG_WARNING, + "%s filter configuration is invalid \n", + sec_name); /* Continue reading next filter section */ continue; } else { /* Filter properties read and stored successfuly */ - valid = 0; + if (valid != 1) + { + valid = 0; + } + } } else /* unknown section */ { - snprintf(error_msg, - DLT_DAEMON_TEXTBUFSIZE, - "Unknown section: %s", - sec_name); - dlt_log(LOG_WARNING, error_msg); + dlt_vlog(LOG_WARNING, "Unknown section: %s", sec_name); } } @@ -1099,54 +1686,133 @@ int dlt_logstorage_store_filters(DltLogStorage *handle, char *config_file_name) * dlt_logstorage_load_config * * Read dlt_logstorage.conf file and setup filters in hash table - * Hash table key consists of "APPID:CTXID", e.g "APP1:CTX1". If + * Hash table key consists of "APID:CTID", e.g "APP1:CTX1". If * wildcards used for application id or context id, the hash table - * key consists of none wildcard value, e.g. appid=.*, cxtid=CTX1 + * key consists of none wildcard value, e.g. apid=.*, cxid=CTX1 * results in "CTX1". * * Combination of two wildcards is not allowed. * * @param input_file pointer to configuration file stored on device - * @return 0 on success, -1 on error + * @return 0 on success, -1 on error, 1 on warning */ -int dlt_logstorage_load_config(DltLogStorage *handle) +STATIC int dlt_logstorage_load_config(DltLogStorage *handle) { char config_file_name[PATH_MAX + 1] = {'\0'}; + int ret = 0; /* Check if handle is NULL or already initialized or already configured */ - if ((handle == NULL) || (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED)) + if ((handle == NULL) || + (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED)) + { return -1; + } /* Check if this device config was already setup */ if (handle->config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { - dlt_log(LOG_ERR, "dlt_logstorage_load_config Error : Device already configured\n"); - dlt_log(LOG_ERR, "Send disconnect, connect request to re-configure \n"); + dlt_vlog(LOG_ERR, + "%s: Device already configured. Send disconnect first.\n", + __func__); return -1; } - if(snprintf(config_file_name, PATH_MAX, "%s/%s", - handle->device_mount_point, - DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME) < 0) + if (snprintf(config_file_name, + PATH_MAX, + "%s/%s", + handle->device_mount_point, + DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME) < 0) { - dlt_log(LOG_ERR, "dlt_logstorage_load_config Error : Device already configured\n"); - dlt_log(LOG_ERR, "Send disconnect, connect request to re-configure \n"); + dlt_log(LOG_ERR, + "Creating configuration file path string failed\n"); return -1; } - if (dlt_logstorage_hash_create(DLT_OFFLINE_LOGSTORAGE_MAXFILTERS, &(handle->config_htab)) != 0) + ret = dlt_logstorage_store_filters(handle, config_file_name); + if (ret == 1) + { + handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; + return 1; + } + else if (ret != 0) { - dlt_log(LOG_ERR, "dlt_logstorage_load_config Error : Hash creation failed\n"); + dlt_log(LOG_ERR, + "dlt_logstorage_load_config Error : Storing filters failed\n"); return -1; } - if (dlt_logstorage_store_filters(handle, config_file_name) != 0) + handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; + + return 0; +} + +/** + * dlt_logstorage_device_connected + * + * Initializes DLT Offline Logstorage with respect to device status + * + * @param handle DLT Logstorage handle + * @param mount_point Device mount path + * @return 0 on success, -1 on error, 1 on warning + */ +int dlt_logstorage_device_connected(DltLogStorage *handle, char *mount_point) +{ + if ((handle == NULL) || (mount_point == NULL)) { - dlt_log(LOG_ERR, "dlt_logstorage_load_config Error : Storing filters failed\n"); + dlt_log(LOG_ERR, "Handle error \n"); return -1; } - handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; + if (handle->connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) + { + dlt_log(LOG_WARNING, + "Device already connected. Send disconnect, connect request\n"); + + dlt_logstorage_device_disconnected( + handle, + DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); + } + + strncpy(handle->device_mount_point, mount_point, DLT_MOUNT_PATH_MAX); + handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; + handle->config_status = 0; + handle->write_errors = 0; + handle->num_filter_keys = 0; + + /* Setup logstorage with config file settings */ + return dlt_logstorage_load_config(handle); +} + +/** + * dlt_logstorage_device_disconnected + * + * De-Initializes DLT Offline Logstorage with respect to device status + * + * @param handle DLT Logstorage handle + * @param reason Reason for disconnect + * @return 0 on success, -1 on error + * + */ +int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason) +{ + if (handle == NULL) + { + return -1; + } + + /* If configuration loading was done, free it */ + if (handle->config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) + { + dlt_logstorage_free(handle, reason); + } + + /* Reset all device status */ + memset(handle->device_mount_point, '\0', sizeof(char) * DLT_MOUNT_PATH_MAX); + handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED; + handle->config_status = 0; + handle->write_errors = 0; + handle->num_filter_keys = 0; + handle->num_configs = 0; return 0; } @@ -1164,16 +1830,25 @@ int dlt_logstorage_load_config(DltLogStorage *handle) */ int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key) { - DltLogStorageConfigData *config; + DltLogStorageFilterConfig *config = NULL; /* Check if handle is NULL,already initialized or already configured */ - if ((handle == NULL) || (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) - || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) + if ((handle == NULL) || + (key == NULL) || + (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || + (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) { return -1; } - config = (DltLogStorageConfigData *)dlt_logstorage_hash_find(key, &(handle->config_htab)); + config = (DltLogStorageFilterConfig *) + dlt_logstorage_list_find(key, &(handle->config_list)); + + if (config == NULL) + { + dlt_vlog(LOG_WARNING, "Configuration for key [%s] not found!\n", key); + return -1; + } return config->log_level; } @@ -1186,113 +1861,185 @@ int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key) * data available in the Hash map, this function will return the address * of configuration data for all these 3 combinations * - * @param handle DltLogStorage handle - * @param appid application id - * @param ctxid context id - * @param num_config (o/p) contains the number of filter configration data obtained - * @return on success: address of configuration data, NULL on failure or no configuration data found + * @param handle DltLogStorage handle + * @param config Pointer to array of filter configurations + * @param apid application id + * @param ctid context id + * @return number of found configurations */ -DltLogStorageConfigData **dlt_logstorage_get_config(DltLogStorage *handle, char *apid, char *ctid, int *num_config) +int dlt_logstorage_get_config(DltLogStorage *handle, + DltLogStorageFilterConfig **config, + char *apid, + char *ctid, + char *ecuid) { - DltLogStorageConfigData **config = NULL; - DltLogStorageConfigData *ptr_config = NULL; - char key[3][DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN]= {{'\0'},{'\0'},{'\0'}}; - int i=0; + DltLogStorageFilterConfig *ptr_config = NULL; + char key[DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS][DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN] = {{'\0'}, {'\0'}, {'\0'}}; + int i = 0; int apid_len = 0; int ctid_len = 0; + int ecuid_len = 0; + int num = 0; /* Check if handle is NULL,already initialized or already configured */ - if ((handle == NULL) || (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) - || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) - return NULL; + if ((handle == NULL) || (config == NULL) || + (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || + (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) || + (ecuid == NULL)) + { + return 0; + } + + /* Prepare possible keys with + * Possible combinations are + * ecu:: + ecu:apid:ctid + :apid:ctid + ecu::ctid + ecu:apid: + ::ctid + :apid: */ + + ecuid_len = strlen(ecuid); + if (ecuid_len > DLT_ID_SIZE) + { + ecuid_len = DLT_ID_SIZE; + } + + if ((apid == NULL) && (ctid == NULL)) + { + /* ecu:: */ + strncpy(key[0], ecuid, ecuid_len); + strncat(key[0], ":", 1); + strncat(key[0], ":", 1); - if ((apid == NULL) || (ctid == NULL)) - return NULL; + ptr_config = (DltLogStorageFilterConfig *) dlt_logstorage_list_find( + key[0], &(handle->config_list)); - /* Check if num_config passed is non zero */ - if (*(num_config) !=0) - *(num_config) = 0; + if (ptr_config != NULL) + { + config[num] = ptr_config; + num += 1; + } + return num; + } - /* Prepare possible keys with apid and ctid, - Possible combinataions are apid: , :ctid and apid:ctid */ apid_len = strlen(apid); if (apid_len > DLT_ID_SIZE) - apid_len = DLT_ID_SIZE; - - strncpy(key[0], apid, apid_len); - strncat(key[0], ":",1); + { + apid_len = DLT_ID_SIZE; + } ctid_len = strlen(ctid); if (ctid_len > DLT_ID_SIZE) - ctid_len = DLT_ID_SIZE; + { + ctid_len = DLT_ID_SIZE; + } + + /* :apid: */ + strncpy(key[0], ":", 1); + strncat(key[0], apid, apid_len); + strncat(key[0], ":", 1); + /* ::ctid */ strncpy(key[1], ":", 1); + strncat(key[1], ":", 1); strncat(key[1], ctid, ctid_len); - strncpy(key[2], apid, apid_len); + /* :apid:ctid */ + strncpy(key[2], ":", 1); + strncat(key[2], apid, apid_len); strncat(key[2], ":", 1); strncat(key[2], ctid, ctid_len); - config = (DltLogStorageConfigData **)calloc(3, sizeof(DltLogStorageConfigData *)); + /* ecu:apid:ctid */ + strncpy(key[3], ecuid, ecuid_len); + strncat(key[3], ":", 1); + strncat(key[3], apid, apid_len); + strncat(key[3], ":", 1); + strncat(key[3], ctid, ctid_len); - if (config == NULL) - return NULL; + /* ecu:apid: */ + strncpy(key[4], ecuid, ecuid_len); + strncat(key[4], ":", 1); + strncat(key[4], apid, apid_len); + strncat(key[4], ":", 1); + + /* ecu::ctid */ + strncpy(key[5], ecuid, ecuid_len); + strncat(key[5], ":", 1); + strncat(key[5], ":", 1); + strncat(key[5], ctid, ctid_len); + + /* ecu:: */ + strncpy(key[6], ecuid, ecuid_len); + strncat(key[6], ":", 1); + strncat(key[6], ":", 1); - /* Search the list thrice with keys as -apid: , :ctid and apid:ctid */ - for (i=0; i<3; i++) + /* Search the list three times with keys as -apid: , :ctid and apid:ctid */ + for (i = 0; i < DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS; i++) { - ptr_config = (DltLogStorageConfigData *)dlt_logstorage_hash_find(key[i], &(handle->config_htab)); + ptr_config = (DltLogStorageFilterConfig *) + dlt_logstorage_list_find(key[i], &(handle->config_list)); + if (ptr_config != NULL) { - config[*(num_config)] = ptr_config; - *(num_config) += 1; + config[num] = ptr_config; + num += 1; } } - if (*(num_config) == 0) - { - free(config); - return NULL; - } - - return config; + return num; } /** * dlt_logstorage_filter * - * Check if log message need to be stored in a certain device based on filter config - * - get all DltLogStorageConfigData from hash table possible by given apid/ctid (apid:, :ctid, apid:ctid + * Check if log message need to be stored in a certain device based on filter + * config + * - get all DltLogStorageFilterConfig from hash table possible by given + * apid/ctid (apid:, :ctid, apid:ctid * - for each found structure, compare message log level with configured one * - * @param appid application id - * @param ctxid context id + * @param handle DltLogStorage handle + * @param config Pointer to array of filter configurations + * @param apid application id + * @param ctid context id * @param log_level Log level of message * @param ecuid EcuID given in the message - * @param num Number of found configurations - * @return list of filters received from hashmap or NULL + * @return number of found configurations */ -DltLogStorageConfigData **dlt_logstorage_filter(DltLogStorage *handle, - char *appid, - char *ctxid, - char *ecuid, - int log_level, - int *num) +STATIC int dlt_logstorage_filter(DltLogStorage *handle, + DltLogStorageFilterConfig **config, + char *apid, + char *ctid, + char *ecuid, + int log_level) { - DltLogStorageConfigData **config = NULL; int i = 0; + int num = 0; - /* filter on names: find DltLogStorageConfigData structures */ - config = dlt_logstorage_get_config(handle, appid, ctxid, num); + if ((handle == NULL) || (config == NULL) || (ecuid == NULL)) + { + return -1; + } - if (config == NULL) + /* filter on names: find DltLogStorageFilterConfig structures */ + num = dlt_logstorage_get_config(handle, config, apid, ctid, ecuid); + + if (num == 0) { - *num = 0; - return NULL; + dlt_log(LOG_DEBUG, "No valid filter configuration found\n"); + return 0; } - for (i = 0; i < *num; i++) + for (i = 0 ; i < DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS ; i++) { + if (config[i] == NULL) + { + continue; + } + /* filter on log level */ if (log_level > config[i]->log_level) { @@ -1303,14 +2050,14 @@ DltLogStorageConfigData **dlt_logstorage_filter(DltLogStorage *handle, /* filter on ECU id only if EcuID is set */ if (config[i]->ecuid != NULL) { - if (strncmp(ecuid, config[i]->ecuid, strlen(ecuid)) != 0) + if (strncmp(ecuid, config[i]->ecuid, DLT_ID_SIZE) != 0) { config[i] = NULL; } } } - return config; + return num; } /** @@ -1336,142 +2083,204 @@ int dlt_logstorage_write(DltLogStorage *handle, unsigned char *data3, int size3) { - DltLogStorageConfigData **config = NULL; + DltLogStorageFilterConfig *config[DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS] = {0}; int i = 0; int ret = 0; int num = 0; int err = 0; /* data2 contains DltStandardHeader, DltStandardHeaderExtra and * DltExtendedHeader. We are interested in ecuid, apid, ctid and loglevel */ - DltExtendedHeader *extendedHeader; - DltStandardHeaderExtra *extraHeader; - DltStandardHeader *standardHeader; - int standardHeaderExtraLen = 0; + DltExtendedHeader *extendedHeader = NULL; + DltStandardHeaderExtra *extraHeader = NULL; + DltStandardHeader *standardHeader = NULL; + unsigned int standardHeaderExtraLen = sizeof(DltStandardHeaderExtra); + unsigned int header_len = 0; int log_level = -1; - if (handle == NULL || uconfig == NULL || - data1 == NULL || data2 == NULL || data3 == NULL || - handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED || - handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) + if ((handle == NULL) || (uconfig == NULL) || + (data1 == NULL) || (data2 == NULL) || (data3 == NULL) || + (handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || + (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) { return 0; } + /* Calculate real length of DltStandardHeaderExtra */ standardHeader = (DltStandardHeader *)data2; - standardHeaderExtraLen = sizeof(DltStandardHeaderExtra); + if (!DLT_IS_HTYP_WEID(standardHeader->htyp)) { standardHeaderExtraLen -= DLT_ID_SIZE; } + if (!DLT_IS_HTYP_WSID(standardHeader->htyp)) { standardHeaderExtraLen -= DLT_SIZE_WSID; } + if (!DLT_IS_HTYP_WTMS(standardHeader->htyp)) { standardHeaderExtraLen -= DLT_SIZE_WTMS; } - extendedHeader = (DltExtendedHeader *)(data2 + - sizeof(DltStandardHeader) + - standardHeaderExtraLen); - extraHeader = (DltStandardHeaderExtra *)(data2 + sizeof(DltStandardHeader)); + extraHeader = (DltStandardHeaderExtra *) (data2 + + sizeof(DltStandardHeader)); + + if (DLT_IS_HTYP_UEH(standardHeader->htyp)) + { + header_len = sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + standardHeaderExtraLen; + /* check if size2 is big enough to contain expected DLT message header */ + if ((unsigned int)size2 < header_len) + { + dlt_log(LOG_ERR, "DLT message header is too small\n"); + return 0; + } + + extendedHeader = (DltExtendedHeader *) (data2 + + sizeof(DltStandardHeader) + standardHeaderExtraLen); + + log_level = DLT_GET_MSIN_MTIN(extendedHeader->msin); + + /* check if log message need to be stored in a certain device based on + * filter configuration */ + num = dlt_logstorage_filter(handle, config, extendedHeader->apid, + extendedHeader->ctid, extraHeader->ecu, log_level); + + if (num == 0 || num == -1) + { + dlt_log(LOG_DEBUG, "No valid filter configuration found!\n"); + return 0; + } + } + else + { + header_len = sizeof(DltStandardHeader) + standardHeaderExtraLen; + /* check if size2 is big enough to contain expected DLT message header */ + if ((unsigned int)size2 < header_len) + { + dlt_log(LOG_ERR, "DLT message header is too small (without extended header)\n"); + return 0; + } + + log_level = DLT_LOG_VERBOSE; - log_level = DLT_GET_MSIN_MTIN(extendedHeader->msin); + /* check if log message need to be stored in a certain device based on + * filter configuration */ + num = dlt_logstorage_filter(handle, config, NULL, + NULL, extraHeader->ecu, log_level); - /* check if log message need to be stored in a certain device based on - * filter configuration */ - config = dlt_logstorage_filter(handle, - extendedHeader->apid, - extendedHeader->ctid, - extraHeader->ecu, - log_level, - &num); + if (num == 0 || num == -1) + { + dlt_log(LOG_DEBUG, "No valid filter configuration found!\n"); + return 0; + } + } - if (config != NULL) + /* store log message in every found filter */ + for (i = 0; i < DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS; i++) { - /* store log message in every found filter */ - while (i < num) + if (config[i] == NULL) { - if(config[i] != NULL) + continue; + } + + /* If file name is not present, the filter is non verbose control filter + * hence skip storing */ + if (config[i]->file_name == NULL) + { + continue; + } + + /* prepare log file (create and/or open)*/ + ret = config[i]->dlt_logstorage_prepare(config[i], + uconfig, + handle->device_mount_point, + size1 + size2 + size3); + + if (ret == 0) /* log data (write) */ + { + ret = config[i]->dlt_logstorage_write(config[i], + data1, + size1, + data2, + size2, + data3, + size3); + + if (ret == 0) { - /* prepare log file (create and/or open)*/ - ret = config[i]->dlt_logstorage_prepare(config[i], - uconfig, - handle->device_mount_point, - size1 + size2 + size3); - if (ret == 0) /* log data (write) */ + /* flush to be sure log is stored on device */ + ret = config[i]->dlt_logstorage_sync(config[i], + uconfig, + handle->device_mount_point, + DLT_LOGSTORAGE_SYNC_ON_MSG); + + if (ret != 0) { - ret = config[i]->dlt_logstorage_write(config[i], - data1, - size1, - data2, - size2, - data3, - size3); - - if (ret == 0) - { - /* 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) - { - dlt_log(LOG_ERR, - "dlt_logstorage_write: Unable to sync.\n"); - } - } - else - { - handle->write_errors += 1; - if (handle->write_errors >= - DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS) - { - err = -1; - } - - dlt_log(LOG_ERR, - "dlt_logstorage_write: Unable to write.\n"); - } + dlt_log(LOG_ERR, + "dlt_logstorage_write: Unable to sync.\n"); } - else + } + else + { + handle->write_errors += 1; + + if (handle->write_errors >= + DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS) { - dlt_log(LOG_ERR, - "dlt_logstorage_write: Unable to prepare.\n"); + err = -1; } + + dlt_log(LOG_ERR, + "dlt_logstorage_write: Unable to write.\n"); } - i++; } - - free(config); + else + { + dlt_log(LOG_ERR, + "dlt_logstorage_write: Unable to prepare.\n"); + } } return err; } +/** + * dlt_logstorage_sync_caches + * + * Write Cache data to file + * + * @param handle DltLogStorage handle + * @return 0 on success, -1 on error + */ int dlt_logstorage_sync_caches(DltLogStorage *handle) { - int i = 0; + DltLogStorageFilterList **tmp = NULL; if (handle == NULL) { return -1; } - for (i=0; i<handle->num_filter_keys; i++) + tmp = &(handle->config_list); + + while (*(tmp) != NULL) { - /* sync data if necessary */ - /* ignore return value */ - if (handle->config_data[i].data.dlt_logstorage_sync( - &(handle->config_data[i].data), - DLT_LOGSTORAGE_SYNC_ON_DEMAND) != 0) + if ((*tmp)->data != NULL) { - - dlt_log(LOG_ERR, - "dlt_logstorage_sync_caches: Sync failed." - " Continue with next cache.\n"); + if ((*tmp)->data->dlt_logstorage_sync((*tmp)->data, + &handle->uconfig, + handle->device_mount_point, + DLT_LOGSTORAGE_SYNC_ON_DEMAND) != 0) + { + dlt_vlog(LOG_ERR, + "%s: Sync failed. Continue with next cache.\n", + __func__); + } } + tmp = &(*tmp)->next; + } return 0; diff --git a/src/offlinelogstorage/dlt_offline_logstorage.h b/src/offlinelogstorage/dlt_offline_logstorage.h index df232b7..b3f7dd3 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage.h +++ b/src/offlinelogstorage/dlt_offline_logstorage.h @@ -54,10 +54,13 @@ #define DLT_OFFLINE_LOGSTORAGE_H #include <search.h> +#include <stdbool.h> #include "dlt_common.h" #include "dlt-daemon_cfg.h" +#include "dlt_config_file_parser.h" -#define DLT_OFFLINE_LOGSTORAGE_MAXFILTERS 100 /* Maximum entries in hashmap */ +#define DLT_OFFLINE_LOGSTORAGE_MAXIDS 100 /* Maximum entries for each apids and ctids */ +#define DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS 7 /* max number of possible filters when searching for */ #define DLT_OFFLINE_LOGSTORAGE_INIT_DONE 1 /* For device configuration status */ #define DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED 1 @@ -67,7 +70,7 @@ #define DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES 2 /* sync logstorage caches */ -#define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN 10 /* Maximum size for key */ +#define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN 15 /* Maximum size for key */ #define DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN 50 /* Maximum file name length of the log file */ #define DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN 4 @@ -82,23 +85,6 @@ DLT_OFFLINE_LOGSTORAGE_INDEX_LEN + \ DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + 1) -#define DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT 0 -#define DLT_OFFLINE_LOGSTORAGE_ECUID (1<<8) -#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 -/* Sync behavior and ECUid are 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_IS_FILTER_PRESENT(A) ((A) & DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT) - #define DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN 50 #define DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME "dlt_logstorage.conf" @@ -114,15 +100,20 @@ #define DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION "FILTER" #define DLT_OFFLINE_LOGSTORAGE_GENERAL_CONFIG_SECTION "GENERAL" +#define DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION "NON-VERBOSE-STORAGE-FILTER" +#define DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION "NON-VERBOSE-LOGLEVEL-CTRL" /* Offline Logstorage sync strategies */ #define DLT_LOGSTORAGE_SYNC_ON_ERROR -1 /* error case */ +#define DLT_LOGSTORAGE_SYNC_UNSET 0 /* strategy not set */ #define DLT_LOGSTORAGE_SYNC_ON_MSG 1 /* default, on message sync */ -#define DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT (1<<1) /* sync on daemon exit */ -#define DLT_LOGSTORAGE_SYNC_ON_DEMAND (1<<2) /* sync on demand */ -#define DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT (1<<3) /* sync on device disconnect*/ +#define DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT (1 << 1) /* sync on daemon exit */ +#define DLT_LOGSTORAGE_SYNC_ON_DEMAND (1 << 2) /* sync on demand */ +#define DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT (1 << 3) /* sync on device disconnect*/ +#define DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE (1 << 4) /* sync on after specific size */ +#define DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE (1 << 5) /* sync on file size reached */ -#define DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(S, s) ((S) & (s)) +#define DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(S, s) ((S) &(s)) /* logstorage max cache */ unsigned int g_logstorage_cache_max; @@ -131,9 +122,10 @@ unsigned int g_logstorage_cache_size; typedef struct { - int offset; /* current write offset */ + unsigned int offset; /* current write offset */ unsigned int wrap_around_cnt; /* wrap around counter */ -}DltLogStorageCacheFooter; + unsigned int last_sync_offset; /* last sync position */ +} DltLogStorageCacheFooter; typedef struct { @@ -142,7 +134,7 @@ typedef struct char logfile_delimiter; /* Choice of delimiter */ unsigned int logfile_maxcounter; /* Maximum file index counter */ unsigned int logfile_counteridxlen; /* File index counter length */ -}DltLogStorageUserConfig; +} DltLogStorageUserConfig; typedef struct DltLogStorageFileList { @@ -150,25 +142,28 @@ typedef struct DltLogStorageFileList char *name; /* Filename */ unsigned int idx; /* File index */ struct DltLogStorageFileList *next; -}DltLogStorageFileList; +} DltLogStorageFileList; -typedef struct DltLogStorageConfigData DltLogStorageConfigData; +typedef struct DltLogStorageFilterConfig DltLogStorageFilterConfig; -struct DltLogStorageConfigData +struct DltLogStorageFilterConfig { /* filter section */ + char *apids; /* Application IDs configured for filter */ + char *ctids; /* Context IDs configured for filter */ int log_level; /* Log level number configured for filter */ + int reset_log_level; /* reset Log level to be sent on disconnect */ 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 */ char *ecuid; /* ECU identifier */ /* callback function for filter configurations */ - int (*dlt_logstorage_prepare)(DltLogStorageConfigData *config, + int (*dlt_logstorage_prepare)(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size); - int (*dlt_logstorage_write)(DltLogStorageConfigData *config, + int (*dlt_logstorage_write)(DltLogStorageFilterConfig *config, unsigned char *data1, int size1, unsigned char *data2, @@ -177,27 +172,37 @@ struct DltLogStorageConfigData 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); + int (*dlt_logstorage_sync)(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *uconfig, + char *dev_path, + int status); FILE *log; /* current open log file */ void *cache; /* log data cache */ + unsigned int specific_size; /* cache size used for specific_size sync strategy */ + unsigned int current_write_file_offset; /* file offset for specific_size sync strategy */ + unsigned int total_write_count; /* total count of data need to sync to file */ + bool pre_cache_sync; /* sync done in previous wrap around */ + bool cur_cache_sync; /* sync done in present cache */ + bool sync_from_start; /* sync done from start of cache */ DltLogStorageFileList *records; /* File name list */ }; +typedef struct DltLogStorageFilterList DltLogStorageFilterList; -typedef struct +struct DltLogStorageFilterList { - char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN]; /* Keys stored in hash table */ - DltLogStorageConfigData data; /* Data stored in hash table */ -}DltLogStorageConfig; - + char *key; /* Key to find data */ + DltLogStorageFilterConfig *data; /* Filter data */ + DltLogStorageFilterList *next; /* Pointer to next */ +}; typedef struct { - struct hsearch_data config_htab; /* Hash table object declaration used by hsearch_r()*/ - DltLogStorageConfig *config_data; /* Configuration data */ - char *filter_keys; /* List of all keys stored in config_htab */ + DltLogStorageFilterList *config_list; /* List of all filters */ + DltLogStorageUserConfig uconfig; /* User configurations for file name*/ + int num_configs; /* Number of configs */ int num_filter_keys; /* Number of keys */ - char device_mount_point[DLT_MOUNT_PATH_MAX]; /* Device mount path */ + char device_mount_point[DLT_MOUNT_PATH_MAX + 1]; /* Device mount path */ unsigned int connection_type; /* Type of connection */ unsigned int config_status; /* Status of configuration */ int write_errors; /* number of write errors */ @@ -213,18 +218,10 @@ typedef struct * @param mount_point Device mount path * @return 0 on success, -1 on error */ -extern int dlt_logstorage_device_connected(DltLogStorage *handle, char *mount_point); +int dlt_logstorage_device_connected(DltLogStorage *handle, + char *mount_point); /** - * dlt_logstorage_load_config - * - * Parse dlt_logstorage.conf file in the device and setup internal info table - * - * @param handle DltLogStorage handle - * @return 0 on success, -1 on error - */ -extern int dlt_logstorage_load_config(DltLogStorage *handle); -/** * dlt_logstorage_device_disconnected * De-Initializes DLT Offline Logstorage with respect to device status * @@ -232,7 +229,8 @@ extern int dlt_logstorage_load_config(DltLogStorage *handle); * @param reason Reason for device disconnection * @return 0 on success, -1 on error */ -extern int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason); +int dlt_logstorage_device_disconnected(DltLogStorage *handle, + int reason); /** * dlt_logstorage_get_config * @@ -241,25 +239,30 @@ extern int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason) * data available in the Hash map, this function will return the address * of configuration data for all these 3 combinations * - * @param handle DltLogStorage handle - * @param appid application id - * @param ctxid context id - * @param num_config (o/p) contains the number of filter configration data obtained - * @return on success: address of configuration data, NULL on failure or no configuration data found + * @param handle DltLogStorage handle + * @param config Pointer to array of filter configurations + * @param appid application id + * @param ctxid context id + * @return number of found configurations */ -extern DltLogStorageConfigData **dlt_logstorage_get_config(DltLogStorage *handle, char *apid, char *ctid, int *num_config); +int dlt_logstorage_get_config(DltLogStorage *handle, + DltLogStorageFilterConfig **config, + char *apid, + char *ctid, + char *ecuid); + /** * dlt_logstorage_get_loglevel_by_key * * Obtain the log level for the provided key * This function can be used to obtain log level when the actual - * key stored in the Hash map is availble with the caller + * key stored in the Hash map is available with the caller * * @param handle DltLogstorage handle * @param key key to search for in Hash MAP * @return log level on success:, -1 on error */ -extern int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); +int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); /** * dlt_logstorage_write @@ -275,14 +278,14 @@ extern int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); * @param size2 Size of message body * @return 0 on success or write errors < max write errors, -1 on error */ -extern int dlt_logstorage_write(DltLogStorage *handle, - DltLogStorageUserConfig *uconfig, - unsigned char *data1, - int size1, - unsigned char *data2, - int size2, - unsigned char *data3, - int size3); +int dlt_logstorage_write(DltLogStorage *handle, + DltLogStorageUserConfig *uconfig, + unsigned char *data1, + int size1, + unsigned char *data2, + int size2, + unsigned char *data3, + int size3); /** * dlt_logstorage_sync_caches @@ -292,6 +295,6 @@ extern int dlt_logstorage_write(DltLogStorage *handle, * @param handle DltLogStorage handle * @return 0 on success, -1 otherwise */ -extern int dlt_logstorage_sync_caches(DltLogStorage *handle); +int dlt_logstorage_sync_caches(DltLogStorage *handle); #endif /* DLT_OFFLINE_LOGSTORAGE_H */ diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior.c b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c index f68d10d..6a210b5 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage_behavior.c +++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c @@ -55,7 +55,7 @@ void dlt_logstorage_log_file_name(char *log_file_name, char *name, int idx) { - if (log_file_name == NULL || file_config == NULL) + if ((log_file_name == NULL) || (file_config == NULL)) { return; } @@ -67,16 +67,17 @@ void dlt_logstorage_log_file_name(char *log_file_name, strcat(log_file_name, name); strncat(log_file_name, &file_config->logfile_delimiter, 1); - snprintf(file_index, 10, "%d",idx); + 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); + snprintf(file_index, 10, "%d", idx); digit_idx = strlen(file_index); - for(i=0; i<(file_config->logfile_counteridxlen - digit_idx); i++) + + for (i = 0 ; i < (file_config->logfile_counteridxlen - digit_idx) ; i++) { strcat(log_file_name, "0"); } @@ -117,7 +118,7 @@ void dlt_logstorage_sort_file_name(DltLogStorageFileList **head) { int done = 0; - if (head == NULL || *head == NULL || (*head)->next == NULL) + if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL)) { return; } @@ -141,6 +142,7 @@ void dlt_logstorage_sort_file_name(DltLogStorageFileList **head) done = 0; } + pv = &nd->next; nd = nx; nx = nx->next; @@ -164,12 +166,12 @@ void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head) DltLogStorageFileList *wrap_post = NULL; DltLogStorageFileList *n = NULL; - if (head == NULL || *head == NULL || (*head)->next == NULL) + if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL)) { return; } - for (n = *head; n != NULL; n = n->next) + for (n = *head ; n != NULL ; n = n->next) { if (n && n_prev) { @@ -179,8 +181,10 @@ void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head) wrap_pre = n_prev; } } + n_prev = n; } + tail = n_prev; if (wrap_post && wrap_pre) @@ -201,51 +205,58 @@ void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head) * @return index on success, -1 if no index is found */ unsigned int dlt_logstorage_get_idx_of_log_file( - DltLogStorageUserConfig *file_config, - char *file) + DltLogStorageUserConfig *file_config, + char *file) { unsigned int idx = -1; char *endptr; char *filename; - unsigned int filename_len = 0 ; + unsigned int filename_len = 0; unsigned int fileindex_len = 0; - if (file_config == NULL || file == NULL) + if ((file_config == NULL) || (file == NULL)) { return -1; } /* Calculate actual file name length */ - filename=strchr(file, file_config->logfile_delimiter); + filename = strchr(file, file_config->logfile_delimiter); + + if (filename == NULL) + { + dlt_vlog(LOG_ERR, "Cannot extract filename from %s\n", file); + return -1; + } + filename_len = strlen(file) - strlen(filename); /* index is retrived from file name */ - if(file_config->logfile_timestamp) + if (file_config->logfile_timestamp) { fileindex_len = strlen(file) - - (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + - DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + - filename_len + 1); + (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)], + (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); + (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); + idx = (int) strtol(&file[strlen(file) - + (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + + fileindex_len)], &endptr, 10); } - if (endptr == file || idx == 0) + if ((endptr == file) || (idx == 0)) { dlt_log(LOG_ERR, "Unable to calculate index from log file name. Reset to 001.\n"); @@ -262,12 +273,12 @@ unsigned int dlt_logstorage_get_idx_of_log_file( * * @param file_config User configurations for log file * @param path Path to storage directory - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @return 0 on success, -1 on error */ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, char *path, - DltLogStorageConfigData *config) + DltLogStorageFilterConfig *config) { int i = 0; int cnt = 0; @@ -275,15 +286,16 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, struct dirent **files = {0}; unsigned int current_idx = 0; - if (config == NULL || - file_config == NULL || - path == NULL || - config->file_name == NULL) + 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, @@ -291,22 +303,24 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, return -1; } - for (i = 0; i < cnt; i++) + 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)) + (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) + if (config->records == NULL) { config->records = malloc(sizeof(DltLogStorageFileList)); + if (config->records == NULL) { ret = -1; @@ -314,16 +328,20 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, "Memory allocation failed\n"); break; } + tmp = &config->records; } else { tmp = &config->records; - while(*(tmp) != NULL) + + while (*(tmp) != NULL) { tmp = &(*tmp)->next; } + *tmp = malloc(sizeof(DltLogStorageFileList)); + if (*tmp == NULL) { ret = -1; @@ -332,8 +350,9 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, break; } } + (*tmp)->name = strdup(files[i]->d_name); - (*tmp)->idx = current_idx; + (*tmp)->idx = current_idx; (*tmp)->next = NULL; } } @@ -345,10 +364,11 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, } /* free scandir result */ - for (i = 0; i < cnt; i++) + for (i = 0 ; i < cnt ; i++) { free(files[i]); } + free(files); return ret; @@ -362,20 +382,20 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, * 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 config DltLogStorageFilterConfig * @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, +int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *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'}; + char absolute_file_path[DLT_MOUNT_PATH_MAX + DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 1] = {'\0'}; + char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 1] = {'\0'}; unsigned int num_log_files = 0; struct stat s; DltLogStorageFileList **tmp = NULL; @@ -387,33 +407,40 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, return -1; } - if(snprintf(storage_path, DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN, - "%s/", dev_path) >= DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN) + if (strlen(dev_path) > DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN) { - dlt_log(LOG_ERR, "Mount point path name too long\n"); + dlt_vlog(LOG_ERR, "device path '%s' is too long to store\n", dev_path); return -1; } + snprintf(storage_path, DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN, "%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) + + while (*(tmp) != NULL) { num_log_files += 1; - if((*tmp)->next == NULL) + + if ((*tmp)->next == NULL) + { newest = tmp; + } tmp = &(*tmp)->next; } - /* need new file*/ + /* need new file*/ if (num_log_files == 0) { dlt_logstorage_log_file_name(file_name, @@ -428,14 +455,16 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, /* 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)->idx = 1; (*tmp)->next = NULL; } else /* newest file available*/ @@ -446,7 +475,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, ret = stat(absolute_file_path, &s); /* if size is enough, open it */ - if (ret == 0 && s.st_size + msg_size < (int)config->file_size) + if ((ret == 0) && (s.st_size + msg_size < (int)config->file_size)) { config->log = fopen(absolute_file_path, "a+"); } @@ -461,7 +490,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, /* 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) + if ((idx > file_config->logfile_maxcounter) || (idx == 0)) { idx = 1; } @@ -474,13 +503,14 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, /* concatenate path and file and open absolute path */ memset(absolute_file_path, 0, - sizeof(absolute_file_path)/sizeof(char)); + 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, @@ -489,7 +519,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, } (*tmp)->name = strdup(file_name); - (*tmp)->idx = idx; + (*tmp)->idx = idx; (*tmp)->next = NULL; num_log_files += 1; @@ -502,7 +532,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, DltLogStorageFileList *n = *head; memset(absolute_file_path, 0, - sizeof(absolute_file_path)/sizeof(char)); + sizeof(absolute_file_path) / sizeof(char)); strcat(absolute_file_path, storage_path); strcat(absolute_file_path, (*head)->name); remove(absolute_file_path); @@ -525,18 +555,323 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, } /** + * dlt_logstorage_find_dlt_header + * + * search for dlt header in cache + * + * @param ptr cache starting position + * @param offset offset + * @param cnt count + * @return index on success, -1 on error + */ +STATIC int dlt_logstorage_find_dlt_header(void *ptr, + unsigned int offset, + unsigned int cnt) +{ + int index = 0; + char substring[] = {'D', 'L', 'T', 0x01}; + while(cnt > 0) + { + if (*((char *)(ptr + offset + index)) == 'D') + { + if (strncmp(ptr + offset + index , substring, 4) == 0) + { + return index; + } + } + cnt--; + index++; + } + return -1; +} + +/** + * dlt_logstorage_check_write_ret + * + * check the return value of fwrite + * + * @param config DltLogStorageFilterConfig + * @param ret return value of fwrite call + */ +STATIC void dlt_logstorage_check_write_ret(DltLogStorageFilterConfig *config, + int ret) +{ + if (config == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + } + if (ret <= 0) + { + if (ferror(config->log) != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to write cache into log file\n", __func__); + } + } + else + { + /* force sync */ + if (fflush(config->log) != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to flush log file\n", __func__); + } + if (fsync(fileno(config->log)) != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync log file\n", __func__); + } + } +} + +/** + * dlt_logstorage_sync_create_new_file + * + * Write the log message and open new log file + * + * @param config DltLogStorageFilterConfig + * @param file_config DltLogStorageUserConfig + * @param dev_path Storage device mount point + * @param remain_file_size log file remaining size + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_logstorage_sync_create_new_file( + DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, + unsigned int remain_file_size) +{ + int index = 0; + int ret; + unsigned int cache_offset = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; + + if (config == NULL || file_config == NULL || dev_path == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + footer = (DltLogStorageCacheFooter *)(config->cache + + config->file_size); + if (footer == NULL) + { + dlt_vlog(LOG_ERR, "%s: Cannot retrieve cache information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + + /* sync capable data to file */ + if (footer->offset >= footer->last_sync_offset) + { + count = config->file_size - footer->offset; + if (count > remain_file_size) + { + count = remain_file_size; + } + index = dlt_logstorage_find_dlt_header(config->cache,footer->offset,count); + cache_offset = footer->offset; + } + else + { + count = config->file_size - footer->last_sync_offset; + if (count > remain_file_size) + { + count = remain_file_size; + } + index = dlt_logstorage_find_dlt_header(config->cache, + footer->last_sync_offset, + count); + cache_offset = footer->last_sync_offset; + + } + if (index >= 0) + { + ret = fwrite(config->cache + cache_offset + index, count - index, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count - index; + } + if (footer->last_sync_offset == 0) + { + footer->last_sync_offset = footer->offset + count; + } + else + { + footer->last_sync_offset += count; + } + config->total_write_count -= count; + + /* sync data to current file in case of file is not full */ + if (config->current_write_file_offset < config->file_size) + { + count = config->file_size - config->current_write_file_offset; + + if (footer->last_sync_offset < config->file_size) + { + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + footer->last_sync_offset += count; + } + /* sync remaining amount of file from start of cache */ + else + { + config->sync_from_start = 1; + if (count > footer->offset) + { + count = footer->offset; + } + ret = fwrite(config->cache, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + footer->last_sync_offset = count; + } + config->total_write_count -= count; + } + + config->current_write_file_offset = 0; + fclose(config->log); + config->log = NULL; + /* get always a new file */ + if (dlt_logstorage_prepare_on_msg(config, + file_config, + dev_path, + config->file_size) != 0) + { + dlt_vlog(LOG_ERR, + "%s: failed to prepare log file for file_size\n", __func__); + return DLT_RETURN_ERROR; + } + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_sync_to_file + * + * Write the log message to log file + * + * @param config DltLogStorageFilterConfig + * @param file_config DltLogStorageUserConfig + * @param dev_path Storage device mount point path + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_logstorage_sync_to_file( + DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path) +{ + int ret = 0; + unsigned int remain_file_size = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; + + if (config == NULL || file_config == NULL || dev_path == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + footer = (DltLogStorageCacheFooter *)(config->cache + config->file_size); + + if (footer == NULL) + { + dlt_vlog(LOG_ERR, "%s: Cannot retrieve cache information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + }; + count = footer->offset - footer->last_sync_offset; + remain_file_size = config->file_size - config->current_write_file_offset; + + /* sync data to file if required sync data exceeds remaining file size */ + if (count > remain_file_size) + { + ret = fwrite(config->cache + footer->last_sync_offset, remain_file_size, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += remain_file_size; + footer->last_sync_offset += remain_file_size; + + count = footer->offset - footer->last_sync_offset; + config->current_write_file_offset = 0; + fclose(config->log); + config->log = NULL; + /* get always a new file */ + if (dlt_logstorage_prepare_on_msg(config, + file_config, + dev_path, + config->file_size) != 0) + { + dlt_vlog(LOG_ERR, + "%s: failed to prepare log file for file_size\n", __func__); + return DLT_RETURN_ERROR; + } + } + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count; + footer->last_sync_offset = footer->offset; + config->cur_cache_sync = 1; + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_sync_capable_data_to_file + * + * Write the log message to log file + * + * @param config DltLogStorageFilterConfig + * @param index_status check for index is required or not + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_logstorage_sync_capable_data_to_file( + DltLogStorageFilterConfig *config, + int index_status) +{ + int ret = 0; + int index = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; + + if (config == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + + footer = (DltLogStorageCacheFooter *)(config->cache + config->file_size); + if (footer == NULL) + { + dlt_vlog(LOG_ERR, "%s: Cannot retrieve cache information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + }; + count = config->file_size - footer->last_sync_offset; + if (index_status == 1) + { + index = dlt_logstorage_find_dlt_header(config->cache, + footer->last_sync_offset, + count); + } + if (count > 0 && index >=0) + { + ret = fwrite(config->cache + footer->last_sync_offset + index, + count - index, + 1, + config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count - index; + } + config->total_write_count -= count; + footer->last_sync_offset = 0; + + return DLT_RETURN_OK; +} + +/** * 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 config DltLogStorageFilterConfig * @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, +int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size) @@ -544,7 +879,7 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, int ret = 0; struct stat s; - if (config == NULL || file_config == NULL || dev_path == NULL) + if ((config == NULL) || (file_config == NULL) || (dev_path == NULL)) { return -1; } @@ -559,7 +894,9 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, else /* already open, check size and create a new file if needed */ { ret = fstat(fileno(config->log), &s); - if (ret == 0) { + + 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) { @@ -582,6 +919,7 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, ret = -1; } } + return ret; } @@ -590,7 +928,7 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, * * Write the log message. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @param data1 header * @param size1 header size * @param data2 storage header @@ -599,32 +937,37 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, * @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 dlt_logstorage_write_on_msg(DltLogStorageFilterConfig *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) + 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"); @@ -638,14 +981,22 @@ int dlt_logstorage_write_on_msg(DltLogStorageConfigData *config, * * sync data to disk. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig + * @param file_config User configurations for log file + * @param dev_path Storage device path * @param status Strategy flag * @return 0 on success, -1 on error */ -int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status) +int dlt_logstorage_sync_on_msg(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, + int status) { int ret; + file_config = file_config; /* satisfy compiler */ + dev_path = dev_path; + if (config == NULL) { return -1; @@ -671,59 +1022,112 @@ int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status) * files max size reached, open a new file. * Create a memory area to cache data. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @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_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size) { - if (config == NULL || file_config == NULL || dev_path == NULL) + if ((config == NULL) || (file_config == NULL) || (dev_path == NULL)) { return -1; } + /* Combinations allowed: on Daemon_Exit with on Demand,File_Size with Daemon_Exit + * File_Size with on Demand, Specific_Size with Daemon_Exit,Specific_Size with on Demand + * Combination not allowed : File_Size with Specific_Size + */ + /* check for combinations of specific_size and file_size strategy */ + if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) && + (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE)) > 0) + { + dlt_log(LOG_WARNING, "wrong combination of sync strategies \n"); + return -1; + } + log_msg_size = log_msg_size; /* satisfy compiler */ /* create file to sync cache into later */ if (config->log == NULL) { - /* get always a new file */ - if (dlt_logstorage_prepare_on_msg(config, - file_config, - dev_path, - config->file_size) != 0) + + if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) && + (config->specific_size > config->file_size)) { dlt_log(LOG_ERR, - "Cannot prepare log file for ON_DAEMON_EXIT sync\n"); + "Cannot prepare log file for ON_DAEMON_SPECIFIC_SIZE sync\n"); return -1; } + else + { + /* 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; + } + } } - /* create cache */ + if (config->cache == NULL) { - /* check total logstorage cache size */ - if ((g_logstorage_cache_size + - config->file_size + - sizeof(DltLogStorageCacheFooter)) > - g_logstorage_cache_max) + + /* check for sync_specific_size strategy */ + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { - dlt_log(LOG_ERR, "Max size of Logstorage Cache already used."); - return -1; + /* check total logstorage cache size */ + if ((g_logstorage_cache_size + + config->specific_size + + sizeof(DltLogStorageCacheFooter)) > + g_logstorage_cache_max) + { + dlt_log(LOG_ERR, "Max size of Logstorage Cache already used."); + return -1; + } + + /* create cache */ + config->cache = calloc(1, + config->specific_size + + sizeof(DltLogStorageCacheFooter)); + + /* update current used cache size */ + g_logstorage_cache_size = config->specific_size + + sizeof(DltLogStorageCacheFooter); } + else /* other cache strategies */ + { - config->cache = calloc(1, - config->file_size + - sizeof(DltLogStorageCacheFooter)); + /* 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; + } - /* update current used cache size */ - g_logstorage_cache_size = config->file_size + - sizeof(DltLogStorageCacheFooter); + /* create cache */ + 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) { @@ -740,7 +1144,7 @@ int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, * * Write the log message. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @param data1 header * @param size1 header size * @param data2 storage header @@ -749,7 +1153,7 @@ int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, * @param size3 payload size * @return 0 on success, -1 on error */ -int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_write_msg_cache(DltLogStorageFilterConfig *config, unsigned char *data1, int size1, unsigned char *data2, @@ -758,25 +1162,44 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, int size3) { DltLogStorageCacheFooter *footer = NULL; + DltLogStorageUserConfig *uconfig = NULL; + char *dev_path = NULL; int msg_size; int remain_cache_size; void *curr_write_addr = NULL; + int ret = 0; - if (config == NULL || data1 == NULL || size1 < 0 || data2 == NULL || - size2 < 0 || data3 == NULL || size3 < 0 || config->cache == 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) + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { - dlt_log(LOG_ERR, "Cannot retrieve cache footer. Address is NULL\n"); - return -1; + footer = (DltLogStorageCacheFooter *)(config->cache + + config->specific_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->specific_size - footer->offset; + } + else + { + 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; } - - msg_size = size1 + size2 + size3; - remain_cache_size = config->file_size - footer->offset; if (msg_size < remain_cache_size) /* add at current position */ { @@ -785,12 +1208,61 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, } else if (msg_size > remain_cache_size) { - if ((unsigned int) msg_size > config->file_size) + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + { + /*check for message size exceeds cache size for specific_size strategy */ + if ((unsigned int) msg_size > config->specific_size) + { + dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n"); + return -1 ; + } + } + else if ((unsigned int) msg_size > config->file_size) { dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n"); return -1; } + /*sync to file for specific_size or file_size */ + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) > 0) + { + ret = config->dlt_logstorage_sync(config, + uconfig, + dev_path, + DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE); + if (ret != 0) + { + dlt_log(LOG_ERR,"dlt_logstorage_sync: Unable to sync.\n"); + return -1; + } + } + else if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + { + + ret = config->dlt_logstorage_sync(config, + uconfig, + dev_path, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE); + if (ret != 0) + { + dlt_log(LOG_ERR,"dlt_logstorage_sync: Unable to sync.\n"); + return -1; + } + } + else if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_DEMAND) > 0) + { + config->pre_cache_sync = config->cur_cache_sync; + config->cur_cache_sync = 0; + if (config->pre_cache_sync == 0) + { + footer->last_sync_offset = 0; + } + } + /* start writing from beginning */ curr_write_addr = config->cache; footer->offset = msg_size; @@ -799,7 +1271,6 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, else /* message just fits into cache */ { curr_write_addr = (void *)(config->cache + footer->offset); - footer->offset = 0; footer->wrap_around_cnt += 1; } @@ -818,14 +1289,21 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, * * sync data to disk. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig + * @param file_config User configurations for log file + * @param dev_path Storage device path * @param status Strategy flag * @return 0 on success, -1 on error */ -int dlt_logstorage_sync_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_sync_msg_cache(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, int status) { int ret = 0; + unsigned int remain_file_size = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; if (config == NULL) @@ -836,56 +1314,192 @@ int dlt_logstorage_sync_msg_cache(DltLogStorageConfigData *config, /* sync only, if given strategy is set */ if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, status) > 0) { - if (config->log == NULL || config->cache == NULL) + 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); + /* sync cache data to file for specific_size strategies */ - if (footer == NULL) + if ((status == DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) + || ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + && (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND)) + || ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + && (status == DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT))) { - dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); - return -1; - } + footer = (DltLogStorageCacheFooter *)(config->cache + + config->specific_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); + count = footer->offset - footer->last_sync_offset; + /* write ring buffer into file */ + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += footer->offset - footer->last_sync_offset; + remain_file_size = config->file_size - config->current_write_file_offset; - if (ret <= 0) - { - if (ferror(config->log) != 0) + if (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND) + { + footer->last_sync_offset = footer->offset; + } + else { - dlt_log(LOG_CRIT, "Failed to write cache into log file\n"); + footer->last_sync_offset = 0; } + + if (remain_file_size < config->specific_size) + { + config->current_write_file_offset = 0; + /* clean ring buffer and reset footer information */ + memset(config->cache, + 0, + config->specific_size + sizeof(DltLogStorageCacheFooter)); + + /* close the file, a new one will be created when prepare is + * called again */ + + fclose(config->log); + config->log = NULL; + } } - else + /* sync cache data to file for file size strategies*/ + + else if ((status == DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) || + (status == DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) || + ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) > 0) + && (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND))) { - /* force sync */ - if (fsync(fileno(config->log)) != 0) + footer = (DltLogStorageCacheFooter *)(config->cache + + config->file_size); + if (footer == NULL) { - dlt_log(LOG_ERR, "Failed to sync log file\n"); + dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); + return -1; + } + + count = footer->offset - footer->last_sync_offset; + /* write cache to file */ + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += footer->offset - footer->last_sync_offset; + footer->last_sync_offset = footer->offset; + + if ((status != DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) + && (status != DLT_LOGSTORAGE_SYNC_ON_DEMAND)) + { + config->current_write_file_offset = 0; + /* clean ring buffer and reset footer information */ + memset(config->cache, + 0, + config->file_size + sizeof(DltLogStorageCacheFooter)); + + /* close the file, a new one will be created when prepare is + * called again */ + fclose(config->log); + config->log = NULL; } } + /* sync cache to file for on_demand strategy */ - /* do not reinitialize in case of ON_DAEMON_EXIT */ - if (status != DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) + else if (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND) { - /* clean ring buffer and reset footer information */ - memset(config->cache, - 0, - config->file_size + sizeof(DltLogStorageCacheFooter)); + config->sync_from_start = 0; + if ((file_config == NULL) || (dev_path == NULL)) + { + dlt_log(LOG_ERR, "Cannot retrieve user configuration or mount point\n"); + return -1; + } + footer = (DltLogStorageCacheFooter *)(config->cache + + config->file_size); + if (footer == NULL) + { + dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); + return -1; + } + /* check for wrap around is 0 or cache is synced at least once + * in every wrap around */ + + if ((footer->wrap_around_cnt < 1) || (config->cur_cache_sync == 1)) + { + ret = dlt_logstorage_sync_to_file(config, + file_config, + dev_path); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync data to file \n", __func__); + } + } + else + { + remain_file_size = config->file_size - config->current_write_file_offset; + + /* check for total bytes of data need to sync */ + if (footer->offset >= footer->last_sync_offset ) + { + config->total_write_count = config->file_size; + } + else + { + config->total_write_count = config->file_size - footer->last_sync_offset + footer->offset; + } - /* close the file, a new one will be created when prepare is - * called again */ - fclose(config->log); - config->log = NULL; + /* sync data to file if required sync data exceeds remaining file size */ + if (config->total_write_count >= remain_file_size) + { + ret = dlt_logstorage_sync_create_new_file(config, + file_config, + dev_path, + remain_file_size); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync and open new file\n", __func__); + } + + /* sync remaining end of cache data to new file*/ + if (config->sync_from_start == 0) + { + ret = dlt_logstorage_sync_capable_data_to_file(config, 0); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync capable data to file\n", __func__); + } + } + } + /* sync data to file if required sync data less than remaining file size */ + else + { + ret = dlt_logstorage_sync_capable_data_to_file(config, 1); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync capable data\n", __func__); + } + } + /* sync data to file from almost the begin of cache + * if still data needs to sync */ + + if (config->total_write_count > 0) + { + count = footer->offset - footer->last_sync_offset; + ret = fwrite(config->cache + footer->last_sync_offset, + count, + 1, + config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count; + + footer->last_sync_offset += count; + } + config->cur_cache_sync = 1; + } } } diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior.h b/src/offlinelogstorage/dlt_offline_logstorage_behavior.h index f26ce69..68de0ab 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage_behavior.h +++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior.h @@ -53,29 +53,32 @@ #define DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ /* ON_MSG behavior */ -int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, +int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *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); +int dlt_logstorage_write_on_msg(DltLogStorageFilterConfig *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); +int dlt_logstorage_sync_on_msg(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, + int status); /* Logstorage cache functionality */ -int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size); -int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_write_msg_cache(DltLogStorageFilterConfig *config, unsigned char *data1, int size1, unsigned char *data2, @@ -83,7 +86,9 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, unsigned char *data3, int size3); -int dlt_logstorage_sync_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_sync_msg_cache(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, int status); #endif /* DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ */ |