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 --- CMakeLists.txt | 2 +- doc/dlt_offline_logstorage.txt | 47 +- include/dlt/dlt_protocol.h | 3 + src/console/logstorage/dlt-logstorage-ctrl.c | 22 + src/console/logstorage/dlt-logstorage-udev.c | 28 +- src/daemon/dlt-daemon.c | 13 +- src/daemon/dlt_daemon_client.c | 166 +- src/daemon/dlt_daemon_common.c | 8 +- src/daemon/dlt_daemon_offline_logstorage.c | 1127 ++++++--- src/daemon/dlt_daemon_offline_logstorage.h | 121 +- src/gateway/dlt_gateway.c | 29 + src/gateway/dlt_gateway.h | 12 + src/offlinelogstorage/dlt_offline_logstorage.c | 2383 +++++++++++++------- src/offlinelogstorage/dlt_offline_logstorage.h | 141 +- .../dlt_offline_logstorage_behavior.c | 886 ++++++-- .../dlt_offline_logstorage_behavior.h | 29 +- src/shared/dlt_common.c | 2 +- 17 files changed, 3632 insertions(+), 1387 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6445d06..cf1be9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,7 +203,7 @@ if(WITH_DLT_LOGSTORAGE_CTRL_UDEV) endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV) if(WITH_DLT_LOGSTORAGE_CTRL_PROP) - add_definitions( -DDLT_LOGSTORAGE_CTRL_PROP) + add_definitions( -DHAS_PROPRIETARY_LOGSTORAGE) endif(WITH_DLT_LOGSTORAGE_CTRL_PROP) if (WITH_DLT_FATAL_LOG_TRAP) diff --git a/doc/dlt_offline_logstorage.txt b/doc/dlt_offline_logstorage.txt index 49a2a30..1673dfe 100644 --- a/doc/dlt_offline_logstorage.txt +++ b/doc/dlt_offline_logstorage.txt @@ -36,18 +36,20 @@ Filter configuration For DLT daemon to store logs the configuration file named “dlt_logstorage.conf” should be present in external storage or internal storage device. The format is defined as follows: ---- -[Filter] # filter configration name -LogAppName= # Name of application to store logs from. Multiple applications can be separated by "," and ".*" denotes all applications -ContextName= # Name or names of contexts to store logs from. Multiple contexts can be separated by "," and ".*" denotes all contexts of the application -LogLevel= # Define log level, e.g. DLT_LOG_INFO or DLT_LOG_FATAL -File= # Base name of the created files that containing the logs, e.g. "example". For further file naming scheme configurations see man dlt.conf -FileSize= # Maximum file size in bytes -NOFiles= # Number of created files before oldest is deleted and a new one is created -SyncBehavior= # Specify sync strategy. Default: Sync'ed after every message. See Logstorage Rinbuffer Implementation below. -EcuID= # Specify ECU identifier +[Filter] # filter configration name +LogAppName= # Name of application to store logs from. Multiple applications can be separated by "," and ".*" denotes all applications +ContextName= # Name or names of contexts to store logs from. Multiple contexts can be separated by "," and ".*" denotes all contexts of the application +LogLevel= # Define log level, e.g. DLT_LOG_INFO or DLT_LOG_FATAL +File= # Base name of the created files that containing the logs, e.g. "example". For further file naming scheme configurations see man dlt.conf +FileSize= # Maximum file size in bytes +NOFiles= # Number of created files before oldest is deleted and a new one is created +SyncBehavior= # Specify sync strategy. Default: Sync'ed after every message. See Logstorage Rinbuffer Implementation below. +EcuID= # Specify ECU identifier +SpecificSize= # Store logs in storage devices after specific size is reached. + ---- -The Parameter "SyncBehavior" and "EcuID" are optional - all others are mandatory. -*Note*: Not allowed is the combination of wildcards for LogAppName *and* ContextName. The Parameter "SyncBehavior" and "EcuID" are optional - all others are mandatory. + +The Parameter "SyncBehavior","EcuID" and "SpecificSize" are optional - all others are mandatory. +*Note*: Not allowed is the combination of wildcards for LogAppName *and* ContextName. The Parameter "SyncBehavior","EcuID" and "SpecificSize" are optional - all others are mandatory. + An configuration file should look like: + @@ -67,8 +69,20 @@ LogLevel=DLT_LOG_ERROR File=Test FileSize=250000 NOFiles=5 -SyncStrategy=ON_DEMAND EcuID=ECU1 +SyncBehavior=ON_SPECIFIC_SIZE +SpecificSize=5000 + +[FILTER3] +LogAppName=TEST +ContextName=.* +LogLevel=DLT_LOG_ERROR +File=Test +FileSize=250000 +NOFiles=5 +SyncBehavior=ON_FILE_SIZE,ON_DEMAND +EcuID=ECU1 + ---- Filter algorithm @@ -127,7 +141,7 @@ Using dlt-logstorage-ctrl application ---- Usage: dlt-logstorage-ctrl [options] -Send a trigger to DLT daemon to connect/disconnecta certain logstorage device +Send a trigger to DLT daemon to connect/disconnect a certain logstorage device Options: -c Connection type: connect = 1, disconnect = 0 @@ -191,7 +205,10 @@ The obvious idea is to cache incoming log messages in memory and write the log d Incoming log messages are stored in a data cache with a specific size. Depending on user defined strategy, the data cache is written onto the storage device、without relying on the sync mechanism of the file system. The following strategies are implemented: -. ON_MSG - sync every message +. ON_MSG - sync every message(Default) . ON_DAEMON_EXIT - sync on daemon exit . ON_DEMAND - sync on demand -. Combinations (not allowed: combinations with ON_MSG) +. ON_FILE_SIZE - sync on file size reached +. ON_SPECIFIC_SIZE - sync after specific size is reached + Note : 1.Combinations (not allowed: combinations with ON_MSG,combination of ON_FILE_SIZE with ON_SPECIFIC_SIZE) + 2.If on_demand sync strategy alone is specified, it is advised to concatenate the log files in sequential order before viewing it on viewer. diff --git a/include/dlt/dlt_protocol.h b/include/dlt/dlt_protocol.h index 1440d6c..7c194b1 100644 --- a/include/dlt/dlt_protocol.h +++ b/include/dlt/dlt_protocol.h @@ -211,6 +211,9 @@ #define DLT_SERVICE_RESPONSE_OK 0x00 /**< Control message response: OK */ #define DLT_SERVICE_RESPONSE_NOT_SUPPORTED 0x01 /**< Control message response: Not supported */ #define DLT_SERVICE_RESPONSE_ERROR 0x02 /**< Control message response: Error */ +#define DLT_SERVICE_RESPONSE_PERM_DENIED 0x03 /**< Control message response: Permission denied */ +#define DLT_SERVICE_RESPONSE_WARNING 0x04 /**< Control message response: warning */ +#define DLT_SERVICE_RESPONSE_LAST 0x05 /**< Used as max value */ /* * Definitions of DLT service connection state diff --git a/src/console/logstorage/dlt-logstorage-ctrl.c b/src/console/logstorage/dlt-logstorage-ctrl.c index 227acec..15ccc04 100644 --- a/src/console/logstorage/dlt-logstorage-ctrl.c +++ b/src/console/logstorage/dlt-logstorage-ctrl.c @@ -155,6 +155,8 @@ static int analyze_response(char *data, void *payload, int len) { int ret = -1; char resp_ok[MAX_RESPONSE_LENGTH] = { 0 }; + char resp_warning[MAX_RESPONSE_LENGTH] = { 0 }; + char resp_perm_denied[MAX_RESPONSE_LENGTH] = { 0 }; if (data == NULL || payload == NULL) { @@ -170,10 +172,30 @@ static int analyze_response(char *data, void *payload, int len) "service(%u), ok", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); + snprintf(resp_warning, + MAX_RESPONSE_LENGTH, + "service(%u), warning", + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); + + snprintf(resp_perm_denied, + MAX_RESPONSE_LENGTH, + "service(%u), perm_denied", + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); + if (strncmp(data, resp_ok, strlen(resp_ok)) == 0) { ret = 0; } + if (strncmp(data, resp_warning, strlen(resp_warning)) == 0) + { + pr_error("Warning:Some filter configurations are ignored due to configuration issues \n"); + ret = 0; + } + if (strncmp(data, resp_perm_denied, strlen(resp_perm_denied)) == 0) + { + pr_error("Warning: Permission denied.\n"); + ret = 0; + } pr_verbose("Response received: '%s'\n", data); pr_verbose("Response expected: '%s'\n", resp_ok); diff --git a/src/console/logstorage/dlt-logstorage-udev.c b/src/console/logstorage/dlt-logstorage-udev.c index 355977e..e3584d7 100644 --- a/src/console/logstorage/dlt-logstorage-udev.c +++ b/src/console/logstorage/dlt-logstorage-udev.c @@ -108,6 +108,12 @@ static char *dlt_logstorage_udev_get_mount_point(char *dev_node) { mnt_point = strdup(ent->mnt_dir); + if (mnt_point == NULL) + { + pr_error("Cannot duplicate string.\n"); + return NULL; + } + /* Remounting rw */ if (strlen(mnt_point)) { @@ -162,6 +168,11 @@ static int check_mountpoint_from_partition(int event, struct udev_device *part) } dev_node = strdup(udev_device_get_devnode(part)); + if (dev_node == NULL) + { + pr_error("Cannot allocate memory for to store string\n"); + return -1; + } if (event == EVENT_MOUNTED) { @@ -174,6 +185,7 @@ static int check_mountpoint_from_partition(int event, struct udev_device *part) } else { + free(mnt_point); mnt_point = NULL; } } @@ -222,7 +234,7 @@ static int logstorage_udev_udevd_callback(void) prvt = (LogstorageCtrlUdev *)lctrl->prvt; - if (!prvt || !prvt->mon) + if ((!prvt) || (!prvt->mon)) { pr_error("Not able to get private data.\n"); return -1; @@ -282,6 +294,12 @@ static int logstorage_udev_udevd_callback(void) */ static int dlt_logstorage_udev_check_mounted(struct udev *udev) { + if (udev == NULL) + { + pr_error("%s: udev structure is NULL\n", __func__); + return -1; + } + /* Create a list of the devices in the 'partition' subsystem. */ struct udev_enumerate *enumerate = udev_enumerate_new(udev); struct udev_list_entry *devices = NULL; @@ -300,7 +318,8 @@ static int dlt_logstorage_udev_check_mounted(struct udev *udev) devices = udev_enumerate_get_list_entry(enumerate); /* For each list entry, get the corresponding device */ - udev_list_entry_foreach(dev_list_entry, devices) { + udev_list_entry_foreach(dev_list_entry, devices) + { const char *path; struct udev_device *partition = NULL; @@ -349,6 +368,11 @@ int dlt_logstorage_udev_deinit(void) prvt = (LogstorageCtrlUdev *)lctrl->prvt; + if (prvt == NULL) + { + return -1; + } + if (prvt->mon) { udev_monitor_unref(prvt->mon); diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c index c62ea82..2cf8632 100644 --- a/src/daemon/dlt-daemon.c +++ b/src/daemon/dlt-daemon.c @@ -719,11 +719,14 @@ int main(int argc, char* argv[]) if(daemon_local.flags.offlineLogstorageDirPath[0]) { - if(dlt_daemon_logstorage_setup_internal_storage(&daemon, - daemon_local.flags.offlineLogstorageDirPath, - daemon_local.flags.vflag)==-1) - { - dlt_log(LOG_INFO,"Setting up internal offline log storage failed!\n"); + if (dlt_daemon_logstorage_setup_internal_storage( + &daemon, + &daemon_local, + daemon_local.flags.offlineLogstorageDirPath, + daemon_local.flags.vflag) == -1) + { + dlt_log(LOG_INFO, + "Setting up internal offline log storage failed!\n"); } } diff --git a/src/daemon/dlt_daemon_client.c b/src/daemon/dlt_daemon_client.c index a265632..dd69326 100644 --- a/src/daemon/dlt_daemon_client.c +++ b/src/daemon/dlt_daemon_client.c @@ -2347,23 +2347,40 @@ int dlt_daemon_process_systemd_timer(DltDaemon *daemon, } #endif -void dlt_daemon_control_service_logstorage(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, DltMessage *msg, int verbose) +void dlt_daemon_control_service_logstorage(int sock, + DltDaemon *daemon, + DltDaemonLocal *daemon_local, + DltMessage *msg, + int verbose) { DltServiceOfflineLogstorage *req; int ret; + unsigned int connection_type = 0; + DltLogStorage *device = NULL; + int device_index = -1; + int i = 0; PRINT_FUNCTION_VERBOSE(verbose); - if ((daemon == NULL) || (msg == NULL) || (daemon_local == NULL) || (msg->databuffer == NULL)) + if ((daemon == NULL) || (msg == NULL) || (daemon_local == NULL)) { - dlt_log(LOG_ERR, "Invalid function parameters used for dlt_daemon_control_service_logstorage\n"); + dlt_vlog(LOG_ERR, + "%s: Invalid function parameters\n", + __func__); return ; } - if(daemon_local->flags.offlineLogstorageMaxDevices <= 0) + if ((daemon_local->flags.offlineLogstorageMaxDevices <= 0) || (msg->databuffer == NULL)) { - dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); - dlt_log(LOG_INFO, "Offline logstorage functionality not enabled or MAX device set is 0\n"); + dlt_daemon_control_service_response(sock, + daemon, + daemon_local, + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, + DLT_SERVICE_RESPONSE_ERROR, + verbose); + + dlt_log(LOG_INFO, + "Logstorage functionality not enabled or MAX device set is 0\n"); return; } @@ -2373,82 +2390,140 @@ void dlt_daemon_control_service_logstorage(int sock, DltDaemon *daemon, DltDaemo } req = (DltServiceOfflineLogstorage*) (msg->databuffer); - int device_index=-1; - int i=0; - for(i=0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) + + for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) { + connection_type = daemon->storage_handle[i].connection_type; /* Check if the requested device path is already used as log storage device */ - if(strcmp(daemon->storage_handle[i].device_mount_point, - req->mount_point) == 0) + if (strncmp(daemon->storage_handle[i].device_mount_point, + req->mount_point, strlen(req->mount_point)) == 0) { device_index = i; break; } + /* Get first available device index here */ - if((daemon->storage_handle[i].connection_type != - DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) && - (device_index == -1)) + if ((connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) && + (device_index == -1)) { device_index = i; } } - if((device_index) == -1) + /* It might be possible to sync all caches of all devices */ + if ((req->connection_type == DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES) && + (strlen(req->mount_point) == 0)) { - dlt_daemon_control_service_response(sock, - daemon, - daemon_local, - DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, - DLT_SERVICE_RESPONSE_ERROR, - verbose); - dlt_log(LOG_WARNING, "MAX devices already in use \n"); - return; + /* It is expected to receive an empty mount point to sync all Logstorage + * devices in this case. */ + } + else + { + if (device_index == -1) + { + dlt_daemon_control_service_response(sock, + daemon, + daemon_local, + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, + DLT_SERVICE_RESPONSE_ERROR, + verbose); + dlt_log(LOG_WARNING, "MAX devices already in use \n"); + return; + } } - - /* Check for device connection request from log storage ctrl app */ + /* Check for device connection request from log storage ctrl app */ + device = &daemon->storage_handle[device_index]; if (req->connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) { - ret = dlt_logstorage_device_connected(&(daemon->storage_handle[device_index]), req->mount_point); - if(ret != 0) + ret = dlt_logstorage_device_connected(device, req->mount_point); + + if (ret == 1) { - dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); + dlt_daemon_control_service_response(sock, + daemon, + daemon_local, + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, + DLT_SERVICE_RESPONSE_WARNING, + verbose); return; } - - /* Setup logstorage with config file settings */ - ret = dlt_logstorage_load_config(&(daemon->storage_handle[device_index])); - if(ret != 0) + else if (ret != 0) { - dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); + dlt_daemon_control_service_response(sock, + daemon, + daemon_local, + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, + DLT_SERVICE_RESPONSE_ERROR, + verbose); return; } - dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE,DLT_SERVICE_RESPONSE_OK, verbose); + dlt_daemon_control_service_response(sock, + daemon, + daemon_local, + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, + DLT_SERVICE_RESPONSE_OK, + verbose); /* Check if log level of running application needs an update */ - dlt_daemon_logstorage_update_application_loglevel(daemon, device_index, verbose); + dlt_daemon_logstorage_update_application_loglevel(daemon, + daemon_local, + device_index, + verbose); } /* Check for device disconnection request from log storage ctrl app */ else if(req->connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_DISCONNECTED) { /* Check if log level of running application needs to be reset */ - dlt_daemon_logstorage_reset_application_loglevel(daemon, device_index, daemon_local->flags.offlineLogstorageMaxDevices, verbose); + dlt_daemon_logstorage_reset_application_loglevel( + daemon, + daemon_local, + device_index, + daemon_local->flags.offlineLogstorageMaxDevices, + verbose); dlt_logstorage_device_disconnected(&(daemon->storage_handle[device_index]), DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); - dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_OK, verbose); + dlt_daemon_control_service_response(sock, + daemon, + daemon_local, + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, + DLT_SERVICE_RESPONSE_OK, + verbose); + } /* Check for cache synchronization request from log storage ctrl app */ else if(req->connection_type == DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES) { - /* trigger logstorage to sync caches */ - if (dlt_daemon_logstorage_sync_cache(daemon, - daemon_local, - req->mount_point, - verbose) == 0) + int ret = 0; + if (device_index == -1) /* sync all Logstorage devices */ + { + for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) + { + if (daemon->storage_handle[i].connection_type == + DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) + { + ret = dlt_daemon_logstorage_sync_cache( + daemon, + daemon_local, + daemon->storage_handle[i].device_mount_point, + verbose); + } + } + } + else + { + /* trigger logstorage to sync caches */ + ret = dlt_daemon_logstorage_sync_cache(daemon, + daemon_local, + req->mount_point, + verbose); + } + + if (ret == 0) { dlt_daemon_control_service_response(sock, daemon, @@ -2469,7 +2544,12 @@ void dlt_daemon_control_service_logstorage(int sock, DltDaemon *daemon, DltDaemo } else { - dlt_daemon_control_service_response(sock, daemon, daemon_local, DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE_ERROR, verbose); + dlt_daemon_control_service_response(sock, + daemon, + daemon_local, + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, + DLT_SERVICE_RESPONSE_ERROR, + verbose); } } diff --git a/src/daemon/dlt_daemon_common.c b/src/daemon/dlt_daemon_common.c index 3ba4c9b..990c029 100644 --- a/src/daemon/dlt_daemon_common.c +++ b/src/daemon/dlt_daemon_common.c @@ -973,9 +973,8 @@ DltDaemonContext* dlt_daemon_context_add(DltDaemon *daemon, /* Store log level and trace status, if this is a new context, or if this is an old context and the runtime cfg was not loaded */ - if ((strncmp(daemon->ecuid, ecu, DLT_ID_SIZE) == 0) && - ((new_context == 1) || ((new_context == 0) && - (daemon->runtime_context_cfg_loaded == 0)))) + if ((new_context == 1) || + ((new_context == 0) && (daemon->runtime_context_cfg_loaded == 0))) { context->log_level = log_level; context->trace_status = trace_status; @@ -1785,6 +1784,3 @@ void dlt_daemon_change_state(DltDaemon *daemon, DltDaemonState newState) } } - - - diff --git a/src/daemon/dlt_daemon_offline_logstorage.c b/src/daemon/dlt_daemon_offline_logstorage.c index f6642ba..fe4d8a7 100644 --- a/src/daemon/dlt_daemon_offline_logstorage.c +++ b/src/daemon/dlt_daemon_offline_logstorage.c @@ -1,24 +1,24 @@ /** -* @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_daemon_offline_logstorage.c -* For further information see http://www.genivi.org/. -* @licence end@ -*/ + * @licence app begin@ + * Copyright (C) 2013 - 2018 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_daemon_offline_logstorage.c + * For further information see http://www.genivi.org/. + * @licence end@ + */ #include #include @@ -26,11 +26,248 @@ #include #include "dlt_daemon_offline_logstorage.h" +#include "dlt_gateway_types.h" +#include "dlt_gateway.h" + +/** + * dlt_logstorage_split_ecuid + * + * Split keys with ECU ID alone + * + * @param key Key + * @param len Key length + * @param ecuid ECU ID from key stored here + * @param apid Application ID as .* stored here + * @param ctxid Context id as .* stored here + * @return 0 on success -1 on error + */ +STATIC DltReturnValue dlt_logstorage_split_ecuid(char *key, + int len, + char *ecuid, + char *appid, + char *ctxid) +{ + if ((len > (DLT_ID_SIZE + 2)) || (len < 2)) + { + return DLT_RETURN_ERROR; + } + + strncpy(ecuid, key, (len - 2)); + strncpy(appid, ".*", 2); + strncpy(ctxid, ".*", 2); + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_split_ctid + * + * Split keys with Context ID alone + * + * @param key Key + * @param len Key length + * @param appid Application ID as .* stored here + * @param ctxid Context id from key stored here + * @return 0 on success -1 on error + */ +STATIC DltReturnValue dlt_logstorage_split_ctid(char *key, + int len, + char *appid, + char *ctxid) +{ + if ((len > (DLT_ID_SIZE + 2)) || (len < 1) ) + { + return DLT_RETURN_ERROR; + } + + strncpy(ctxid, (key + 2), (len - 1)); + strncpy(appid, ".*", 2); + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_split_apid + * + * Split keys with Application ID alone + * + * @param key Key + * @param len Key length + * @param appid Application ID from key is stored here + * @param ctxid Context id as .* stored here + * @return 0 on success -1 on error + */ +STATIC DltReturnValue dlt_logstorage_split_apid(char *key, + int len, + char *appid, + char *ctxid) +{ + if ((len > (DLT_ID_SIZE + 2)) || (len < 2)) + { + return DLT_RETURN_ERROR; + } + + strncpy(appid, key + 1, (len - 2)); + strncpy(ctxid, ".*", 2); + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_split_apid_ctid + * + * Split keys with Application ID and Context ID + * + * @param key Key + * @param len Key length + * @param appid Application ID from key is stored here + * @param ctxid CContext id from key is stored here + * @return 0 on success -1 on error + */ +STATIC DltReturnValue dlt_logstorage_split_apid_ctid(char *key, + int len, + char *appid, + char *ctxid) +{ + char *tok = NULL; + + if (len > DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) + { + return DLT_RETURN_ERROR; + } + + /* copy appid and ctxid */ + tok = strtok(key, ":"); + if (tok != NULL) + { + strncpy(appid, tok, DLT_ID_SIZE); + } + else + { + return DLT_RETURN_ERROR; + } + + tok = strtok(NULL, ":"); + if (tok != NULL) + { + strncpy(ctxid, tok, DLT_ID_SIZE); + } + else + { + return DLT_RETURN_ERROR; + } + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_split_ecuid_apid + * + * Split keys with ECU ID and Application ID + * + * @param key Key + * @param len Key length + * @param ecuid ECU ID from key stored here + * @param appid Application ID from key is stored here + * @param ctxid CContext id as .* stored here + * @return 0 on success -1 on error + */ +STATIC DltReturnValue dlt_logstorage_split_ecuid_apid(char *key, + int len, + char *ecuid, + char *appid, + char *ctxid) +{ + char *tok = NULL; + + if (len > DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) + { + return DLT_RETURN_ERROR; + } + + /* copy appid and ctxid */ + tok = strtok(key, ":"); + if (tok != NULL) + { + strncpy(ecuid, tok, DLT_ID_SIZE); + } + else + { + return DLT_RETURN_ERROR; + } + + tok = strtok(NULL, ":"); + + if (tok != NULL) + { + strncpy(appid, tok, DLT_ID_SIZE); + } + else + { + return DLT_RETURN_ERROR; + } + strncpy(ctxid, ".*", 2); + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_split_multi + * + * Prepares keys with application ID alone, will use ecuid if provided + * (ecuid:apid::) or (:apid::) + * + * @param ecuid ECU ID + * @param apid Application ID + * @param key Prepared key stored here + * @return None + */ +STATIC DltReturnValue dlt_logstorage_split_multi(char *key, + int len, + char *ecuid, + char *appid, + char *ctxid) +{ + char *tok = NULL; + + if (len > DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) + { + return DLT_RETURN_ERROR; + } + + tok = strtok(key, ":"); + if (tok == NULL) + { + return DLT_RETURN_ERROR; + } + + len = strlen(tok); + if (key[len + 1] == ':') + { + strncpy(ecuid, tok, DLT_ID_SIZE); + + tok = strtok(NULL, ":"); + if (tok != NULL) + { + strncpy(ctxid, tok, DLT_ID_SIZE); + } + strncpy(appid, ".*", 2); + } + else + { + strncpy(ecuid, tok, DLT_ID_SIZE); + tok = strtok(NULL, ":"); + strncpy(appid, tok, DLT_ID_SIZE); + tok = strtok(NULL, ":"); + strncpy(ctxid, tok, DLT_ID_SIZE); + } + + return DLT_RETURN_OK; +} /** * dlt_logstorage_split_key -* + * * Split a given key into appid and ctxid. * If APID: - appid = APID and ctxid = .* * If :CTID - ctxid = CTID and appid = .* @@ -41,105 +278,323 @@ * @param ctxid Context id * @return 0 on success, -1 on error */ -int dlt_logstorage_split_key(char *key, char *appid, char *ctxid) +STATIC DltReturnValue dlt_logstorage_split_key(char *key, char *appid, char *ctxid, char *ecuid) { - char *tok = NULL; int len = 0; - int ret = 0; char *sep = NULL; - if (key == NULL) + if ((key == NULL) || (appid == NULL) || (ctxid == NULL) || (ecuid == NULL)) { - return -1; + return DLT_RETURN_WRONG_PARAMETER; } len = strlen(key); sep = strchr (key, ':'); - if(sep == NULL) + + if (sep == NULL) { - return -1; + return DLT_RETURN_WRONG_PARAMETER; } - /* key is context id only */ - if(key[0] == ':') + /* key is ecuid only ecuid::*/ + if ((key[len - 1] == ':') && (key[len - 2] == ':')) + { + return dlt_logstorage_split_ecuid(key, len, ecuid, appid, ctxid); + } + /* key is context id only ::apid*/ + else if ((key[0] == ':') && (key[1] == ':')) + { + return dlt_logstorage_split_ctid(key, len, appid, ctxid); + } + /* key is application id only :apid: */ + else if ((key[0] == ':') && key[len - 1] == ':') + { + return dlt_logstorage_split_apid(key, len, appid, ctxid); + } + /* key is :apid:ctid */ + else if ((key[0] == ':') && key[len - 1] != ':') + { + return dlt_logstorage_split_apid_ctid(key, len, appid, ctxid); + } + /* key is ecuid:apid: */ + else if ((key[0] != ':') && key[len - 1] == ':') { - if(len > (DLT_ID_SIZE+1)) - return -1; + return dlt_logstorage_split_ecuid_apid(key, len, ecuid, appid, ctxid); + } + /* key is either ecuid::ctid or ecuid:apid:ctid */ + else + { + return dlt_logstorage_split_multi(key, len, ecuid, appid, ctxid); + } +} - strncpy(ctxid,(key+1),(len-1)); - strncpy(appid, ".*",2); +/** + * Forward SET_LOG_LEVEL request to passive node + * + * @param daemon_local pointer to DltDaemonLocal structure + * @param apid Application ID + * @param ctid Context ID + * @param ecuid ECU ID + * @param loglevel requested log level + * @param verbose verbosity flag + */ +STATIC DltReturnValue dlt_daemon_logstorage_update_passive_node_context( + DltDaemonLocal *daemon_local, + char *apid, + char *ctid, + char *ecuid, + int loglevel, + int verbose) +{ + // Need to be updated + // To avoid compiler warning + (void) daemon_local; + (void) apid; + (void) ctid; + (void) ecuid; + (void) loglevel; + (void) verbose; + + return DLT_RETURN_OK; +} + +/** + * dlt_daemon_logstorage_send_log_level + * + * Send new log level for the provided context, if ecuid is not daemon ecuid + * update log level of passive node + * + * @param daemon DltDaemon structure + * @param daemon_local DltDaemonLocal structure + * @param context DltDaemonContext structure + * @param ecuid ECU id + * @param loglevel log level to be set to context + * @param verbose If set to true verbose information is printed out + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_daemon_logstorage_send_log_level(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + DltDaemonContext *context, + char *ecuid, + int loglevel, + int verbose) +{ + int old_log_level = -1; + int ll = DLT_LOG_DEFAULT; + + if ((daemon == NULL) || (daemon_local == NULL) || (ecuid == NULL) || + (context == NULL) || (loglevel > DLT_LOG_VERBOSE) || (loglevel < DLT_LOG_DEFAULT)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; } - /* key is application id only */ - else if (key[len-1] == ':') + + + if (strncmp(ecuid, daemon->ecuid, DLT_ID_SIZE) == 0) { - if(len > (DLT_ID_SIZE+1)) - return -1; + old_log_level = context->storage_log_level; + + context->storage_log_level = DLT_OFFLINE_LOGSTORAGE_MAX(loglevel, + context->storage_log_level); + + if (context->storage_log_level > old_log_level) + { + if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) + { + dlt_log(LOG_ERR, "Unable to update log level\n"); + return DLT_RETURN_ERROR; + } + } - strncpy(appid,key,(len-1)); - strncpy(ctxid, ".*",2); } - /* key is appid:ctxid */ else { - if(len > DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN) - return -1; - /* copy appid and ctxid */ - tok = strtok(key, ":"); - if (tok != NULL) - strncpy(appid,tok,DLT_ID_SIZE); - else - ret = -1; + old_log_level = context->log_level; + + ll = DLT_OFFLINE_LOGSTORAGE_MAX(loglevel, context->log_level); + + if (ll > old_log_level) + { + return dlt_daemon_logstorage_update_passive_node_context(daemon_local, + context->apid, + context->ctid, + ecuid, + ll, + verbose); + } - tok = strtok(NULL, ":"); - if (tok != NULL) - strncpy(ctxid,tok,DLT_ID_SIZE); - else - ret = -1; } + return DLT_RETURN_OK; +} + +/** + * dlt_daemon_logstorage_reset_log_level + * + * The log levels are reset if log level provided is -1 (not sent to + * application in this case). Reset and sent to application if current log level + * provided is 0. + * + * @param daemon DltDaemon structure + * @param daemon_local DltDaemonLocal structure + * @param ecuid ECU ID + * @param loglevel log level to be set to context + * @param verbose If set to true verbose information is printed out + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_daemon_logstorage_reset_log_level(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + DltDaemonContext *context, + char *ecuid, + int loglevel, + int verbose) +{ + if ((daemon == NULL) || (daemon_local == NULL) || (ecuid == NULL) || + (context == NULL) || (loglevel > DLT_LOG_VERBOSE) || (loglevel < DLT_LOG_DEFAULT)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + + + /* Set storage level to -1, to clear log levels */ + context->storage_log_level = DLT_LOG_DEFAULT; + + if (loglevel == DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL) + { + if (strncmp(ecuid, daemon->ecuid, DLT_ID_SIZE) == 0) + { + if (dlt_daemon_user_send_log_level(daemon, + context, + verbose) == DLT_RETURN_ERROR) + { + dlt_log(LOG_ERR, "Unable to update log level\n"); + return DLT_RETURN_ERROR; + } + } + else /* forward set log level to passive node */ + { + return dlt_daemon_logstorage_update_passive_node_context(daemon_local, + context->apid, + context->ctid, + ecuid, + DLT_LOG_DEFAULT, + verbose); + } + } + return DLT_RETURN_OK; +} + +/** + * dlt_daemon_logstorage_force_reset_level + * + * Force resetting of log level since have no data provided by passive node. + * + * @param daemon DltDaemon structure + * @param daemon_local DltDaemonLocal structure + * @param ecuid ECU ID + * @param loglevel log level to be set to context + * @param verbose If set to true verbose information is printed out + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_daemon_logstorage_force_reset_level(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + char *apid, + char *ctxid, + char *ecuid, + int loglevel, + int verbose) +{ + int ll = DLT_LOG_DEFAULT; + int num = 0; + int i = 0; + DltLogStorageFilterConfig *config[DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS] = { 0 }; + + if ((daemon == NULL) || (daemon_local == NULL) || (ecuid == NULL) || + (apid == NULL) || (ctxid == NULL) || (loglevel > DLT_LOG_VERBOSE) || (loglevel < DLT_LOG_DEFAULT)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + + for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) + { + num = dlt_logstorage_get_config(&(daemon->storage_handle[i]), config, apid, ctxid, ecuid); + if (num > 0) + { + break; /* found config */ + } + } + + if ((num == 0) || (config[0] == NULL )) + { + dlt_vlog(LOG_ERR, + "%s: No information about APID: %s, CTID: %s, ECU: %s in Logstorage configuration\n", + __func__, apid, ctxid, ecuid); + return DLT_RETURN_ERROR; + } + + if (loglevel == DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL) + { + ll = config[0]->reset_log_level; + } + else + { + ll = config[0]->log_level; + } + + return dlt_daemon_logstorage_update_passive_node_context(daemon_local, apid, + ctxid, ecuid, ll, verbose); - return ret; } /** * dlt_logstorage_update_all_contexts * - * Update log level of all contexts of the application by updating the daemon internal table - * The compare flags (cmp_flag) indicates if Id has to be compared with application ID - * or Context id of the daemon internal table - * The log levels are reset if current log level provided is -1 (not sent to application in this case) - * Reset and sent to application if current log level provided is 0 + * Update log level of all contexts of the application by updating the daemon + * internal table. The compare flags (cmp_flag) indicates if Id has to be + * compared with application id or Context id of the daemon internal table. + * The log levels are reset if current log level provided is -1 (not sent to + * application in this case). Reset and sent to application if current log level + * provided is 0. * * @param daemon DltDaemon structure + * @param daemon_local DltDaemonLocal structure * @param id application id or context id * @param curr_log_level log level to be set to context * @param cmp_flag compare flag (1 id is apid, 2 id is ctxid) + * @param ecuid ecu id where application runs * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ -int dlt_logstorage_update_all_contexts(DltDaemon *daemon, char *id, int curr_log_level, int cmp_flag, int verbose) +DltReturnValue dlt_logstorage_update_all_contexts(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + char *id, + int curr_log_level, + int cmp_flag, + char *ecuid, + int verbose) { - int i = 0; - char tmp_id[DLT_ID_SIZE+1]; - int old_log_level = -1; DltDaemonRegisteredUsers* user_list = NULL; + int i = 0; + char tmp_id[DLT_ID_SIZE + 1] = {'\0'}; - if((daemon == 0) || (id == NULL)) - return -1; - - if((cmp_flag < 0 ) || (cmp_flag > 2 )) - return -1; - - memset(tmp_id, 0, sizeof(tmp_id)); + if ((daemon == NULL) || (daemon_local == NULL) ||(id == NULL) || + (ecuid == NULL) || (cmp_flag < DLT_DAEMON_LOGSTORAGE_CMP_APID) || + (cmp_flag > DLT_DAEMON_LOGSTORAGE_CMP_CTID)) + { + dlt_vlog(LOG_ERR, "Wrong parameter in function %s\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } - user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose); + user_list = dlt_daemon_find_users_list(daemon, ecuid, verbose); if (user_list == NULL) { - return -1; + return DLT_RETURN_ERROR; } - for (i = 0 ; i < user_list->num_contexts ; i++) + for (i = 0; i < user_list->num_contexts; i++) { if (cmp_flag == 1) { @@ -150,106 +605,115 @@ int dlt_logstorage_update_all_contexts(DltDaemon *daemon, char *id, int curr_log dlt_set_id(tmp_id, user_list->contexts[i].ctid); } - if(strcmp(id, tmp_id) == 0) + if (strncmp(id, tmp_id, DLT_ID_SIZE) == 0) { - if(curr_log_level > 0) + if (curr_log_level > 0) { - old_log_level = user_list->contexts[i].storage_log_level; - - user_list->contexts[i].storage_log_level = - DLT_OFFLINE_LOGSTORAGE_MAX( - curr_log_level, - user_list->contexts[i].storage_log_level); - - if (user_list->contexts[i].storage_log_level > old_log_level) - { - if (dlt_daemon_user_send_log_level(daemon, - &user_list->contexts[i], - verbose) == -1) - { - dlt_log(LOG_ERR, "Unable to update loglevel\n"); - return -1; - } - } + dlt_daemon_logstorage_send_log_level(daemon, + daemon_local, + &user_list->contexts[i], + ecuid, + curr_log_level, + verbose); } - else /* The request is to reset log levels */ + else /* The request is to reset log levels */ { - /* Set storage level to -1, to clear log levels */ - user_list->contexts[i].storage_log_level = -1; - - if(curr_log_level == DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL) - { - if (dlt_daemon_user_send_log_level(daemon, - &user_list->contexts[i], - verbose) == -1) - { - dlt_log(LOG_ERR, "Unable to reset loglevel\n"); - return -1; - } - } - + dlt_daemon_logstorage_reset_log_level(daemon, + daemon_local, + &user_list->contexts[i], + ecuid, + curr_log_level, + verbose); } } } - return 0; + return DLT_RETURN_OK; } /** * dlt_logstorage_update_context * * Update log level of a context by updating the daemon internal table - * The log levels are reset if current log level provided is -1 (not sent to application in this case) + * The log levels are reset if current log level provided is -1 (not sent to + * application in this case) * Reset and sent to application if current log level provided is 0 * * @param daemon DltDaemon structure + * @param daemon_local DltDaemonLocal structure * @param apid application id * @param ctxid context id + * @param ecuid ecu id * @param curr_log_level log level to be set to context * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ -int dlt_logstorage_update_context(DltDaemon *daemon, char *apid, char *ctxid, int curr_log_level , int verbose) +DltReturnValue dlt_logstorage_update_context(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + char *apid, + char *ctxid, + char *ecuid, + int curr_log_level, + int verbose) { DltDaemonContext *context = NULL; - int old_log_level = -1; - if((daemon == 0) || (apid == NULL) || (ctxid == NULL)) - return -1; - - context = dlt_daemon_context_find(daemon, apid, ctxid, daemon->ecuid, verbose); + if ((daemon == NULL) || (daemon_local == NULL) ||(apid == NULL) + || (ctxid == NULL) || (ecuid == NULL)) + { + dlt_vlog(LOG_ERR, "Wrong parameter in function %s\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + context = dlt_daemon_context_find(daemon, apid, ctxid, ecuid, verbose); if (context != NULL) { - if(curr_log_level > 0) + if (curr_log_level > 0) { - old_log_level = context->storage_log_level; - - context->storage_log_level = DLT_OFFLINE_LOGSTORAGE_MAX(curr_log_level, context->storage_log_level); - if(context->storage_log_level > old_log_level) - { - if(dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) - { - dlt_log(LOG_ERR, "Unable to update loglevel\n"); - return -1; - } - } + return dlt_daemon_logstorage_send_log_level(daemon, + daemon_local, + context, + ecuid, + curr_log_level, + verbose); + } + else /* The request is to reset log levels */ + { + return dlt_daemon_logstorage_reset_log_level(daemon, + daemon_local, + context, + ecuid, + curr_log_level, + verbose); + } + } + else + { + if (strncmp(ecuid, daemon->ecuid, DLT_ID_SIZE) != 0) + { + // we intentionally have no data provided by passive node. + // We blindly send the log level or reset log level + return dlt_daemon_logstorage_force_reset_level(daemon, + daemon_local, + apid, + ctxid, + ecuid, + curr_log_level, + verbose); } else { - context->storage_log_level = -1; - - if(curr_log_level == DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL) - { - if(dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) - { - dlt_log(LOG_ERR, "Unable to update loglevel\n"); - return -1; - } - } + dlt_vlog(LOG_WARNING, + "%s: No information about APID: %s, CTID: %s, ECU: %s\n", + __func__, + apid, + ctxid, + ecuid); + return DLT_RETURN_ERROR; } } - return 0; + + return DLT_RETURN_OK; } /** @@ -263,47 +727,82 @@ int dlt_logstorage_update_context(DltDaemon *daemon, char *apid, char *ctxid, in * @param verbose If set to true verbose information is printed out * @return 0 on success, -1 on error */ -int dlt_logstorage_update_context_loglevel(DltDaemon *daemon, char *key, int curr_log_level , int verbose) +DltReturnValue dlt_logstorage_update_context_loglevel(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + char *key, + int curr_log_level, + int verbose) { - - int cmp_flag=0; - char appid[DLT_ID_SIZE+1] = {'\0'}; - char ctxid[DLT_ID_SIZE+1] = {'\0'}; + int cmp_flag = 0; + char appid[DLT_ID_SIZE + 1] = {'\0'}; + char ctxid[DLT_ID_SIZE + 1] = {'\0'}; + char ecuid[DLT_ID_SIZE + 1] = {'\0'}; PRINT_FUNCTION_VERBOSE(verbose); - if((daemon == 0) || (key == NULL)) - return -1; - - memset(appid, 0, sizeof(appid)); - memset(ctxid, 0, sizeof(ctxid)); + if ((daemon == NULL) || (daemon_local == NULL) || (key == NULL)) + { + return DLT_RETURN_WRONG_PARAMETER; + } - if(dlt_logstorage_split_key(key, appid, ctxid) != 0) + if (dlt_logstorage_split_key(key, appid, ctxid, ecuid) != 0) { - dlt_log(LOG_ERR, "Error while updating application log levels (splt key)\n"); - return -1; + dlt_log(LOG_ERR, + "Error while updating application log levels (split key)\n"); + return DLT_RETURN_ERROR; } - if(strcmp(ctxid, ".*") == 0) /* wildcard for context id, find all contexts of given application id */ + if (ecuid[0] == '\0') /* ECU id was not specified in filter configuration */ { - cmp_flag = 1; + dlt_set_id(ecuid, daemon->ecuid); + } - if(dlt_logstorage_update_all_contexts(daemon, appid, curr_log_level, cmp_flag, verbose) != 0) - return -1; + /* wildcard for context id, find all contexts of given application id */ + if (strcmp(ctxid, ".*") == 0) + { + cmp_flag = DLT_DAEMON_LOGSTORAGE_CMP_APID; + + if (dlt_logstorage_update_all_contexts(daemon, + daemon_local, + appid, + curr_log_level, + cmp_flag, + ecuid, + verbose) != 0) + { + return DLT_RETURN_ERROR; + } } - else if(strcmp(appid, ".*") == 0) /* wildcard for application id, find all contexts with context id */ + /* wildcard for application id, find all contexts with context id */ + else if (strcmp(appid, ".*") == 0) { - cmp_flag = 2; - - if(dlt_logstorage_update_all_contexts(daemon, ctxid, curr_log_level, cmp_flag, verbose) != 0) - return -1; + cmp_flag = DLT_DAEMON_LOGSTORAGE_CMP_CTID; + + if (dlt_logstorage_update_all_contexts(daemon, + daemon_local, + ctxid, + curr_log_level, + cmp_flag, + ecuid, + verbose) != 0) + { + return DLT_RETURN_ERROR; + } } - else /* In case of given application id, context id pair, call available context find function */ + /* In case of given application id, context id pair, call available context + * find function */ + else if (dlt_logstorage_update_context(daemon, + daemon_local, + appid, + ctxid, + ecuid, + curr_log_level, + verbose) != 0) { - if(dlt_logstorage_update_context(daemon, appid, ctxid, curr_log_level, verbose) != 0) - return -1; + return DLT_RETURN_ERROR; } - return 0; + + return DLT_RETURN_OK; } /** @@ -311,135 +810,193 @@ int dlt_logstorage_update_context_loglevel(DltDaemon *daemon, char *key, int cur * * Reset storage log level of all running applications * 2 steps for resetting - * 1. Setup storage_loglevel of all contexts configured for the requested device to -1 + * 1. Setup storage_loglevel of all contexts configured for the requested device + * to -1 * 2. Re-run update log level for all other configured devices * * @param daemon Pointer to DLT Daemon structure + * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param max_device Maximum storage devices setup by the daemon * @param verbose If set to true verbose information is printed out */ -void dlt_daemon_logstorage_reset_application_loglevel(DltDaemon *daemon, int dev_num, int max_device, int verbose) +void dlt_daemon_logstorage_reset_application_loglevel(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int dev_num, + int max_device, + int verbose) { DltLogStorage *handle = NULL; + DltLogStorageFilterList **tmp = NULL; int i = 0; - char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN] = {'\0'}; + char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = {'\0'}; int num_device_configured = 0; + unsigned int status; PRINT_FUNCTION_VERBOSE(verbose); - if((daemon == 0) || (dev_num < 0)) + if ((daemon == NULL) || (daemon_local == NULL) || + (daemon->storage_handle == NULL) || (dev_num < 0)) { - dlt_log(LOG_ERR, "Invalid function parameters used for dlt_daemon_logstorage_reset_application_loglevel\n"); + dlt_vlog(LOG_ERR, + "Invalid function parameters used for %s\n", + __func__); return; } handle = &(daemon->storage_handle[dev_num]); - if ((handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) - || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) + + if ((handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || + (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) { return; } /* First, check number of devices configured */ - for(i = 0; istorage_handle[i].config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) + status = daemon->storage_handle[i].config_status; + + if (status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { - num_device_configured += 1; + num_device_configured++; } } - /* for all filters (keys) check if application context are already running and log level need to be reset*/ - for(i = 0; i < handle->num_filter_keys; i++) + /* for all filters (keys) check if application context are already running + * and log level need to be reset*/ + tmp = &(handle->config_list); + while (*(tmp) != NULL) { memset(key, 0, sizeof(key)); - strncpy(key, (handle->filter_keys + i * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN), DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN); + strncpy(key, + (*tmp)->key, + DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN); - if(num_device_configured == 1) + if (num_device_configured == 1) + { /* Reset context log level and send to application */ - dlt_logstorage_update_context_loglevel(daemon, key, DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL, verbose); - else - /* Reset context log level do not send to application as other devices can have same configuration */ - dlt_logstorage_update_context_loglevel(daemon, key, DLT_DAEMON_LOGSTORAGE_RESET_LOGLEVEL, verbose); + dlt_logstorage_update_context_loglevel( + daemon, + daemon_local, + key, + DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL, + verbose); + } + else /* Reset context log level do not send to application as other + devices can have same configuration */ + { + dlt_logstorage_update_context_loglevel( + daemon, + daemon_local, + key, + DLT_DAEMON_LOGSTORAGE_RESET_LOGLEVEL, + verbose); + } + tmp = &(*tmp)->next; } /* Re-run update log level for all other configured devices */ - for(i=0; istorage_handle[i].config_status; + if (i == dev_num) + { continue; + } - if (daemon->storage_handle[i].config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) + if (status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { - dlt_daemon_logstorage_update_application_loglevel(daemon, i, verbose); + dlt_daemon_logstorage_update_application_loglevel(daemon, + daemon_local, + i, + verbose); } } + return; } /** * dlt_daemon_logstorage_update_application_loglevel * - * Update log level of all running applications with new filter configuration available due - * to newly attached DltLogstorage device. The log level is only updated when the current - * application log level is less than the log level obtained from the storage configuration file + * Update log level of all running applications with new filter configuration + * available due to newly attached DltLogstorage device. The log level is only + * updated when the current application log level is less than the log level + * obtained from the storage configuration file * * @param daemon Pointer to DLT Daemon structure + * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param verbose If set to true verbose information is printed out */ -void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, int dev_num, int verbose) +void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int dev_num, + int verbose) { DltLogStorage *handle = NULL; - int i = 0; - char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN] = {'\0'}; - + DltLogStorageFilterList **tmp = NULL; + char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN + 1] = {'\0'}; PRINT_FUNCTION_VERBOSE(verbose); - if((daemon == 0) || (dev_num < 0)) + if ((daemon == NULL) || (dev_num < 0)) { - dlt_log(LOG_ERR, "Invalid function parameters used for dlt_daemon_logstorage_update_application_loglevel\n"); + dlt_vlog(LOG_ERR, + "Invalid function parameters used for %s\n", + __func__); return; } handle = &(daemon->storage_handle[dev_num]); - if ((handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) - || (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) + + if ((handle->connection_type != DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) || + (handle->config_status != DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE)) { return; } - /* for all filters (keys) check if application or context already running and log level need to be updated*/ - for(i = 0; i < handle->num_filter_keys; i++) + /* for all filters (keys) check if application or context already running + * and log level need to be updated*/ + tmp = &(handle->config_list); + while (*(tmp) != NULL) { int log_level = -1; memset(key, 0, sizeof(key)); - strncpy(key, (handle->filter_keys + i * DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN), DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN); + strncpy(key, + (*tmp)->key, + DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN); /* Obtain storage configuration data */ log_level = dlt_logstorage_get_loglevel_by_key(handle, key); - if(log_level < 0) + + if (log_level < 0) { dlt_log(LOG_ERR, "Failed to get log level by key \n"); - return; + return; } /* Update context log level with storage configuration log level */ - dlt_logstorage_update_context_loglevel(daemon, key, log_level, verbose); + dlt_logstorage_update_context_loglevel(daemon, + daemon_local, + key, + log_level, + verbose); + tmp = &(*tmp)->next; } + return; } /** * dlt_daemon_logstorage_get_loglevel * - * Obtain log level as a union of all configured storage devices and filters for the - * provided application id and context id + * Obtain log level as a union of all configured storage devices and filters for + * the provided application id and context id * * @param daemon Pointer to DLT Daemon structure * @param max_device Maximum storage devices setup by the daemon @@ -447,42 +1004,71 @@ void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, int de * @param ctid Context ID * @return Log level on success, -1 on error */ -int dlt_daemon_logstorage_get_loglevel(DltDaemon *daemon, int max_device, char *apid, char *ctid) +int dlt_daemon_logstorage_get_loglevel(DltDaemon *daemon, + int max_device, + char *apid, + char *ctid) { - DltLogStorageConfigData **config = NULL; + DltLogStorageFilterConfig *config[DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS] = {0}; int i = 0; int j = 0; int8_t storage_loglevel = -1; - int8_t retrvd_loglevel = -1; + int8_t configured_loglevel = -1; int num_config = 0; - if((daemon == 0) || (max_device == 0) || (apid == NULL) || (ctid == NULL)) - return -1; + if ((daemon == NULL) || (max_device == 0) || (apid == NULL) || (ctid == NULL)) + { + return DLT_RETURN_WRONG_PARAMETER; + } - for(i = 0; istorage_handle[i].config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) + if (daemon->storage_handle[i].config_status == + DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { - config = dlt_logstorage_get_config(&(daemon->storage_handle[i]), apid, ctid, &num_config); - if(config != NULL) + num_config = dlt_logstorage_get_config(&(daemon->storage_handle[i]), + config, + apid, + ctid, + daemon->ecuid); + + if (num_config == 0) { - for(j = 0; jlog_level; - storage_loglevel = DLT_OFFLINE_LOGSTORAGE_MAX(retrvd_loglevel, storage_loglevel); + continue; } - free(config); + + /* If logstorage configuration do not contain file name, + * then it is non verbose control filter, so return level as in this filter */ + if (config[j]->file_name == NULL) + { + storage_loglevel = config[j]->log_level; + break; + } + configured_loglevel = config[j]->log_level; + storage_loglevel = DLT_OFFLINE_LOGSTORAGE_MAX( + configured_loglevel, + storage_loglevel); } } } + return storage_loglevel; } /** * dlt_daemon_logstorage_write * - * Write log message to all attached storage device. If the called dlt_logstorage_write function is not able - * to write to the device, DltDaemon will disconnect this device. + * Write log message to all attached storage device. If the called + * dlt_logstorage_write function is not able to write to the device, DltDaemon + * will disconnect this device. * * @param daemon Pointer to Dlt Daemon structure * @param user_config DltDaemon configuration @@ -505,13 +1091,15 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, int i = 0; DltLogStorageUserConfig file_config; - if (daemon == NULL || (user_config->offlineLogstorageMaxDevices <= 0) - || data1 == NULL || data2 == NULL || data3 == NULL) + if ((daemon == NULL) || (user_config == NULL) || + (user_config->offlineLogstorageMaxDevices <= 0) || (data1 == NULL) || + (data2 == NULL) || (data3 == NULL)) { - dlt_log(LOG_INFO, - "dlt_daemon_logstorage_write: message type is not log. " - "Skip storing.\n"); + dlt_vlog(LOG_DEBUG, + "%s: message type is not LOG. Skip storing.\n", + __func__); return; + /* Log Level changed callback */ } /* Copy user configuration */ @@ -519,7 +1107,7 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, file_config.logfile_delimiter = user_config->offlineLogstorageDelimiter; file_config.logfile_maxcounter = user_config->offlineLogstorageMaxCounter; file_config.logfile_counteridxlen = - user_config->offlineLogstorageMaxCounterIdx; + user_config->offlineLogstorageMaxCounterIdx; for (i = 0; i < user_config->offlineLogstorageMaxDevices; i++) { @@ -541,8 +1129,8 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, /* DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS happened, * therefore remove logstorage device */ dlt_logstorage_device_disconnected( - &(daemon->storage_handle[i]), - DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); + &(daemon->storage_handle[i]), + DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); } } } @@ -554,37 +1142,40 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, * Setup user defined path as offline log storage device * * @param daemon Pointer to Dlt Daemon structure + * @param daemon_local Pointer to Dlt Daemon local structure * @param path User configured internal storage path * @param verbose If set to true verbose information is printed out + * @return 0 on sucess, -1 otherwise */ -int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, char *path, int verbose) +int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + char *path, + int verbose) { int ret = 0; - if((path == NULL) || (daemon == NULL)) + PRINT_FUNCTION_VERBOSE(verbose); + + if ((path == NULL) || (daemon == NULL)) { - return -1; + return DLT_RETURN_WRONG_PARAMETER; } /* connect internal storage device */ /* Device index always used as 0 as it is setup on DLT daemon startup */ ret = dlt_logstorage_device_connected(&(daemon->storage_handle[0]), path); - if(ret != 0) - { - dlt_log(LOG_ERR,"dlt_daemon_logstorage_setup_emmc_support : Device connect failed\n"); - return -1; - } - /* setup logstorage with config file settings */ - ret = dlt_logstorage_load_config(&(daemon->storage_handle[0])); - if(ret != 0) + if (ret != 0) { - dlt_log(LOG_ERR,"dlt_daemon_logstorage_setup_emmc_support : Loading configuration file failed\n"); - return -1; + dlt_vlog(LOG_ERR, "%s: Device connect failed\n", __func__); + return DLT_RETURN_ERROR; } /* check if log level of running application need an update */ - dlt_daemon_logstorage_update_application_loglevel(daemon, 0, verbose); + dlt_daemon_logstorage_update_application_loglevel(daemon, + daemon_local, + 0, + verbose); return ret; } @@ -592,7 +1183,7 @@ int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, char *path, void dlt_daemon_logstorage_set_logstorage_cache_size(unsigned int size) { /* store given [KB] size in [Bytes] */ - g_logstorage_cache_max = size * 1000; + g_logstorage_cache_max = size * 1024; } int dlt_daemon_logstorage_cleanup(DltDaemon *daemon, @@ -603,9 +1194,9 @@ int dlt_daemon_logstorage_cleanup(DltDaemon *daemon, PRINT_FUNCTION_VERBOSE(verbose); - if (daemon == NULL || daemon_local == NULL) + if ((daemon == NULL) || (daemon_local == NULL)) { - return -1; + return DLT_RETURN_WRONG_PARAMETER; } for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) @@ -615,8 +1206,8 @@ int dlt_daemon_logstorage_cleanup(DltDaemon *daemon, DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) { dlt_logstorage_device_disconnected( - &daemon->storage_handle[i], - DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT); + &daemon->storage_handle[i], + DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT); } } @@ -633,9 +1224,9 @@ int dlt_daemon_logstorage_sync_cache(DltDaemon *daemon, PRINT_FUNCTION_VERBOSE(verbose); - if (daemon == NULL || mnt_point == NULL) + if ((daemon == NULL) || (daemon_local == NULL) || (mnt_point == NULL)) { - return -1; + return DLT_RETURN_WRONG_PARAMETER; } if (strlen(mnt_point) > 0) /* mount point is given */ @@ -646,26 +1237,42 @@ int dlt_daemon_logstorage_sync_cache(DltDaemon *daemon, verbose); if (handle == NULL) { - return -1; + return DLT_RETURN_ERROR; } else { + handle->uconfig.logfile_counteridxlen = + daemon_local->flags.offlineLogstorageMaxCounterIdx; + handle->uconfig.logfile_delimiter = + daemon_local->flags.offlineLogstorageDelimiter; + handle->uconfig.logfile_maxcounter = + daemon_local->flags.offlineLogstorageMaxCounter; + handle->uconfig.logfile_timestamp = + daemon_local->flags.offlineLogstorageTimestamp; if (dlt_logstorage_sync_caches(handle) != 0) { - return -1; + return DLT_RETURN_ERROR; } } } else /* sync caches for all connected logstorage devices */ { - for(i=0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) + for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) { if (daemon->storage_handle[i].connection_type == - DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) + DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED) { + daemon->storage_handle[i].uconfig.logfile_counteridxlen = + daemon_local->flags.offlineLogstorageMaxCounterIdx; + daemon->storage_handle[i].uconfig.logfile_delimiter = + daemon_local->flags.offlineLogstorageDelimiter; + daemon->storage_handle[i].uconfig.logfile_maxcounter = + daemon_local->flags.offlineLogstorageMaxCounter; + daemon->storage_handle[i].uconfig.logfile_timestamp = + daemon_local->flags.offlineLogstorageTimestamp; if (dlt_logstorage_sync_caches(&daemon->storage_handle[i]) != 0) { - return -1; + return DLT_RETURN_ERROR; } } } @@ -680,28 +1287,28 @@ DltLogStorage *dlt_daemon_logstorage_get_device(DltDaemon *daemon, int verbose) { int i = 0; + int len = 0; int len1 = 0; int len2 = 0; PRINT_FUNCTION_VERBOSE(verbose); - if (daemon == NULL || daemon_local == NULL || mnt_point == NULL) + if ((daemon == NULL) || (daemon_local == NULL) || (mnt_point == NULL)) { return NULL; } len1 = strlen(mnt_point); - for(i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) + for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) { len2 = strlen(daemon->storage_handle[i].device_mount_point); /* Check if the requested device path is already used as log storage * device. Check for strlen first, to avoid comparison errors when * final '/' is given or not */ - if (strncmp(daemon->storage_handle[i].device_mount_point, - mnt_point, - len1 > len2 ? len2 : len1) == 0) + len = len1 > len2 ? len2 : len1; + if (strncmp(daemon->storage_handle[i].device_mount_point, mnt_point, len) == 0) { return &daemon->storage_handle[i]; } diff --git a/src/daemon/dlt_daemon_offline_logstorage.h b/src/daemon/dlt_daemon_offline_logstorage.h index 3ab092a..f9d587d 100644 --- a/src/daemon/dlt_daemon_offline_logstorage.h +++ b/src/daemon/dlt_daemon_offline_logstorage.h @@ -1,44 +1,44 @@ /** -* @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_daemon_offline_logstorage.h -* For further information see http://www.genivi.org/. -* @licence end@ -*/ + * @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_daemon_offline_logstorage.h + * For further information see http://www.genivi.org/. + * @licence end@ + */ /******************************************************************************* -* ** -* SRC-MODULE: dlt_daemon_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 ** -* ** -******************************************************************************/ + * ** + * SRC-MODULE: dlt_daemon_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 ** @@ -48,7 +48,7 @@ * -------- ------------------------- ---------------------------------- ** * sh Syed Hameed ADIT ** * cl Christoph Lipka ADIT ** - *******************************************************************************/ +*******************************************************************************/ #ifndef DLT_DAEMON_OFFLINE_LOGSTORAGE_H #define DLT_DAEMON_OFFLINE_LOGSTORAGE_H @@ -60,11 +60,14 @@ #define DLT_DAEMON_LOGSTORAGE_RESET_LOGLEVEL -1 #define DLT_DAEMON_LOGSTORAGE_RESET_SEND_LOGLEVEL 0 +#define DLT_DAEMON_LOGSTORAGE_CMP_APID 1 +#define DLT_DAEMON_LOGSTORAGE_CMP_CTID 2 + /** * dlt_daemon_logstorage_get_loglevel * - * Obtain log level as a union of all configured storage devices and filters for the - * provided application id and context id + * Obtain log level as a union of all configured storage devices and filters for + * the provided application id and context id * * @param daemon Pointer to DLT Daemon structure * @param max_device Maximum storage devices setup by the daemon @@ -72,35 +75,49 @@ * @param ctid Context ID * @return Log level on success, -1 on error */ -int dlt_daemon_logstorage_get_loglevel(DltDaemon *daemon, int max_device, char *apid, char *ctid); +int dlt_daemon_logstorage_get_loglevel(DltDaemon *daemon, + int max_device, + char *apid, + char *ctid); /** * dlt_daemon_logstorage_reset_application_loglevel * * Reset storage log level of all running applications with -1 * * @param daemon Pointer to DLT Daemon structure + * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param verbose If set to true verbose information is printed out */ -void dlt_daemon_logstorage_reset_application_loglevel(DltDaemon *daemon, int dev_num, int max_device, int verbose); +void dlt_daemon_logstorage_reset_application_loglevel(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int dev_num, + int max_device, + int verbose); /** * dlt_daemon_logstorage_update_application_loglevel * - * Update log level of all running applications with new filter configuration available due - * to newly attached DltLogstorage device. The log level is only updated when the current - * application log level is less than the log level obtained from the storage configuration file + * Update log level of all running applications with new filter configuration + * available due to newly attached DltLogstorage device. The log level is only + * updated when the current application log level is less than the log level + * obtained from the storage configuration file. * * @param daemon Pointer to DLT Daemon structure + * @param daemon_local Pointer to DLT Daemon local structure * @param dev_num Number of attached DLT Logstorage device * @param verbose if set to true verbose information is printed out */ -void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, int dev_num, int verbose); +void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + int dev_num, + int verbose); /** * dlt_daemon_logstorage_write * - * Write log message to all attached storage device. If the called dlt_logstorage_write function is not able - * to write to the device, DltDaemon will disconnect this device. + * Write log message to all attached storage device. If the called + * dlt_logstorage_write function is not able to write to the device, + * DltDaemon will disconnect this device. * * @param daemon Pointer to Dlt Daemon structure * @param user_config DltDaemon configuration @@ -127,10 +144,14 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, * Setup user defined path as offline log storage device * * @param daemon Pointer to Dlt Daemon structure + * @param daemon_local Pointer to Dlt Daemon Local structure * @param path User configured internal storage path * @param verbose If set to true verbose information is printed out */ -int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, char *path, int verbose); +int dlt_daemon_logstorage_setup_internal_storage(DltDaemon *daemon, + DltDaemonLocal *daemon_local, + char *path, + int verbose); /** * Set max size of logstorage cache. Stored internally in bytes diff --git a/src/gateway/dlt_gateway.c b/src/gateway/dlt_gateway.c index 04237c2..dda1833 100644 --- a/src/gateway/dlt_gateway.c +++ b/src/gateway/dlt_gateway.c @@ -1293,3 +1293,32 @@ void dlt_gateway_send_control_message(DltGatewayConnection *con, dlt_message_free(&msg, verbose); } } + +DltGatewayConnection *dlt_gateway_get_connection(DltGateway *gateway, + char *ecu, + int verbose) +{ + DltGatewayConnection *con = NULL; + int i = 0; + + PRINT_FUNCTION_VERBOSE(verbose); + + if ((gateway == NULL) || (ecu == NULL)) + { + dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__); + return con; + } + + for (i = 0; i < gateway->num_connections; i++) + { + con = &gateway->connections[i]; + if (strncmp(con->ecuid, ecu, DLT_ID_SIZE) == 0) + { + return con; + } + } + + dlt_vlog(LOG_ERR, "%s: No connection found\n", ecu); + + return con; +} diff --git a/src/gateway/dlt_gateway.h b/src/gateway/dlt_gateway.h index 9fa2d6a..571a76a 100644 --- a/src/gateway/dlt_gateway.h +++ b/src/gateway/dlt_gateway.h @@ -175,6 +175,18 @@ void dlt_gateway_send_control_message(DltGatewayConnection *con, DltDaemonLocal *daemon_local, int verbose); +/** + * Gets the connection handle of passive node with specified ECU + * + * @param g DltGateway + * @param ecu Identifier string + * @param verbose verbose flag + * @returns Gateway connection handle on success, NULL otherwise + */ +DltGatewayConnection *dlt_gateway_get_connection(DltGateway *g, + char *ecu, + int verbose); + /* _ONLY_ for development purposes */ void print_gateway_connection_details(const DltGateway *g); #ifdef DLT_UNIT_TESTS 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; diff --git a/src/offlinelogstorage/dlt_offline_logstorage.h b/src/offlinelogstorage/dlt_offline_logstorage.h index df232b7..b3f7dd3 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage.h +++ b/src/offlinelogstorage/dlt_offline_logstorage.h @@ -54,10 +54,13 @@ #define DLT_OFFLINE_LOGSTORAGE_H #include +#include #include "dlt_common.h" #include "dlt-daemon_cfg.h" +#include "dlt_config_file_parser.h" -#define DLT_OFFLINE_LOGSTORAGE_MAXFILTERS 100 /* Maximum entries in hashmap */ +#define DLT_OFFLINE_LOGSTORAGE_MAXIDS 100 /* Maximum entries for each apids and ctids */ +#define DLT_OFFLINE_LOGSTORAGE_MAX_POSSIBLE_CONFIGS 7 /* max number of possible filters when searching for */ #define DLT_OFFLINE_LOGSTORAGE_INIT_DONE 1 /* For device configuration status */ #define DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED 1 @@ -67,7 +70,7 @@ #define DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES 2 /* sync logstorage caches */ -#define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN 10 /* Maximum size for key */ +#define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN 15 /* Maximum size for key */ #define DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN 50 /* Maximum file name length of the log file */ #define DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN 4 @@ -82,23 +85,6 @@ DLT_OFFLINE_LOGSTORAGE_INDEX_LEN + \ DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + 1) -#define DLT_OFFLINE_LOGSTORAGE_FILTER_UNINIT 0 -#define DLT_OFFLINE_LOGSTORAGE_ECUID (1<<8) -#define DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT (1<<7) -#define DLT_OFFLINE_LOGSTORAGE_APP_INIT (1<<6) -#define DLT_OFFLINE_LOGSTORAGE_CTX_INIT (1<<5) -#define DLT_OFFLINE_LOGSTORAGE_LOG_LVL_INIT (1<<4) -#define DLT_OFFLINE_LOGSTORAGE_NAME_INIT (1<<3) -#define DLT_OFFLINE_LOGSTORAGE_SIZE_INIT (1<<2) -#define DLT_OFFLINE_LOGSTORAGE_SYNC_BEHAVIOR (1<<1) -#define DLT_OFFLINE_LOGSTORAGE_NUM_INIT 1 -/* Sync behavior and ECUid are optional */ -#define DLT_OFFLINE_LOGSTORAGE_FILTER_INIT 0xFD - -#define DLT_OFFLINE_LOGSTORAGE_FILTER_INITIALIZED(A) ((A) >= DLT_OFFLINE_LOGSTORAGE_FILTER_INIT) - -#define DLT_OFFLINE_LOGSTORAGE_IS_FILTER_PRESENT(A) ((A) & DLT_OFFLINE_LOGSTORAGE_FILTER_PRESENT) - #define DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN 50 #define DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME "dlt_logstorage.conf" @@ -114,15 +100,20 @@ #define DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION "FILTER" #define DLT_OFFLINE_LOGSTORAGE_GENERAL_CONFIG_SECTION "GENERAL" +#define DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_STORAGE_SECTION "NON-VERBOSE-STORAGE-FILTER" +#define DLT_OFFLINE_LOGSTORAGE_NONVERBOSE_CONTROL_SECTION "NON-VERBOSE-LOGLEVEL-CTRL" /* Offline Logstorage sync strategies */ #define DLT_LOGSTORAGE_SYNC_ON_ERROR -1 /* error case */ +#define DLT_LOGSTORAGE_SYNC_UNSET 0 /* strategy not set */ #define DLT_LOGSTORAGE_SYNC_ON_MSG 1 /* default, on message sync */ -#define DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT (1<<1) /* sync on daemon exit */ -#define DLT_LOGSTORAGE_SYNC_ON_DEMAND (1<<2) /* sync on demand */ -#define DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT (1<<3) /* sync on device disconnect*/ +#define DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT (1 << 1) /* sync on daemon exit */ +#define DLT_LOGSTORAGE_SYNC_ON_DEMAND (1 << 2) /* sync on demand */ +#define DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT (1 << 3) /* sync on device disconnect*/ +#define DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE (1 << 4) /* sync on after specific size */ +#define DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE (1 << 5) /* sync on file size reached */ -#define DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(S, s) ((S) & (s)) +#define DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(S, s) ((S) &(s)) /* logstorage max cache */ unsigned int g_logstorage_cache_max; @@ -131,9 +122,10 @@ unsigned int g_logstorage_cache_size; typedef struct { - int offset; /* current write offset */ + unsigned int offset; /* current write offset */ unsigned int wrap_around_cnt; /* wrap around counter */ -}DltLogStorageCacheFooter; + unsigned int last_sync_offset; /* last sync position */ +} DltLogStorageCacheFooter; typedef struct { @@ -142,7 +134,7 @@ typedef struct char logfile_delimiter; /* Choice of delimiter */ unsigned int logfile_maxcounter; /* Maximum file index counter */ unsigned int logfile_counteridxlen; /* File index counter length */ -}DltLogStorageUserConfig; +} DltLogStorageUserConfig; typedef struct DltLogStorageFileList { @@ -150,25 +142,28 @@ typedef struct DltLogStorageFileList char *name; /* Filename */ unsigned int idx; /* File index */ struct DltLogStorageFileList *next; -}DltLogStorageFileList; +} DltLogStorageFileList; -typedef struct DltLogStorageConfigData DltLogStorageConfigData; +typedef struct DltLogStorageFilterConfig DltLogStorageFilterConfig; -struct DltLogStorageConfigData +struct DltLogStorageFilterConfig { /* filter section */ + char *apids; /* Application IDs configured for filter */ + char *ctids; /* Context IDs configured for filter */ int log_level; /* Log level number configured for filter */ + int reset_log_level; /* reset Log level to be sent on disconnect */ char *file_name; /* File name for log storage configured for filter */ unsigned int file_size; /* MAX File size of storage file configured for filter */ unsigned int num_files; /* MAX number of storage files configured for filters */ int sync; /* Sync strategy */ char *ecuid; /* ECU identifier */ /* callback function for filter configurations */ - int (*dlt_logstorage_prepare)(DltLogStorageConfigData *config, + int (*dlt_logstorage_prepare)(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size); - int (*dlt_logstorage_write)(DltLogStorageConfigData *config, + int (*dlt_logstorage_write)(DltLogStorageFilterConfig *config, unsigned char *data1, int size1, unsigned char *data2, @@ -177,27 +172,37 @@ struct DltLogStorageConfigData int size3); /* status is strategy, e.g. DLT_LOGSTORAGE_SYNC_ON_MSG is used when callback * is called on message received */ - int (*dlt_logstorage_sync)(DltLogStorageConfigData *config, int status); + int (*dlt_logstorage_sync)(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *uconfig, + char *dev_path, + int status); FILE *log; /* current open log file */ void *cache; /* log data cache */ + unsigned int specific_size; /* cache size used for specific_size sync strategy */ + unsigned int current_write_file_offset; /* file offset for specific_size sync strategy */ + unsigned int total_write_count; /* total count of data need to sync to file */ + bool pre_cache_sync; /* sync done in previous wrap around */ + bool cur_cache_sync; /* sync done in present cache */ + bool sync_from_start; /* sync done from start of cache */ DltLogStorageFileList *records; /* File name list */ }; +typedef struct DltLogStorageFilterList DltLogStorageFilterList; -typedef struct +struct DltLogStorageFilterList { - char key[DLT_OFFLINE_LOGSTORAGE_MAX_KEY_LEN]; /* Keys stored in hash table */ - DltLogStorageConfigData data; /* Data stored in hash table */ -}DltLogStorageConfig; - + char *key; /* Key to find data */ + DltLogStorageFilterConfig *data; /* Filter data */ + DltLogStorageFilterList *next; /* Pointer to next */ +}; typedef struct { - struct hsearch_data config_htab; /* Hash table object declaration used by hsearch_r()*/ - DltLogStorageConfig *config_data; /* Configuration data */ - char *filter_keys; /* List of all keys stored in config_htab */ + DltLogStorageFilterList *config_list; /* List of all filters */ + DltLogStorageUserConfig uconfig; /* User configurations for file name*/ + int num_configs; /* Number of configs */ int num_filter_keys; /* Number of keys */ - char device_mount_point[DLT_MOUNT_PATH_MAX]; /* Device mount path */ + char device_mount_point[DLT_MOUNT_PATH_MAX + 1]; /* Device mount path */ unsigned int connection_type; /* Type of connection */ unsigned int config_status; /* Status of configuration */ int write_errors; /* number of write errors */ @@ -213,17 +218,9 @@ typedef struct * @param mount_point Device mount path * @return 0 on success, -1 on error */ -extern int dlt_logstorage_device_connected(DltLogStorage *handle, char *mount_point); +int dlt_logstorage_device_connected(DltLogStorage *handle, + char *mount_point); -/** - * dlt_logstorage_load_config - * - * Parse dlt_logstorage.conf file in the device and setup internal info table - * - * @param handle DltLogStorage handle - * @return 0 on success, -1 on error - */ -extern int dlt_logstorage_load_config(DltLogStorage *handle); /** * dlt_logstorage_device_disconnected * De-Initializes DLT Offline Logstorage with respect to device status @@ -232,7 +229,8 @@ extern int dlt_logstorage_load_config(DltLogStorage *handle); * @param reason Reason for device disconnection * @return 0 on success, -1 on error */ -extern int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason); +int dlt_logstorage_device_disconnected(DltLogStorage *handle, + int reason); /** * dlt_logstorage_get_config * @@ -241,25 +239,30 @@ extern int dlt_logstorage_device_disconnected(DltLogStorage *handle, int reason) * data available in the Hash map, this function will return the address * of configuration data for all these 3 combinations * - * @param handle DltLogStorage handle - * @param appid application id - * @param ctxid context id - * @param num_config (o/p) contains the number of filter configration data obtained - * @return on success: address of configuration data, NULL on failure or no configuration data found + * @param handle DltLogStorage handle + * @param config Pointer to array of filter configurations + * @param appid application id + * @param ctxid context id + * @return number of found configurations */ -extern DltLogStorageConfigData **dlt_logstorage_get_config(DltLogStorage *handle, char *apid, char *ctid, int *num_config); +int dlt_logstorage_get_config(DltLogStorage *handle, + DltLogStorageFilterConfig **config, + char *apid, + char *ctid, + char *ecuid); + /** * dlt_logstorage_get_loglevel_by_key * * Obtain the log level for the provided key * This function can be used to obtain log level when the actual - * key stored in the Hash map is availble with the caller + * key stored in the Hash map is available with the caller * * @param handle DltLogstorage handle * @param key key to search for in Hash MAP * @return log level on success:, -1 on error */ -extern int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); +int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); /** * dlt_logstorage_write @@ -275,14 +278,14 @@ extern int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); * @param size2 Size of message body * @return 0 on success or write errors < max write errors, -1 on error */ -extern int dlt_logstorage_write(DltLogStorage *handle, - DltLogStorageUserConfig *uconfig, - unsigned char *data1, - int size1, - unsigned char *data2, - int size2, - unsigned char *data3, - int size3); +int dlt_logstorage_write(DltLogStorage *handle, + DltLogStorageUserConfig *uconfig, + unsigned char *data1, + int size1, + unsigned char *data2, + int size2, + unsigned char *data3, + int size3); /** * dlt_logstorage_sync_caches @@ -292,6 +295,6 @@ extern int dlt_logstorage_write(DltLogStorage *handle, * @param handle DltLogStorage handle * @return 0 on success, -1 otherwise */ -extern int dlt_logstorage_sync_caches(DltLogStorage *handle); +int dlt_logstorage_sync_caches(DltLogStorage *handle); #endif /* DLT_OFFLINE_LOGSTORAGE_H */ diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior.c b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c index f68d10d..6a210b5 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage_behavior.c +++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c @@ -55,7 +55,7 @@ void dlt_logstorage_log_file_name(char *log_file_name, char *name, int idx) { - if (log_file_name == NULL || file_config == NULL) + if ((log_file_name == NULL) || (file_config == NULL)) { return; } @@ -67,16 +67,17 @@ void dlt_logstorage_log_file_name(char *log_file_name, strcat(log_file_name, name); strncat(log_file_name, &file_config->logfile_delimiter, 1); - snprintf(file_index, 10, "%d",idx); + snprintf(file_index, 10, "%d", idx); if (file_config->logfile_maxcounter != UINT_MAX) { /* Setup 0's to be appended in file index until max index len*/ unsigned int digit_idx = 0; unsigned int i = 0; - snprintf(file_index, 10, "%d",idx); + snprintf(file_index, 10, "%d", idx); digit_idx = strlen(file_index); - for(i=0; i<(file_config->logfile_counteridxlen - digit_idx); i++) + + for (i = 0 ; i < (file_config->logfile_counteridxlen - digit_idx) ; i++) { strcat(log_file_name, "0"); } @@ -117,7 +118,7 @@ void dlt_logstorage_sort_file_name(DltLogStorageFileList **head) { int done = 0; - if (head == NULL || *head == NULL || (*head)->next == NULL) + if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL)) { return; } @@ -141,6 +142,7 @@ void dlt_logstorage_sort_file_name(DltLogStorageFileList **head) done = 0; } + pv = &nd->next; nd = nx; nx = nx->next; @@ -164,12 +166,12 @@ void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head) DltLogStorageFileList *wrap_post = NULL; DltLogStorageFileList *n = NULL; - if (head == NULL || *head == NULL || (*head)->next == NULL) + if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL)) { return; } - for (n = *head; n != NULL; n = n->next) + for (n = *head ; n != NULL ; n = n->next) { if (n && n_prev) { @@ -179,8 +181,10 @@ void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head) wrap_pre = n_prev; } } + n_prev = n; } + tail = n_prev; if (wrap_post && wrap_pre) @@ -201,51 +205,58 @@ void dlt_logstorage_rearrange_file_name(DltLogStorageFileList **head) * @return index on success, -1 if no index is found */ unsigned int dlt_logstorage_get_idx_of_log_file( - DltLogStorageUserConfig *file_config, - char *file) + DltLogStorageUserConfig *file_config, + char *file) { unsigned int idx = -1; char *endptr; char *filename; - unsigned int filename_len = 0 ; + unsigned int filename_len = 0; unsigned int fileindex_len = 0; - if (file_config == NULL || file == NULL) + if ((file_config == NULL) || (file == NULL)) { return -1; } /* Calculate actual file name length */ - filename=strchr(file, file_config->logfile_delimiter); + filename = strchr(file, file_config->logfile_delimiter); + + if (filename == NULL) + { + dlt_vlog(LOG_ERR, "Cannot extract filename from %s\n", file); + return -1; + } + filename_len = strlen(file) - strlen(filename); /* index is retrived from file name */ - if(file_config->logfile_timestamp) + if (file_config->logfile_timestamp) { fileindex_len = strlen(file) - - (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + - DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + - filename_len + 1); + (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + + DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + + filename_len + 1); idx = (int) strtol(&file[strlen(file) - - (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + - fileindex_len + - DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN)], + (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + + fileindex_len + + DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN)], &endptr, 10); } else { fileindex_len = strlen(file) - - (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + - filename_len + 1); + (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + + filename_len + 1); - idx = (int) strtol(&file[strlen(file)- - (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN - +fileindex_len)], &endptr, 10); + idx = (int) strtol(&file[strlen(file) - + (DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + + fileindex_len)], &endptr, 10); } - if (endptr == file || idx == 0) + if ((endptr == file) || (idx == 0)) { dlt_log(LOG_ERR, "Unable to calculate index from log file name. Reset to 001.\n"); @@ -262,12 +273,12 @@ unsigned int dlt_logstorage_get_idx_of_log_file( * * @param file_config User configurations for log file * @param path Path to storage directory - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @return 0 on success, -1 on error */ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, char *path, - DltLogStorageConfigData *config) + DltLogStorageFilterConfig *config) { int i = 0; int cnt = 0; @@ -275,15 +286,16 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, struct dirent **files = {0}; unsigned int current_idx = 0; - if (config == NULL || - file_config == NULL || - path == NULL || - config->file_name == NULL) + if ((config == NULL) || + (file_config == NULL) || + (path == NULL) || + (config->file_name == NULL)) { return -1; } cnt = scandir(path, &files, 0, alphasort); + if (cnt < 0) { dlt_log(LOG_ERR, @@ -291,22 +303,24 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, return -1; } - for (i = 0; i < cnt; i++) + for (i = 0 ; i < cnt ; i++) { int len = 0; len = strlen(config->file_name); + if ((strncmp(files[i]->d_name, config->file_name, len) == 0) && - (files[i]->d_name[len] == file_config->logfile_delimiter)) + (files[i]->d_name[len] == file_config->logfile_delimiter)) { DltLogStorageFileList **tmp = NULL; current_idx = dlt_logstorage_get_idx_of_log_file(file_config, files[i]->d_name); - if(config->records == NULL) + if (config->records == NULL) { config->records = malloc(sizeof(DltLogStorageFileList)); + if (config->records == NULL) { ret = -1; @@ -314,16 +328,20 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, "Memory allocation failed\n"); break; } + tmp = &config->records; } else { tmp = &config->records; - while(*(tmp) != NULL) + + while (*(tmp) != NULL) { tmp = &(*tmp)->next; } + *tmp = malloc(sizeof(DltLogStorageFileList)); + if (*tmp == NULL) { ret = -1; @@ -332,8 +350,9 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, break; } } + (*tmp)->name = strdup(files[i]->d_name); - (*tmp)->idx = current_idx; + (*tmp)->idx = current_idx; (*tmp)->next = NULL; } } @@ -345,10 +364,11 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, } /* free scandir result */ - for (i = 0; i < cnt; i++) + for (i = 0 ; i < cnt ; i++) { free(files[i]); } + free(files); return ret; @@ -362,20 +382,20 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, * Otherwise create a new file, but take configured max number of files into * account and remove the oldest file if needed. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param msg_size Size of incoming message * @return 0 on succes, -1 on error */ -int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, +int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int msg_size) { int ret = 0; - char absolute_file_path[DLT_MOUNT_PATH_MAX + 1] = {'\0'}; - char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN] = {'\0'}; + char absolute_file_path[DLT_MOUNT_PATH_MAX + DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 1] = {'\0'}; + char storage_path[DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 1] = {'\0'}; unsigned int num_log_files = 0; struct stat s; DltLogStorageFileList **tmp = NULL; @@ -387,33 +407,40 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, return -1; } - if(snprintf(storage_path, DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN, - "%s/", dev_path) >= DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN) + if (strlen(dev_path) > DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN) { - dlt_log(LOG_ERR, "Mount point path name too long\n"); + dlt_vlog(LOG_ERR, "device path '%s' is too long to store\n", dev_path); return -1; } + snprintf(storage_path, DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN, "%s/", dev_path); + /* check if there are already files stored */ if (config->records == NULL) { if (dlt_logstorage_storage_dir_info(file_config, storage_path, config) != 0) + { return -1; + } } /* obtain locations of newest, current file names, file count */ tmp = &config->records; - while(*(tmp) != NULL) + + while (*(tmp) != NULL) { num_log_files += 1; - if((*tmp)->next == NULL) + + if ((*tmp)->next == NULL) + { newest = tmp; + } tmp = &(*tmp)->next; } - /* need new file*/ + /* need new file*/ if (num_log_files == 0) { dlt_logstorage_log_file_name(file_name, @@ -428,14 +455,16 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, /* Add file to file list */ *tmp = malloc(sizeof(DltLogStorageFileList)); + if (*tmp == NULL) { dlt_log(LOG_ERR, "Memory allocation for file name failed\n"); return -1; } + (*tmp)->name = strdup(file_name); - (*tmp)->idx = 1; + (*tmp)->idx = 1; (*tmp)->next = NULL; } else /* newest file available*/ @@ -446,7 +475,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, ret = stat(absolute_file_path, &s); /* if size is enough, open it */ - if (ret == 0 && s.st_size + msg_size < (int)config->file_size) + if ((ret == 0) && (s.st_size + msg_size < (int)config->file_size)) { config->log = fopen(absolute_file_path, "a+"); } @@ -461,7 +490,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, /* wrap around if max index is reached or an error occurred * while calculating index from file name */ - if (idx > file_config->logfile_maxcounter || idx == 0) + if ((idx > file_config->logfile_maxcounter) || (idx == 0)) { idx = 1; } @@ -474,13 +503,14 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, /* concatenate path and file and open absolute path */ memset(absolute_file_path, 0, - sizeof(absolute_file_path)/sizeof(char)); + sizeof(absolute_file_path) / sizeof(char)); strcat(absolute_file_path, storage_path); strcat(absolute_file_path, file_name); config->log = fopen(absolute_file_path, "a+"); /* Add file to file list */ *tmp = malloc(sizeof(DltLogStorageFileList)); + if (*tmp == NULL) { dlt_log(LOG_ERR, @@ -489,7 +519,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, } (*tmp)->name = strdup(file_name); - (*tmp)->idx = idx; + (*tmp)->idx = idx; (*tmp)->next = NULL; num_log_files += 1; @@ -502,7 +532,7 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, DltLogStorageFileList *n = *head; memset(absolute_file_path, 0, - sizeof(absolute_file_path)/sizeof(char)); + sizeof(absolute_file_path) / sizeof(char)); strcat(absolute_file_path, storage_path); strcat(absolute_file_path, (*head)->name); remove(absolute_file_path); @@ -524,19 +554,324 @@ int dlt_logstorage_open_log_file(DltLogStorageConfigData *config, return ret; } +/** + * dlt_logstorage_find_dlt_header + * + * search for dlt header in cache + * + * @param ptr cache starting position + * @param offset offset + * @param cnt count + * @return index on success, -1 on error + */ +STATIC int dlt_logstorage_find_dlt_header(void *ptr, + unsigned int offset, + unsigned int cnt) +{ + int index = 0; + char substring[] = {'D', 'L', 'T', 0x01}; + while(cnt > 0) + { + if (*((char *)(ptr + offset + index)) == 'D') + { + if (strncmp(ptr + offset + index , substring, 4) == 0) + { + return index; + } + } + cnt--; + index++; + } + return -1; +} + +/** + * dlt_logstorage_check_write_ret + * + * check the return value of fwrite + * + * @param config DltLogStorageFilterConfig + * @param ret return value of fwrite call + */ +STATIC void dlt_logstorage_check_write_ret(DltLogStorageFilterConfig *config, + int ret) +{ + if (config == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + } + if (ret <= 0) + { + if (ferror(config->log) != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to write cache into log file\n", __func__); + } + } + else + { + /* force sync */ + if (fflush(config->log) != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to flush log file\n", __func__); + } + if (fsync(fileno(config->log)) != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync log file\n", __func__); + } + } +} + +/** + * dlt_logstorage_sync_create_new_file + * + * Write the log message and open new log file + * + * @param config DltLogStorageFilterConfig + * @param file_config DltLogStorageUserConfig + * @param dev_path Storage device mount point + * @param remain_file_size log file remaining size + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_logstorage_sync_create_new_file( + DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, + unsigned int remain_file_size) +{ + int index = 0; + int ret; + unsigned int cache_offset = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; + + if (config == NULL || file_config == NULL || dev_path == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + footer = (DltLogStorageCacheFooter *)(config->cache + + config->file_size); + if (footer == NULL) + { + dlt_vlog(LOG_ERR, "%s: Cannot retrieve cache information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + + /* sync capable data to file */ + if (footer->offset >= footer->last_sync_offset) + { + count = config->file_size - footer->offset; + if (count > remain_file_size) + { + count = remain_file_size; + } + index = dlt_logstorage_find_dlt_header(config->cache,footer->offset,count); + cache_offset = footer->offset; + } + else + { + count = config->file_size - footer->last_sync_offset; + if (count > remain_file_size) + { + count = remain_file_size; + } + index = dlt_logstorage_find_dlt_header(config->cache, + footer->last_sync_offset, + count); + cache_offset = footer->last_sync_offset; + + } + if (index >= 0) + { + ret = fwrite(config->cache + cache_offset + index, count - index, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count - index; + } + if (footer->last_sync_offset == 0) + { + footer->last_sync_offset = footer->offset + count; + } + else + { + footer->last_sync_offset += count; + } + config->total_write_count -= count; + + /* sync data to current file in case of file is not full */ + if (config->current_write_file_offset < config->file_size) + { + count = config->file_size - config->current_write_file_offset; + + if (footer->last_sync_offset < config->file_size) + { + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + footer->last_sync_offset += count; + } + /* sync remaining amount of file from start of cache */ + else + { + config->sync_from_start = 1; + if (count > footer->offset) + { + count = footer->offset; + } + ret = fwrite(config->cache, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + footer->last_sync_offset = count; + } + config->total_write_count -= count; + } + + config->current_write_file_offset = 0; + fclose(config->log); + config->log = NULL; + /* get always a new file */ + if (dlt_logstorage_prepare_on_msg(config, + file_config, + dev_path, + config->file_size) != 0) + { + dlt_vlog(LOG_ERR, + "%s: failed to prepare log file for file_size\n", __func__); + return DLT_RETURN_ERROR; + } + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_sync_to_file + * + * Write the log message to log file + * + * @param config DltLogStorageFilterConfig + * @param file_config DltLogStorageUserConfig + * @param dev_path Storage device mount point path + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_logstorage_sync_to_file( + DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path) +{ + int ret = 0; + unsigned int remain_file_size = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; + + if (config == NULL || file_config == NULL || dev_path == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + footer = (DltLogStorageCacheFooter *)(config->cache + config->file_size); + + if (footer == NULL) + { + dlt_vlog(LOG_ERR, "%s: Cannot retrieve cache information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + }; + count = footer->offset - footer->last_sync_offset; + remain_file_size = config->file_size - config->current_write_file_offset; + + /* sync data to file if required sync data exceeds remaining file size */ + if (count > remain_file_size) + { + ret = fwrite(config->cache + footer->last_sync_offset, remain_file_size, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += remain_file_size; + footer->last_sync_offset += remain_file_size; + + count = footer->offset - footer->last_sync_offset; + config->current_write_file_offset = 0; + fclose(config->log); + config->log = NULL; + /* get always a new file */ + if (dlt_logstorage_prepare_on_msg(config, + file_config, + dev_path, + config->file_size) != 0) + { + dlt_vlog(LOG_ERR, + "%s: failed to prepare log file for file_size\n", __func__); + return DLT_RETURN_ERROR; + } + } + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count; + footer->last_sync_offset = footer->offset; + config->cur_cache_sync = 1; + + return DLT_RETURN_OK; +} + +/** + * dlt_logstorage_sync_capable_data_to_file + * + * Write the log message to log file + * + * @param config DltLogStorageFilterConfig + * @param index_status check for index is required or not + * @return 0 on success, -1 on error + */ +STATIC DltReturnValue dlt_logstorage_sync_capable_data_to_file( + DltLogStorageFilterConfig *config, + int index_status) +{ + int ret = 0; + int index = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; + + if (config == NULL) + { + dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } + + footer = (DltLogStorageCacheFooter *)(config->cache + config->file_size); + if (footer == NULL) + { + dlt_vlog(LOG_ERR, "%s: Cannot retrieve cache information\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + }; + count = config->file_size - footer->last_sync_offset; + if (index_status == 1) + { + index = dlt_logstorage_find_dlt_header(config->cache, + footer->last_sync_offset, + count); + } + if (count > 0 && index >=0) + { + ret = fwrite(config->cache + footer->last_sync_offset + index, + count - index, + 1, + config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count - index; + } + config->total_write_count -= count; + footer->last_sync_offset = 0; + + return DLT_RETURN_OK; +} + /** * dlt_logstorage_prepare_on_msg * * Prepare the log file for a certain filer. If log file not open or log * files max size reached, open a new file. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param log_msg_size Size of log message * @return 0 on success, -1 on error */ -int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, +int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size) @@ -544,7 +879,7 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, int ret = 0; struct stat s; - if (config == NULL || file_config == NULL || dev_path == NULL) + if ((config == NULL) || (file_config == NULL) || (dev_path == NULL)) { return -1; } @@ -559,7 +894,9 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, else /* already open, check size and create a new file if needed */ { ret = fstat(fileno(config->log), &s); - if (ret == 0) { + + if (ret == 0) + { /* check if adding new data do not exceed max file size */ if (s.st_size + log_msg_size >= (int)config->file_size) { @@ -582,6 +919,7 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, ret = -1; } } + return ret; } @@ -590,7 +928,7 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, * * Write the log message. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @param data1 header * @param size1 header size * @param data2 storage header @@ -599,32 +937,37 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, * @param size3 payload size * @return 0 on success, -1 on error */ -int dlt_logstorage_write_on_msg(DltLogStorageConfigData *config, - unsigned char *data1, - int size1, - unsigned char *data2, - int size2, - unsigned char *data3, - int size3) +int dlt_logstorage_write_on_msg(DltLogStorageFilterConfig *config, + unsigned char *data1, + int size1, + unsigned char *data2, + int size2, + unsigned char *data3, + int size3) { int ret; - if (config == NULL || data1 == NULL || data2 == NULL || data3 == NULL) + if ((config == NULL) || (data1 == NULL) || (data2 == NULL) || (data3 == NULL)) { return -1; } ret = fwrite(data1, 1, size1, config->log); + if (ret != size1) { dlt_log(LOG_WARNING, "Wrote less data than specified\n"); } + ret = fwrite(data2, 1, size2, config->log); + if (ret != size2) { dlt_log(LOG_WARNING, "Wrote less data than specified\n"); } + ret = fwrite(data3, 1, size3, config->log); + if (ret != size3) { dlt_log(LOG_WARNING, "Wrote less data than specified\n"); @@ -638,14 +981,22 @@ int dlt_logstorage_write_on_msg(DltLogStorageConfigData *config, * * sync data to disk. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig + * @param file_config User configurations for log file + * @param dev_path Storage device path * @param status Strategy flag * @return 0 on success, -1 on error */ -int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status) +int dlt_logstorage_sync_on_msg(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, + int status) { int ret; + file_config = file_config; /* satisfy compiler */ + dev_path = dev_path; + if (config == NULL) { return -1; @@ -671,59 +1022,112 @@ int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status) * files max size reached, open a new file. * Create a memory area to cache data. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @param file_config User configurations for log file * @param dev_path Storage device path * @param log_msg_size Size of log message * @return 0 on success, -1 on error */ -int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size) { - if (config == NULL || file_config == NULL || dev_path == NULL) + if ((config == NULL) || (file_config == NULL) || (dev_path == NULL)) { return -1; } + /* Combinations allowed: on Daemon_Exit with on Demand,File_Size with Daemon_Exit + * File_Size with on Demand, Specific_Size with Daemon_Exit,Specific_Size with on Demand + * Combination not allowed : File_Size with Specific_Size + */ + /* check for combinations of specific_size and file_size strategy */ + if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) && + (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE)) > 0) + { + dlt_log(LOG_WARNING, "wrong combination of sync strategies \n"); + return -1; + } + log_msg_size = log_msg_size; /* satisfy compiler */ /* create file to sync cache into later */ if (config->log == NULL) { - /* get always a new file */ - if (dlt_logstorage_prepare_on_msg(config, - file_config, - dev_path, - config->file_size) != 0) + + if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) && + (config->specific_size > config->file_size)) { dlt_log(LOG_ERR, - "Cannot prepare log file for ON_DAEMON_EXIT sync\n"); + "Cannot prepare log file for ON_DAEMON_SPECIFIC_SIZE sync\n"); return -1; } + else + { + /* get always a new file */ + if (dlt_logstorage_prepare_on_msg(config, + file_config, + dev_path, + config->file_size) != 0) + { + dlt_log(LOG_ERR, + "Cannot prepare log file for ON_DAEMON_EXIT sync\n"); + return -1; + } + } } - /* create cache */ + if (config->cache == NULL) { - /* check total logstorage cache size */ - if ((g_logstorage_cache_size + - config->file_size + - sizeof(DltLogStorageCacheFooter)) > - g_logstorage_cache_max) + + /* check for sync_specific_size strategy */ + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { - dlt_log(LOG_ERR, "Max size of Logstorage Cache already used."); - return -1; + /* check total logstorage cache size */ + if ((g_logstorage_cache_size + + config->specific_size + + sizeof(DltLogStorageCacheFooter)) > + g_logstorage_cache_max) + { + dlt_log(LOG_ERR, "Max size of Logstorage Cache already used."); + return -1; + } + + /* create cache */ + config->cache = calloc(1, + config->specific_size + + sizeof(DltLogStorageCacheFooter)); + + /* update current used cache size */ + g_logstorage_cache_size = config->specific_size + + sizeof(DltLogStorageCacheFooter); } + else /* other cache strategies */ + { - config->cache = calloc(1, - config->file_size + - sizeof(DltLogStorageCacheFooter)); + /* check total logstorage cache size */ + if ((g_logstorage_cache_size + + config->file_size + + sizeof(DltLogStorageCacheFooter)) > + g_logstorage_cache_max) + { + dlt_log(LOG_ERR, "Max size of Logstorage Cache already used."); + return -1; + } - /* update current used cache size */ - g_logstorage_cache_size = config->file_size + - sizeof(DltLogStorageCacheFooter); + /* create cache */ + config->cache = calloc(1, + config->file_size + + sizeof(DltLogStorageCacheFooter)); + + /* update current used cache size */ + g_logstorage_cache_size = config->file_size + + sizeof(DltLogStorageCacheFooter); + } if (config->cache == NULL) { @@ -740,7 +1144,7 @@ int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, * * Write the log message. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig * @param data1 header * @param size1 header size * @param data2 storage header @@ -749,7 +1153,7 @@ int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, * @param size3 payload size * @return 0 on success, -1 on error */ -int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_write_msg_cache(DltLogStorageFilterConfig *config, unsigned char *data1, int size1, unsigned char *data2, @@ -758,25 +1162,44 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, int size3) { DltLogStorageCacheFooter *footer = NULL; + DltLogStorageUserConfig *uconfig = NULL; + char *dev_path = NULL; int msg_size; int remain_cache_size; void *curr_write_addr = NULL; + int ret = 0; - if (config == NULL || data1 == NULL || size1 < 0 || data2 == NULL || - size2 < 0 || data3 == NULL || size3 < 0 || config->cache == NULL) + if ((config == NULL) || (data1 == NULL) || (size1 < 0) || (data2 == NULL) || + (size2 < 0) || (data3 == NULL) || (size3 < 0) || (config->cache == NULL)) { return -1; } - footer = (DltLogStorageCacheFooter *)(config->cache + config->file_size); - if (footer == NULL) + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) { - dlt_log(LOG_ERR, "Cannot retrieve cache footer. Address is NULL\n"); - return -1; + footer = (DltLogStorageCacheFooter *)(config->cache + + config->specific_size); + if (footer == NULL) + { + dlt_log(LOG_ERR, "Cannot retrieve cache footer. Address is NULL\n"); + return -1; + } + msg_size = size1 + size2 + size3; + remain_cache_size = config->specific_size - footer->offset; + } + else + { + footer = (DltLogStorageCacheFooter *)(config->cache + + config->file_size); + if (footer == NULL) + { + dlt_log(LOG_ERR, "Cannot retrieve cache footer. Address is NULL\n"); + return -1; + } + msg_size = size1 + size2 + size3; + remain_cache_size = config->file_size - footer->offset; } - - msg_size = size1 + size2 + size3; - remain_cache_size = config->file_size - footer->offset; if (msg_size < remain_cache_size) /* add at current position */ { @@ -785,12 +1208,61 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, } else if (msg_size > remain_cache_size) { - if ((unsigned int) msg_size > config->file_size) + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + { + /*check for message size exceeds cache size for specific_size strategy */ + if ((unsigned int) msg_size > config->specific_size) + { + dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n"); + return -1 ; + } + } + else if ((unsigned int) msg_size > config->file_size) { dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n"); return -1; } + /*sync to file for specific_size or file_size */ + if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) > 0) + { + ret = config->dlt_logstorage_sync(config, + uconfig, + dev_path, + DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE); + if (ret != 0) + { + dlt_log(LOG_ERR,"dlt_logstorage_sync: Unable to sync.\n"); + return -1; + } + } + else if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + { + + ret = config->dlt_logstorage_sync(config, + uconfig, + dev_path, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE); + if (ret != 0) + { + dlt_log(LOG_ERR,"dlt_logstorage_sync: Unable to sync.\n"); + return -1; + } + } + else if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_DEMAND) > 0) + { + config->pre_cache_sync = config->cur_cache_sync; + config->cur_cache_sync = 0; + if (config->pre_cache_sync == 0) + { + footer->last_sync_offset = 0; + } + } + /* start writing from beginning */ curr_write_addr = config->cache; footer->offset = msg_size; @@ -799,7 +1271,6 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, else /* message just fits into cache */ { curr_write_addr = (void *)(config->cache + footer->offset); - footer->offset = 0; footer->wrap_around_cnt += 1; } @@ -818,14 +1289,21 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, * * sync data to disk. * - * @param config DltLogStorageConfigData + * @param config DltLogStorageFilterConfig + * @param file_config User configurations for log file + * @param dev_path Storage device path * @param status Strategy flag * @return 0 on success, -1 on error */ -int dlt_logstorage_sync_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_sync_msg_cache(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, int status) { int ret = 0; + unsigned int remain_file_size = 0; + unsigned int count = 0; + DltLogStorageCacheFooter *footer = NULL; if (config == NULL) @@ -836,56 +1314,192 @@ int dlt_logstorage_sync_msg_cache(DltLogStorageConfigData *config, /* sync only, if given strategy is set */ if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, status) > 0) { - if (config->log == NULL || config->cache == NULL) + if ((config->log == NULL) || (config->cache == NULL)) { dlt_log(LOG_ERR, "Cannot copy cache to file. One of both is NULL\n"); return -1; } - /* TODO: write only what is needed */ - /* write ring buffer into file */ - footer = (DltLogStorageCacheFooter *)(config->cache + - config->file_size); + /* sync cache data to file for specific_size strategies */ - if (footer == NULL) + if ((status == DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) + || ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + && (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND)) + || ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) + && (status == DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT))) { - dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); - return -1; - } + footer = (DltLogStorageCacheFooter *)(config->cache + + config->specific_size); + if (footer == NULL) + { + dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); + return -1; + } - /* TODO: check if really the whole cache need to be written */ - /* write cache to file */ - ret = fwrite(config->cache, config->file_size, 1, config->log); + count = footer->offset - footer->last_sync_offset; + /* write ring buffer into file */ + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += footer->offset - footer->last_sync_offset; + remain_file_size = config->file_size - config->current_write_file_offset; - if (ret <= 0) - { - if (ferror(config->log) != 0) + if (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND) + { + footer->last_sync_offset = footer->offset; + } + else { - dlt_log(LOG_CRIT, "Failed to write cache into log file\n"); + footer->last_sync_offset = 0; } + + if (remain_file_size < config->specific_size) + { + config->current_write_file_offset = 0; + /* clean ring buffer and reset footer information */ + memset(config->cache, + 0, + config->specific_size + sizeof(DltLogStorageCacheFooter)); + + /* close the file, a new one will be created when prepare is + * called again */ + + fclose(config->log); + config->log = NULL; + } } - else + /* sync cache data to file for file size strategies*/ + + else if ((status == DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) || + (status == DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) || + ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, + DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) > 0) + && (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND))) { - /* force sync */ - if (fsync(fileno(config->log)) != 0) + footer = (DltLogStorageCacheFooter *)(config->cache + + config->file_size); + if (footer == NULL) { - dlt_log(LOG_ERR, "Failed to sync log file\n"); + dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); + return -1; + } + + count = footer->offset - footer->last_sync_offset; + /* write cache to file */ + ret = fwrite(config->cache + footer->last_sync_offset, count, 1, config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += footer->offset - footer->last_sync_offset; + footer->last_sync_offset = footer->offset; + + if ((status != DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) + && (status != DLT_LOGSTORAGE_SYNC_ON_DEMAND)) + { + config->current_write_file_offset = 0; + /* clean ring buffer and reset footer information */ + memset(config->cache, + 0, + config->file_size + sizeof(DltLogStorageCacheFooter)); + + /* close the file, a new one will be created when prepare is + * called again */ + fclose(config->log); + config->log = NULL; } } + /* sync cache to file for on_demand strategy */ - /* do not reinitialize in case of ON_DAEMON_EXIT */ - if (status != DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) + else if (status == DLT_LOGSTORAGE_SYNC_ON_DEMAND) { - /* clean ring buffer and reset footer information */ - memset(config->cache, - 0, - config->file_size + sizeof(DltLogStorageCacheFooter)); + config->sync_from_start = 0; + if ((file_config == NULL) || (dev_path == NULL)) + { + dlt_log(LOG_ERR, "Cannot retrieve user configuration or mount point\n"); + return -1; + } + footer = (DltLogStorageCacheFooter *)(config->cache + + config->file_size); + if (footer == NULL) + { + dlt_log(LOG_ERR, "Cannot retrieve cache information\n"); + return -1; + } + /* check for wrap around is 0 or cache is synced at least once + * in every wrap around */ + + if ((footer->wrap_around_cnt < 1) || (config->cur_cache_sync == 1)) + { + ret = dlt_logstorage_sync_to_file(config, + file_config, + dev_path); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync data to file \n", __func__); + } + } + else + { + remain_file_size = config->file_size - config->current_write_file_offset; + + /* check for total bytes of data need to sync */ + if (footer->offset >= footer->last_sync_offset ) + { + config->total_write_count = config->file_size; + } + else + { + config->total_write_count = config->file_size - footer->last_sync_offset + footer->offset; + } - /* close the file, a new one will be created when prepare is - * called again */ - fclose(config->log); - config->log = NULL; + /* sync data to file if required sync data exceeds remaining file size */ + if (config->total_write_count >= remain_file_size) + { + ret = dlt_logstorage_sync_create_new_file(config, + file_config, + dev_path, + remain_file_size); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync and open new file\n", __func__); + } + + /* sync remaining end of cache data to new file*/ + if (config->sync_from_start == 0) + { + ret = dlt_logstorage_sync_capable_data_to_file(config, 0); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync capable data to file\n", __func__); + } + } + } + /* sync data to file if required sync data less than remaining file size */ + else + { + ret = dlt_logstorage_sync_capable_data_to_file(config, 1); + if (ret != 0) + { + dlt_vlog(LOG_ERR, "%s: failed to sync capable data\n", __func__); + } + } + /* sync data to file from almost the begin of cache + * if still data needs to sync */ + + if (config->total_write_count > 0) + { + count = footer->offset - footer->last_sync_offset; + ret = fwrite(config->cache + footer->last_sync_offset, + count, + 1, + config->log); + dlt_logstorage_check_write_ret(config, ret); + config->current_write_file_offset += count; + + footer->last_sync_offset += count; + } + config->cur_cache_sync = 1; + } } } diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior.h b/src/offlinelogstorage/dlt_offline_logstorage_behavior.h index f26ce69..68de0ab 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage_behavior.h +++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior.h @@ -53,29 +53,32 @@ #define DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ /* ON_MSG behavior */ -int dlt_logstorage_prepare_on_msg(DltLogStorageConfigData *config, +int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size); -int dlt_logstorage_write_on_msg(DltLogStorageConfigData *config, - unsigned char *data1, - int size1, - unsigned char *data2, - int size2, - unsigned char *data3, - int size3); +int dlt_logstorage_write_on_msg(DltLogStorageFilterConfig *config, + unsigned char *data1, + int size1, + unsigned char *data2, + int size2, + unsigned char *data3, + int size3); /* status is strategy, e.g. DLT_LOGSTORAGE_SYNC_ON_MSG is used when callback * is called on message received */ -int dlt_logstorage_sync_on_msg(DltLogStorageConfigData *config, int status); +int dlt_logstorage_sync_on_msg(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, + int status); /* Logstorage cache functionality */ -int dlt_logstorage_prepare_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int log_msg_size); -int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_write_msg_cache(DltLogStorageFilterConfig *config, unsigned char *data1, int size1, unsigned char *data2, @@ -83,7 +86,9 @@ int dlt_logstorage_write_msg_cache(DltLogStorageConfigData *config, unsigned char *data3, int size3); -int dlt_logstorage_sync_msg_cache(DltLogStorageConfigData *config, +int dlt_logstorage_sync_msg_cache(DltLogStorageFilterConfig *config, + DltLogStorageUserConfig *file_config, + char *dev_path, int status); #endif /* DLT_OFFLINELOGSTORAGE_DLT_OFFLINE_LOGSTORAGE_BEHAVIOR_H_ */ diff --git a/src/shared/dlt_common.c b/src/shared/dlt_common.c index aafa026..28df590 100644 --- a/src/shared/dlt_common.c +++ b/src/shared/dlt_common.c @@ -87,7 +87,7 @@ static char *service_id[] = {"","set_log_level","set_trace_status","get_log_info "get_local_time","use_ecu_id","use_session_id","use_timestamp","use_extended_header","set_default_log_level","set_default_trace_status", "get_software_version","message_buffer_overflow" }; -static char *return_type[] = {"ok","not_supported","error","","","","","","no_matching_context_id"}; +static char *return_type[] = {"ok","not_supported","error","perm_denied","warning","","","","no_matching_context_id"}; /* internal function definitions */ int dlt_buffer_get(DltBuffer *buf,unsigned char *data, int max_size,int delete); -- cgit v1.2.1