From f4fc0063d0e4bf01e448e9671cab28d4bc287dda Mon Sep 17 00:00:00 2001 From: Christoph Lipka Date: Wed, 13 May 2015 16:26:22 +0900 Subject: Offline Logstorage [3/4]: Core implementation Signed-off-by: Christoph Lipka --- src/offlinelogstorage/dlt_offline_logstorage.c | 1476 ++++++++++++++++++++++++ src/offlinelogstorage/dlt_offline_logstorage.h | 214 ++++ 2 files changed, 1690 insertions(+) create mode 100644 src/offlinelogstorage/dlt_offline_logstorage.c create mode 100644 src/offlinelogstorage/dlt_offline_logstorage.h diff --git a/src/offlinelogstorage/dlt_offline_logstorage.c b/src/offlinelogstorage/dlt_offline_logstorage.c new file mode 100644 index 0000000..ae2071c --- /dev/null +++ b/src/offlinelogstorage/dlt_offline_logstorage.c @@ -0,0 +1,1476 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * DLT offline log storage functionality source file. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Syed Hameed ADIT 2013 - 2015 + * \author Christoph Lipka ADIT 2015 + * + * \file: dlt_offline_logstorage.c + * For further information see http://www.genivi.org/. + * @licence end@ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dlt_offline_logstorage.h" + +typedef enum _line_type_ +{ + LINE_FILTER, + LINE_APP_NAME, + LINE_CTX_NAME, + LINE_LOG_LEVEL, + LINE_FILE_NAME, + LINE_FILE_SIZE, + LINE_FILE_NUMBER, + LINE_ERROR, + LINE_COMMENT +} config_line_type; + +/* Hash map functions */ + +static int dlt_logstorage_hash_create(int num_entries, struct hsearch_data *htab) +{ + memset(htab, 0, sizeof(*htab)); + + if (hcreate_r(num_entries, htab) == 0) + return -1; + + return 0; +} + +static int dlt_logstorage_hash_destroy(struct hsearch_data *htab) +{ + hdestroy_r(htab); + + return 0; +} + +static int dlt_logstorage_hash_add(char *key, void *value, struct hsearch_data *htab) +{ + ENTRY e, *ep; + + memset(&e, 0, sizeof(ENTRY)); + e.key = key; + e.data = value; + + if (hsearch_r(e, ENTER, &ep, htab) == 0) + return -1; + + return 0; +} + +static void *dlt_logstorage_hash_find(char *key, struct hsearch_data *htab) +{ + ENTRY e, *ep; + + e.key = key; + + if (hsearch_r(e, FIND, &ep, htab) != 0) + return ep->data; + else + return NULL; +} + +/* Configuration file parsing helper functions */ + +int dlt_logstorage_count_ids(const char *str) +{ + + if(str == NULL) + return -1; + + // delimiter is: "," + const char *p = str; + int i = 0; + int num = 1; + + while(p[i] != 0) + { + if (p[i] == ',') + num += 1; + + i++; + } + + return num; +} + +/** + * dlt_logstorage_parse_line + * + * Parse each line of dlt_logstorage.conf file + * + * @param input_line line to be parsed + * @param value contains value of line after parsing + * @return line type + */ +static config_line_type dlt_logstorage_parse_line(const char *input_line, char *value) +{ + char line[DLT_OFFLINE_LOGSTORAGE_MAX_LINE_SIZE + 1]; + int len; + int idx; + char tmp_key[DLT_OFFLINE_LOGSTORAGE_MAX_LINE_SIZE]; + + strncpy(line, input_line, DLT_OFFLINE_LOGSTORAGE_MAX_LINE_SIZE); + line[DLT_OFFLINE_LOGSTORAGE_MAX_LINE_SIZE] = '\0'; + + len = (int) strlen(line); + + /* Check if section header is of format "[FILTER" followed by digit and end by "]" */ + if ((strncmp(line, "[FILTER", 7) == 0) && line[len-1] == ']') + { + /* Check for [FILTER] */ + if (line[7] == ']') + { + return LINE_ERROR; + } + + for (idx=7; idx 1 && i < num) + { + strncpy((*names + y + len), ",", 1); + } + y += len + 1; + + i++; + tok = strtok(NULL, ","); + } + + 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. + * + * @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) +{ + int i = 0; + int len = 0; + unsigned long size = 0; + + if (value == NULL) + { + return -1; + } + + *number = 0; + len = strlen(value); + + /* check if string consists of digits only */ + for (i = 0; i < len; i++) + { + if (isdigit(value[i] == 0)) + { + dlt_log(LOG_ERR, "Invalid, is not a number \n"); + return -1; + } + } + + size = strtoul(value, NULL, 10); + + if (size == 0 || size > UINT_MAX) + { + dlt_log(LOG_ERR, "Invalid, is not a number \n"); + return -1; + } + + *number = (unsigned int) size; + + return 0; +} + + +/** + * dlt_logstorage_create_keys + * + * Create keys for hash table + * + * 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. + * + * 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". + * + * @param[in]: appids: string given from filter configuration + * @param[in]: ctxids: 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) +{ + 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; + + if (appids == NULL || ctxids == NULL) + return -1; + + /* discard appid=.* and ctxid=.* */ + if ( strncmp(appids, ".*", 2) == 0 && strncmp(ctxids, ".*", 2) == 0 ) + { + dlt_log(LOG_ERR,"Error: Not allowed combination of wildcards\n"); + return -1; + } + + aids = strdup(appids); + + cids = (char *) calloc(strlen(ctxids)+1, sizeof(char)); + if (cids == NULL) + { + free(aids); + 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; + + /* alloc needed number of keys */ + *(keys) = (char*) calloc(*num_keys * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN, sizeof(char)); + if (*(keys) == NULL) + { + free(aids); + free(cids); + return -1; + } + + /* store all combinations of appid:ctxid in keys */ + for (i = 1; i <= num_appids; 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++) + { + 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 + { + tok_cids = ctxids; + } + + 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*/ + { + 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; + } + } + free(aids); + free(cids); + + return 0; +} + +/** + * dlt_logstorage_device_connected + * + * Initializes DLT Offline Logstorage with respect to device status + * + * @param handle DLT Logstorage handle + * @param device_num device number + * @return 0 on success, -1 on error + */ +int dlt_logstorage_device_connected(DltLogStorage *handle, int device_num) +{ + if(handle == NULL) + { + dlt_log(LOG_ERR, "dlt_logstorage_device_connected Error : Handle error \n"); + 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"); + + dlt_logstorage_device_disconnected(handle); + } + + handle->device_num = device_num; + handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; + handle->config_status = 0; + handle->write_errors = 0; + handle->num_filter_keys = 0; + + handle->config_data = NULL; + handle->filter_keys = NULL; + + return 0; +} + +/** + * dlt_logstorage_free + * + * Free all allocated memory used in log storage handle + * + * @param handle DLT Logstorage handle + * + */ +void dlt_logstorage_free(DltLogStorage *handle) +{ + int i=0; + + dlt_logstorage_hash_destroy(&(handle->config_htab)); + + for(i=0; inum_filter_keys; i++) + { + free(handle->config_data[i].data.file_name); + + if (handle->config_data[i].data.log != NULL) + fclose(handle->config_data[i].data.log); + } + + free(handle->config_data); + handle->config_data = NULL; + + free(handle->filter_keys); + handle->filter_keys = NULL; +} + + +/** + * dlt_logstorage_device_disconnected + * + * De-Initializes DLT Offline Logstorage with respect to device status + * + * @param handle DLT Logstorage handle + * @return 0 on success, -1 on error + * + */ +int dlt_logstorage_device_disconnected(DltLogStorage *handle) +{ + 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); + } + + /* Reset all device status */ + handle->device_num = 0; + handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED; + handle->config_status = 0; + handle->write_errors = 0; + handle->num_filter_keys = 0; + + 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) +{ + int ret = 0; + int num_keys = 0; + char *keys = NULL; + int idx = 0; + + /* Allocate memory for filters */ + if(handle->config_data == NULL) + { + handle->config_data = malloc(sizeof(DltLogStorageConfig) * DLT_OFFLINE_LOGSTORAGE_MAXFILTERS); + memset(handle->config_data, 0, (sizeof(DltLogStorageConfig) * DLT_OFFLINE_LOGSTORAGE_MAXFILTERS)); + + 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); + } + + ret = dlt_logstorage_create_keys(appid, ctxid, &keys, &num_keys); + if (ret != 0) + { + dlt_log(LOG_ERR, "Not able to create keys for hash table\n"); + return -1; + } + + /* hash_add */ + for (idx=0; idx (DLT_OFFLINE_LOGSTORAGE_MAXFILTERS - handle->num_filter_keys)) + { + dlt_log(LOG_ERR, "MAX filters reached \n"); + break; + } + + p_node = &(handle->config_data[handle->num_filter_keys]); + + 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(dlt_logstorage_hash_add(p_node->key, &p_node->data, &(handle->config_htab)) != 0) + { + dlt_log(LOG_ERR, "Adding to hash table failed, returning failure\n"); + + dlt_logstorage_free(handle); + + free(keys); + 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_read_line + * + * This function reads, analyzes the type of configuration line, + * Extracts configuration line type and value 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 line Configuration line + * @param line_number Configuration line number used for logging error line + * @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 + * + */ +int dlt_logstorage_read_line(char *line, int line_number, char **appid, char **ctxid, DltLogStorageConfigData *tmp_data) +{ + char value[DLT_OFFLINE_LOGSTORAGE_MAX_LINE_SIZE] = {'\0'}; + int ret = -1; + + switch (dlt_logstorage_parse_line(line, value)) + { + case LINE_FILTER: + /* Reset all keys and values */ + if (appid != NULL) + { + free(*appid); + *appid = NULL; + } + + if (ctxid != NULL) + { + free(*ctxid); + *ctxid = NULL; + } + + ret = DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT; + break; + + case LINE_APP_NAME: + ret = dlt_logstorage_read_list_of_names(appid, value); + if (ret == 0) + ret = DLT_OFFLINE_LOGSTORAGE_APP_INIT; + break; + + case LINE_CTX_NAME: + ret = dlt_logstorage_read_list_of_names(ctxid, value); + if (ret == 0) + ret = DLT_OFFLINE_LOGSTORAGE_CTX_INIT; + break; + + case LINE_LOG_LEVEL: + ret = dlt_logstorage_read_log_level(&(tmp_data->log_level), value); + if (ret == 0) + ret = DLT_OFFLINE_LOGSTORAGE_LOG_LVL_INIT; + break; + + case LINE_FILE_NAME: + ret = dlt_logstorage_read_file_name(&(tmp_data->file_name), value); + if (ret == 0) + ret = DLT_OFFLINE_LOGSTORAGE_NAME_INIT; + break; + + case LINE_FILE_SIZE: + ret = dlt_logstorage_read_number(&(tmp_data->file_size), value); + if (ret == 0) + ret = DLT_OFFLINE_LOGSTORAGE_SIZE_INIT; + break; + + case LINE_FILE_NUMBER: + ret = dlt_logstorage_read_number(&(tmp_data->num_files), value); + if (ret == 0) + ret = DLT_OFFLINE_LOGSTORAGE_NUM_INIT; + break; + + case LINE_ERROR: + break; + + default: + ret = -1; + break; + } + if (ret == -1) + { + char error_str[DLT_DAEMON_TEXTBUFSIZE]; + snprintf(error_str,DLT_DAEMON_TEXTBUFSIZE,"Error in configuration file line number : %d line : %s Invalid\n",line_number, line); + dlt_log(LOG_ERR, error_str); + } + return ret; +} + +/** + * dlt_logstorage_trim_line + * + * Remove \n and spaces at end of line + * + * @param line File line + * + */ +void dlt_logstorage_trim_line(char *line) +{ + int len = 0; + + /* Consider \n and spaces at end of line */ + len = (int) strlen(line) -1; + while ((len >= 0) && ((line[len] == '\n') || (isspace(line[len])))) + { + line[len]=0; + len--; + } + len = (int) strlen(line) -1; +} + +/** + * 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 + * wildcards used for application id or context id, the hash table + * key consists of none wildcard value, e.g. appid=.*, cxtid=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 + */ +int dlt_logstorage_load_config(DltLogStorage *handle) +{ + FILE *config_file = NULL; + char config_file_name[PATH_MAX + 1] = {'\0'}; + char line[DLT_OFFLINE_LOGSTORAGE_MAX_LINE_SIZE] = {'\0'}; + int ret = 0; + int is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT; + char *appid = NULL; + char *ctxid = NULL; + DltLogStorageConfigData tmp_data; + int line_number = 0; + + memset(&tmp_data, 0, sizeof(DltLogStorageConfigData)); + + /* Check if handle is NULL or already initialized or already configured */ + 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"); + return -1; + } + + + if(snprintf(config_file_name, PATH_MAX, "%s%d/%s", + DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH, + handle->device_num, + 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"); + return -1; + } + + if ((config_file = fopen(config_file_name, "r")) == NULL) + { + dlt_log(LOG_ERR, "Cannot open dlt_logstorage.conf file.\n"); + return -1; + } + + if (dlt_logstorage_hash_create(DLT_OFFLINE_LOGSTORAGE_MAXFILTERS, &(handle->config_htab)) != 0) + { + fclose(config_file); + dlt_log(LOG_ERR, "dlt_logstorage_load_config Error : Hash creation failed\n"); + return -1; + } + + /* Read configuration file line by line */ + while (fgets(line, DLT_OFFLINE_LOGSTORAGE_MAX_LINE_SIZE, config_file) != NULL) + { + line_number += 1; + + /* Ignore empty line, comment line */ + if (line[0] == '#' || line[0] == ';' || line[0] == '\n' || line[0] == '\0') + continue; + + /* Consider \n and spaces at end of line */ + dlt_logstorage_trim_line(line); + + ret = dlt_logstorage_read_line(line, line_number, &appid, &ctxid, &tmp_data); + + /* Check if filter tag was read */ + if ((ret != -1) && (ret == DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT)) + { + is_filter_set = ret; + if (tmp_data.file_name != NULL) + free(tmp_data.file_name);/* not used anymore */ + }/* Check if complete filter is read */ + else if ((ret != -1) && DLT_OFFLINE_LOGSTORAGE_IS_FILTER_PRESENT(is_filter_set)) + { + is_filter_set |= ret; + } + else + { + /* Do not log error here, uninitatilze filter */ + is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT; + } + /* If all items of the filter is populated store them */ + if (DLT_OFFLINE_LOGSTORAGE_FILTER_INITIALIZED(is_filter_set)) + { + ret = dlt_logstorage_prepare_table(handle, appid, ctxid, &tmp_data); + if (ret != 0) + break; + + is_filter_set = DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT; + } + } + + if (ret == 0) + handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; + + free(appid); + free(ctxid); + free(tmp_data.file_name); + fclose(config_file); + + return ret; +} + +/** + * 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 + * + * @param handle DltLogstorage handle + * @param key key to search for in Hash MAP + * @return log level on success:, -1 on error + */ +int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key) +{ + DltLogStorageConfigData *config; + + /* 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 -1; + } + + config = (DltLogStorageConfigData *)dlt_logstorage_hash_find(key, &(handle->config_htab)); + + return config->log_level; +} + +/** + * dlt_logstorage_get_config + * + * Obtain the configuration data of all filters for provided apid and ctid + * For a given apid and ctid, there can be 3 possiblities of configuration + * 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 + */ +DltLogStorageConfigData **dlt_logstorage_get_config(DltLogStorage *handle, char *apid, char *ctid, int *num_config) +{ + DltLogStorageConfigData **config = NULL; + DltLogStorageConfigData *ptr_config = NULL; + char key[3][DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN]= {{'\0'},{'\0'},{'\0'}}; + int i=0; + int apid_len = 0; + int ctid_len = 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 ((apid == NULL) || (ctid == NULL)) + return NULL; + + /* Check if num_config passed is non zero */ + if (*(num_config) !=0) + *(num_config) = 0; + + /* 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); + + ctid_len = strlen(ctid); + if (ctid_len > DLT_ID_SIZE) + ctid_len = DLT_ID_SIZE; + + strncpy(key[1], ":", 1); + strncat(key[1], ctid, ctid_len); + + strncpy(key[2], apid, apid_len); + strncat(key[2], ":", 1); + strncat(key[2], ctid, ctid_len); + + config = (DltLogStorageConfigData **)calloc(3, sizeof(DltLogStorageConfigData *)); + + if (config == NULL) + return NULL; + + /* Search the list thrice with keys as -apid: , :ctid and apid:ctid */ + for (i=0; i<3; i++) + { + ptr_config = (DltLogStorageConfigData *)dlt_logstorage_hash_find(key[i], &(handle->config_htab)); + if (ptr_config != NULL) + { + config[*(num_config)] = ptr_config; + *(num_config) += 1; + } + } + + if (*(num_config) == 0) + { + free(config); + return NULL; + } + + return config; +} + +/** + * 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 + * - for each found structure, compare message log level with configured one + * + * @param appid application id + * @param ctxid context id + * @param log_level Log level of message + * @param num Number of found configurations + * @return list of filters received from hashmap or NULL + */ +DltLogStorageConfigData **dlt_logstorage_filter(DltLogStorage *handle, char *appid, char *ctxid, int log_level, int *num) +{ + DltLogStorageConfigData **config = NULL; + int i = 0; + + /* filter on names: find DltLogStorageConfigData structures */ + config = dlt_logstorage_get_config(handle, appid, ctxid, num); + + if (config == NULL) + { + *num = 0; + return NULL; + } + + for (i = 0; i < *num; i++) + { + /* filter on log level */ + if (log_level > config[i]->log_level) + { + config[i] = NULL; + } + } + + return config; +} + +/** + * dlt_logstorage_log_file_name + * + * Create log file name in form + * __.dlt + * + * filename: given in configuration file + * timestamp: yyyy-mm-dd-hh-mm-ss + * index: 3 digit number, beginning with 001 + * + * @param log_file_name contains complete logfile name + * @param name file name given in configuration file + * @param idx continous index of log files + * @ return 0 on success, -1 on error + */ +void dlt_logstorage_log_file_name(char *log_file_name, char *name, int idx) +{ + char file_index[4] = {0}; + char stamp[DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1] = {0}; + + time_t t = time(NULL); + struct tm *tm_info = localtime(&t); + + sprintf(stamp, "_%04d%02d%02d-%02d%02d%02d", 1900 + tm_info->tm_year, 1 + tm_info->tm_mon, + tm_info->tm_mday, tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec); + + sprintf(file_index, "%03d", idx); + + // create log file name + memset(log_file_name, 0, DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN * sizeof(char)); + strcat(log_file_name, name); + strcat(log_file_name, "_"); + strcat(log_file_name, file_index); + strcat(log_file_name, stamp); + strcat(log_file_name, ".dlt"); +} + +/** + * dlt_logstorage_storage_dir_info + * + * Get information of storage directory. Return newest, oldest log and number of log files + * + * @param path Path to storage directory + * @param file_name Base name of log files + * @param oldest Oldest log file + * @param newest Newest log file + * @return number of logfiles on success, -1 on error + */ +int dlt_logstorage_storage_dir_info(char *path, char *file_name, char *newest, char *oldest) +{ + int i = 0; + int num = 0; + int cnt = 0; + struct dirent **files = {0}; + char *tmp_old = NULL; + char *tmp_new = NULL; + + if (path == NULL || file_name == NULL || newest == NULL || oldest == NULL) + { + return -1; + } + + cnt = scandir(path, &files, 0, alphasort); + + if (cnt < 0) + { + return -1; + } + + for (i = 0; i < cnt; i++) + { + int len = 0; + len = strlen(file_name); + if ((strncmp(files[i]->d_name, file_name, len) == 0) && (files[i]->d_name[len] == '_')) + { + num++; + if (tmp_old == NULL || strcmp(tmp_old, files[i]->d_name) > 0) + { + tmp_old = files[i]->d_name; + } + + if (tmp_new == NULL || strcmp(tmp_new, files[i]->d_name) < 0) + { + tmp_new = files[i]->d_name; + } + } + } + + if (num > 0) + { + if (tmp_old != NULL) + { + if (strlen(tmp_old) < DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN) + { + strncpy(oldest, tmp_old, DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN); + } + else + { + dlt_log(LOG_ERR, "Found log file name too long. New file will be created."); + } + } + if (tmp_new != NULL) + { + if (strlen(tmp_old) < DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN) + { + strncpy(newest, tmp_new, DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN); + } + else + { + dlt_log(LOG_ERR, "Found log file name too long. New file will be created."); + } + } + } + + /* free scandir result */ + for (i = 0; i < cnt; i++) + { + free(files[i]); + } + free(files); + + return num; +} + + +/** + * dlt_logstorage_get_idx_of_log_file + * + * Generate an index of the log file to be used. + * + * @param file file name to extract the index from + * @return index on success, -1 if no index is found + */ +int dlt_logstorage_get_idx_of_log_file(char *file) +{ + int idx = -1; + char *endptr; + + /* index is retrived from file name */ + idx = (int) strtol(&file[strlen(file)-DLT_OFFLINE_LOGSTORAGE_INDEX_OFFSET], &endptr, 10) + 1; + + if(endptr == file || idx <= 0) + { + dlt_log(LOG_ERR, "Unable to calculate index from log file name. Reset index to 001.\n"); + idx = -1; + } + + return idx; +} + +/** + * dlt_logstorage_open_log_file + * + * Open a log file. Check storage directory for already created files and open the oldest if + * there is enough space to store at least msg_size. + * Otherwise create a new file, but take configured max number of files into account and remove + * the oldest file if needed. + * + * @param config DltLogStorageConfigData + * @param dev_num Number of storage device needed for storage dir path + * @param msg_size Size of incoming message + * @return 0 on succes, -1 on error + */ +int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, int dev_num, int msg_size) +{ + int ret = 0; + int idx = 0; + char absolute_file_path[DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN] = {0}; + char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN] = {0}; + char newest[DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN] = {0}; + char oldest[DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN] = {0}; + unsigned int num_log_files = 0; + struct stat s; + + if (config == NULL) + { + return -1; + } + + /* check if there are already files */ + sprintf(storage_path, "%s%d/", DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH, dev_num); + + ret = dlt_logstorage_storage_dir_info(storage_path, config->file_name, + newest, oldest); + + if (ret == -1) + { + dlt_log(LOG_ERR, "dlt_logstorage_create_log_file: Unable to scan storage directory.\n"); + return -1; + } + + /* positive number in case of no error */ + num_log_files = (unsigned int) ret; + + if (strlen(newest) == 0) /* need new file*/ + { + idx += 1; + + dlt_logstorage_log_file_name(newest, config->file_name, idx); + + /* concatenate path and file and open absolute path */ + strcat(absolute_file_path, storage_path); + strcat(absolute_file_path, newest); + config->log = fopen(absolute_file_path, "a+"); + + } + else /* newest file available*/ + { + strcat(absolute_file_path, storage_path); + strcat(absolute_file_path, newest); + + ret = stat(absolute_file_path, &s); + + /* if size is enough, open it */ + if (ret == 0 && s.st_size + msg_size < config->file_size) + { + config->log = fopen(absolute_file_path, "a+"); + } + else /* no space in file or file stats cannot be read */ + { + /* get index of newest log file */ + idx = dlt_logstorage_get_idx_of_log_file(newest); + + /* wrap around if max index is reached or an error occured while calculating index from file name */ + if (idx >= DLT_OFFLINE_LOGSTORAGE_MAX_INDEX || idx < 0) + { + idx = 1; + } + + dlt_logstorage_log_file_name(newest, config->file_name, idx); + + /* concatenate path and file and open absolute path */ + memset(absolute_file_path, 0, sizeof(absolute_file_path)/sizeof(char)); + strcat(absolute_file_path, storage_path); + strcat(absolute_file_path, newest); + config->log = fopen(absolute_file_path, "a+"); + + num_log_files += 1; + /* check if number of log files exceeds configured max value */ + if (num_log_files > config->num_files) + { + /* delete oldest */ + memset(absolute_file_path, 0, sizeof(absolute_file_path)/sizeof(char)); + strcat(absolute_file_path, storage_path); + strcat(absolute_file_path, oldest); + remove(absolute_file_path); + } + } + } + + if (config->log == NULL) + { + dlt_log(LOG_ERR, "dlt_logstorage_create_log_file: Unable to open log file.\n"); + return -1; + } + + return ret; +} + +/** + * dlt_logstorage_prepare_log_file + * + * Prepare the log file for a certain filer. If log file not open or log files max size reached, + * open a new file. + * + * @param config DltLogStorageConfigData + * @param dev_num Numer of storage device + * @param log_msg_size Size of log message + * @return 0 on success, -1 on error + */ +int dlt_logstorage_prepare_log_file(DltLogStorageConfigData *config, int dev_num, int log_msg_size) +{ + int ret = 0; + struct stat s; + + if (config == NULL) + { + return -1; + } + + if (config->log == NULL) /* open a new log file */ + { + ret = dlt_logstorage_open_log_file(config, dev_num, log_msg_size); + } + else /* already open, check size and create a new file if needed */ + { + ret = fstat(fileno(config->log), &s); + if (ret == 0) { + /* check if adding new data do not exceed max file size */ + if (s.st_size + log_msg_size >= config->file_size) + { + fclose(config->log); + config->log = NULL; + ret = dlt_logstorage_open_log_file(config, dev_num, log_msg_size); + } + else /*everything is prepared */ + { + ret = 0; + } + } + else + { + dlt_log(LOG_ERR, "dlt_logstorage_prepare_log_file: Unable to determine file stats.\n"); + ret = -1; + } + } + return ret; +} + +/** + * dlt_logstorage_write + * + * Write a message to one or more configured log files, based on filter configuration. + * + * @param handle DltLogStorage handle + * @param appid Application id of sender + * @param ctxid Context id of sender + * @param log_level log_level of message to store + * @param data1 Data buffer of message header + * @param size1 Size of message header buffer + * @param data2 Data buffer of message body + * @param size2 Size of message body + * @return 0 on success or write errors < max write errors, -1 on error + */ +int dlt_logstorage_write(DltLogStorage *handle, char *appid, char *ctxid, int log_level, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3) +{ + DltLogStorageConfigData **config = NULL; + int i = 0; + int ret = 0; + int num = 0; + int err = 0; + + if (handle == NULL || handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED || handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) + { + return 0; + } + + /* check if log message need to be stored in a certain device based on filter config */ + config = dlt_logstorage_filter(handle, appid, ctxid, log_level, &num); + + if (config != NULL) + { + /* store log message in every found filter */ + while (i < num) + { + if(config[i] != NULL) + { + /* prepare logfile (create and/or open)*/ + ret = dlt_logstorage_prepare_log_file(config[i], handle->device_num, size1 + size2 + size3); + if (ret == 0) /* log data (write) */ + { + fwrite(data1, 1, size1, config[i]->log); + fwrite(data2, 1, size2, config[i]->log); + fwrite(data3, 1, size3, config[i]->log); + ret = ferror(config[i]->log); + + if (ret != 0) + { + 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 log to file.\n"); + } + else + { + /* flush to be sure log is stored on device */ + ret = fflush(config[i]->log); + if (ret != 0) + { + dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to flush log to file.\n"); + } + } + } + else + { + dlt_log(LOG_ERR, "dlt_logstorage_write: Unable to prepare log file.\n"); + } + } + i++; + } + + free(config); + } + + return err; +} diff --git a/src/offlinelogstorage/dlt_offline_logstorage.h b/src/offlinelogstorage/dlt_offline_logstorage.h new file mode 100644 index 0000000..bec4fe3 --- /dev/null +++ b/src/offlinelogstorage/dlt_offline_logstorage.h @@ -0,0 +1,214 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * DLT offline log storage functionality header file. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Syed Hameed ADIT 2013 - 2015 + * \author Christoph Lipka ADIT 2015 + * + * \file: dlt_offline_logstorage.h + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/******************************************************************************* +** ** +** SRC-MODULE: dlt_offline_logstorage.h ** +** ** +** TARGET : linux ** +** ** +** PROJECT : DLT ** +** ** +** AUTHOR : Syed Hameed shameed@jp.adit-jv.com ** +** Christoph Lipka clipka@jp.adit-jv.com ** +** PURPOSE : ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +/******************************************************************************* +** Author Identity ** +******************************************************************************** +** ** +** Initials Name Company ** +** -------- ------------------------- ---------------------------------- ** +** sh Syed Hameed ADIT ** +** cl Christoph Lipka ADIT ** +*******************************************************************************/ + +#ifndef DLT_OFFLINE_LOGSTORAGE_H +#define DLT_OFFLINE_LOGSTORAGE_H + +#include +#include "dlt_common.h" +#include "dlt-daemon_cfg.h" + +#define DLT_OFFLINE_LOGSTORAGE_MAXFILTERS 100 /* Maximum entries in hashmap */ + +#define DLT_OFFLINE_LOGSTORAGE_INIT_DONE 1 /* For device configuration status */ +#define DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED 1 +#define DLT_OFFLINE_LOGSTORAGE_FREE 0 +#define DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED 0 +#define DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE 1 + +#define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN 10 /* 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_MAX_LINE_SIZE 80 /* Maximum length of a line in configuration file */ + +#define DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN 4 +#define DLT_OFFLINE_LOGSTORAGE_INDEX_LEN 3 +#define DLT_OFFLINE_LOGSTORAGE_MAX_INDEX 999 +#define DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN 16 +#define DLT_OFFLINE_LOGSTORAGE_INDEX_OFFSET (DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + \ + DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + \ + DLT_OFFLINE_LOGSTORAGE_INDEX_LEN) +#define DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN (DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + \ + DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + \ + DLT_OFFLINE_LOGSTORAGE_INDEX_LEN + \ + DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + 1) + +#define DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT 0 +#define DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT (1<<6) +#define DLT_OFFLINE_LOGSTORAGE_APP_INIT (1<<5) +#define DLT_OFFLINE_LOGSTORAGE_CTX_INIT (1<<4) +#define DLT_OFFLINE_LOGSTORAGE_LOG_LVL_INIT (1<<3) +#define DLT_OFFLINE_LOGSTORAGE_NAME_INIT (1<<2) +#define DLT_OFFLINE_LOGSTORAGE_SIZE_INIT (1<<1) +#define DLT_OFFLINE_LOGSTORAGE_NUM_INIT 1 +#define DLT_OFFLINE_LOGSTORAGE_FILTER_INIT 0x7F + +#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_DIR_PATH "/tmp/dltlogs/dltlogsdev" +#define DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME "dlt_logstorage.conf" + +/* +3 because of device number and \0 */ +#define DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN (DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN + \ + DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 3) + +#define DLT_OFFLINE_LOGSTORAGE_MAX(A, B) ((A) > (B) ? (A) : (B)) +#define DLT_OFFLINE_LOGSTORAGE_MIN(A, B) ((A) < (B) ? (A) : (B)) + +#define DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS 5 + +typedef struct +{ + /* filter section */ + int log_level; /* Log level number configured for filter */ + char *file_name; /* File name for log storage configured for filter */ + unsigned int file_size; /* MAX FIle size of storage file configured for filter */ + unsigned int num_files; /* MAX number of storage files configured for filters */ + FILE *log; /* current open log file */ +}DltLogStorageConfigData; + + +typedef struct +{ + char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN]; /* Keys stored in hash table */ + DltLogStorageConfigData data; /* Data stored in hash table */ +}DltLogStorageConfig; + + +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 */ + int num_filter_keys; /* Number of keys */ + unsigned int device_num; /* Number of device to be used */ + unsigned int connection_type; /* Type of connection */ + unsigned int config_status; /* Status of configuration */ + int write_errors; /* number of write errors */ +}DltLogStorage; + +/** + * dlt_logstorage_device_connected + * + * Initializes DLT Offline Logstorage with respect to device status + * + * + * @param handle DLT Logstorage handle + * @param device_num device number + * @return 0 on success, -1 on error + */ +extern int dlt_logstorage_device_connected(DltLogStorage *handle, int device_num); + +/** + * 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 + * + * @param handle DLT Logstorage handle + * @return 0 on success, -1 on error + */ +extern int dlt_logstorage_device_disconnected(DltLogStorage *handle); +/** + * dlt_logstorage_get_config + * + * Obtain the configuration data of all filters for provided apid and ctid + * For a given apid and ctid, there can be 3 possiblities of configuration + * 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 + */ +extern DltLogStorageConfigData **dlt_logstorage_get_config(DltLogStorage *handle, char *apid, char *ctid, int *num_config); +/** + * 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 + * + * @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); + +/** + * dlt_logstorage_write + * + * Write a message to one or more configured log files, based on filter configuration. + * + * @param handle DltLogStorage handle + * @param appid Application id of sender + * @param ctxid Context id of sender + * @param log_level log_level of message to store + * @param data1 Data buffer of message header + * @param size1 Size of message header buffer + * @param data2 Data buffer of message body + * @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, char *appid, char *ctxid, int loglevel, unsigned char *data1, int size1, unsigned char *data2, int size2, unsigned char *data3, int size3); +#endif /* DLT_OFFLINE_LOGSTORAGE_H */ -- cgit v1.2.1