From 3cfb292aa43774428ce8dfe120fe16785942b086 Mon Sep 17 00:00:00 2001 From: ManikandanChockalingam Date: Thu, 15 Nov 2018 13:52:21 +0100 Subject: Log storage - Updates (#82) - improvements and refactor key creation - Sync strategies added Signed-off-by: ManikandanC Signed-off-by: Saya Sugiura Signed-off-by: S. Hameed Signed-off-by: Ravi Sankar P Signed-off-by: Christoph Lipka --- src/offlinelogstorage/dlt_offline_logstorage.c | 2383 ++++++++++++++++-------- 1 file changed, 1596 insertions(+), 787 deletions(-) (limited to 'src/offlinelogstorage/dlt_offline_logstorage.c') 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; + } + + tmp = calloc(1, sizeof(DltLogStorageFilterList)); + + if (tmp == NULL) + { + return -1; + } - memset(&e, 0, sizeof(ENTRY)); - e.key = key; - e.data = value; + tmp->key = strdup(key); + tmp->next = NULL; + tmp->data = calloc(1, sizeof(DltLogStorageFilterConfig)); - if (hsearch_r(e, ENTER, &ep, htab) == 0) + 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++; } @@ -108,21 +291,43 @@ int dlt_logstorage_count_ids(const char *str) return num; } +/** + * 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++; @@ -177,109 +389,20 @@ int dlt_logstorage_read_list_of_names(char **names, char *value) return 0; } -/** - * 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) + { + strncpy(curr_str, ecuid, strlen(ecuid)); + strncat(curr_str, ":", 1); + } + else { - free(*ecuid); - *ecuid = NULL; + 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; - } - - *num_keys = 0; + 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; + } - 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 - { - tok_aids = aids; - } - - for (j = 1; j <= num_ctxids; j++) + curr_apid = apid_list + (i * (DLT_ID_SIZE + 1)); + for (j = 0; j < num_ctids; j++) { - if (num_ctxids > 1 && j == 1) - { - save_cids = NULL; - memcpy(cids, ctxids, strlen(ctxids)); - tok_cids = strtok_r(cids, ",", &save_cids); - } - else if (num_ctxids > 1 && j > 0) - { - tok_cids = strtok_r(NULL, ",", &save_cids); - } - else + curr_ctid = ctid_list + (j * (DLT_ID_SIZE + 1)); + if (strncmp(curr_apid, ".*", 2) == 0) /* only context id matters */ { - tok_cids = ctxids; + dlt_logstorage_create_keys_only_ctid(ecuid, curr_ctid, curr_key); } - - if (strncmp(tok_aids, ".*", 2) == 0) /* only context id matters */ - { - 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); - } - else if (strncmp(tok_cids,".*", 2) == 0) /* only application id matters*/ + else if (strncmp(curr_ctid, ".*", 2) == 0) /* only app 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); + dlt_logstorage_create_keys_only_apid(ecuid, curr_apid, curr_key); } - else /* key is combination of both */ + else /* key is combination of all */ { - 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); + dlt_logstorage_create_keys_multi(ecuid, curr_apid, curr_ctid, curr_key); } - 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] * - * @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; inum_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; + } +} - free(handle->filter_keys); - handle->filter_keys = NULL; +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; + } + + 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; idxfile_name != NULL) { - DltLogStorageConfig *p_node = NULL; + free(config->file_name); + config->file_name = NULL; + } + + len = strlen(value); - if (num_keys > (DLT_OFFLINE_LOGSTORAGE_MAXFILTERS - handle->num_filter_keys)) + /* 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; + } - p_node = &(handle->config_data[handle->num_filter_keys]); + return 0; +} - 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) +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; + } + + 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) + if ((config == NULL) || (value == NULL) || (value[0] == '\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; + return -1; } - else if (strncmp(filter_key, "LogLevel", strlen("LogLevel")) == 0) + + if (config->ecuid != NULL) { - ret = dlt_logstorage_read_log_level(&(tmp_data->log_level), filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_LOG_LVL_INIT; + free(config->ecuid); + config->ecuid = NULL; } - else if (strncmp(filter_key, "FileSize", strlen("FileSize")) == 0) + + len = strlen(value); + config->ecuid = calloc((len + 1), sizeof(char)); + if (config->ecuid == NULL) { - ret = dlt_logstorage_read_number(&(tmp_data->file_size), filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_SIZE_INIT; + return -1; } - else if (strncmp(filter_key, "File", strlen("File")) == 0) + strncpy(config->ecuid, value, len); + + 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 + } +}; +/** + * 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 + */ +STATIC int dlt_logstorage_check_param(DltLogStorageFilterConfig *config, + DltLogstorageFilterConfType ctype, + char *value) +{ + if ((config == NULL) || (value == NULL)) { - ret = dlt_logstorage_read_file_name(&(tmp_data->file_name), filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_NAME_INIT; + return -1; } - else if (strncmp(filter_key, "NOFiles", strlen("NOFiles")) == 0) + + if (ctype < DLT_LOGSTORAGE_FILTER_CONF_COUNT) { - ret = dlt_logstorage_read_number(&(tmp_data->num_files), filter_value); - if (ret == 0) - ret = DLT_OFFLINE_LOGSTORAGE_NUM_INIT; + return filter_cfg_entries[ctype].func(config, value); } - else if (strncmp(filter_key, "SyncBehavior", strlen ("SyncBehavior")) == 0) + + 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)) { - ret = dlt_logstorage_set_sync_strategy(&(tmp_data->sync), filter_value); - if (ret == 0) - { - return DLT_OFFLINE_LOGSTORAGE_SYNC_BEHAVIOR; - } + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; } - else if (strncmp(filter_key, "EcuID", strlen("EcuID")) == 0) + + /* Branch based on section name, no complete string compare needed */ + if (strncmp(sec_name, + DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION, + config_sec_len) == 0) { - ret = dlt_logstorage_set_ecuid(&(tmp_data->ecuid), filter_value); - if (ret == 0) + if (filter_cfg_entries[index].key != NULL) { - return DLT_OFFLINE_LOGSTORAGE_ECUID; - } - } - else - { - /* Invalid filter key */ - ret = -1; - dlt_log(LOG_ERR, "Invalid filter key"); - } + ret = dlt_config_file_get_value(config_file, sec_name, + filter_cfg_entries[index].key, + value); - if (ret == -1) - dlt_log(LOG_ERR, "Error in configuration file\n"); - - return ret; -} - -/** - * dlt_logstorage_validate_filter_name - * - * Validates if the provided filter name is as required [FILTER] - * - * @param name Filter name - * @return 0 on success, -1 on error - * - */ -int dlt_logstorage_validate_filter_name(char *name) -{ - int len = 0; - int idx = 0; + if ((ret != 0) && (filter_cfg_entries[index].is_opt == 0)) + { + 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 (name == NULL) + 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; + } + } + else + { + return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; + } + } + else if (strncmp(sec_name, + DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION, + storage_sec_len) == 0) { - return -1; + 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; + } } - - len = strlen(name); - - /* Check if section header is of format "FILTER" followed by a number */ - if (strncmp(name, - DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION, - strlen(DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION)) == 0) + else if ((strncmp(sec_name, + DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION, + control_sec_len) == 0)) { - for (idx=6; idx %s : %s\n", + sec_name, filter_nonverbose_control_entries[index].key, + value); + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; } } - return 0; + else + { + return DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE; + } } - return -1; + else + { + dlt_log(LOG_ERR, "Error: Section name not valid \n"); + return DLT_OFFLINE_LOGSTORAGE_FILTER_ERROR; + } + + return 0; } -void dlt_logstorage_filter_set_strategy(DltLogStorageConfigData *config, - int strategy) +STATIC int dlt_logstorage_setup_table(DltLogStorage *handle, + DltLogStorageFilterConfig *tmp_data) { - if (config == NULL) - { - return; - } + int ret = 0; - if (strategy == DLT_LOGSTORAGE_SYNC_ON_MSG) /* file based */ - { - 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 */ + /* 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) { - 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_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) + { + return ret; + } + + if (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_CONTINUE) { - 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; + continue; } - /* Validate filter value */ - if (ret == 0) + /* check value and store temporary */ + ret = dlt_logstorage_check_param(&tmp_data, i, value); + if (ret != 0) { - 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)) + 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) { - dlt_log(LOG_ERR, "dlt_logstorage_load_config Error : Hash creation failed\n"); + handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; + return 1; + } + else if (ret != 0) + { + 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); - /* Search the list thrice with keys as -apid: , :ctid and apid:ctid */ - for (i=0; i<3; i++) + /* ecu:: */ + strncpy(key[6], ecuid, ecuid_len); + strncat(key[6], ":", 1); + strncat(key[6], ":", 1); + + /* 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; + + if ((handle == NULL) || (config == NULL) || (ecuid == NULL)) + { + return -1; + } - /* filter on names: find DltLogStorageConfigData structures */ - config = dlt_logstorage_get_config(handle, appid, ctxid, num); + /* filter on names: find DltLogStorageFilterConfig structures */ + num = dlt_logstorage_get_config(handle, config, apid, ctid, ecuid); - if (config == NULL) + 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) + { + 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) */ { - if(config[i] != NULL) + 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; inum_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; -- cgit v1.2.1