From 4ed1b974f6155f8a042b4b39a2619898981e3870 Mon Sep 17 00:00:00 2001 From: lvklevankhanh <119659574+lvklevankhanh@users.noreply.github.com> Date: Fri, 1 Sep 2023 03:43:27 -0400 Subject: [PATCH] Logstorage changes (#525) * lib: Introduce WITH_LIB_NO_VERSION cmake option Signed-off By: Saya Sugiura * logstorage: optional index and stop mode adds options to imitate libdlt file logging with offlinelogstorage: - optional index when NOFiles == 1 e.g.: APID.dlt - disable ringbuffer for specific filters: OverwriteBehavior=DISCARD_NEW this stops the automatic removal of the oldest messages. Also contains: - some fixes for memcheck findings about usage of uninitialized memory. - cmake coverage target and option can be used to generate a html report about the code coverage by the ctest tests. Signed-off-by: Felix Herrmann * logstorage: Open file on correct cache size In case of ON_SPECIFIC_SIZE sync strategy, the file was not opened on correct cache size, so the file size was smaller than defined even next log messages can fit there. Signed-off-by: Saya Sugiura * logstorage: Test all sync strategies All sync strategies are verified in logstorage component test. To make it work, following adaptions are also done: - dlt-logstorage-control: Add option to specify dlt.conf path Signed-off-by: Saya Sugiura * Offline-Logstorage - Skip the file when prepare fails This change allows to append directory path in File option in dlt_logstorage.conf (e.g. File=path/Filename). If path does not exist and file preparation fails, it will try up to DLT_OFFLINE_LOGSTORAGE_MAX_ERRORS times (=5 times) If it reaches the maximum, that file will be skipped from next trial so that the daemon does not try to prepare file under non-existing directory every time the log message is received. Signed-off By: Saya Sugiura * logstorage: Add internal function to store config Signed-off-by: Saya Sugiura * cfg: make multiple config mechanism avaiable in logstorage Signed-off-by: Felix Herrmann * logstorage: Add max cache size test case Signed-off By: Matthias Dangers * logstorage: Add debug and details log messages Signed-off By: Saya Sugiura * logstorage: Add option to disable network routing in DLT Daemon, when only file is configured If the option is enabled in dlt_logstorage,conf, routing to network will be disabled if the corresponding key (APID:CTID:ECUID) is available in logstorage. For ecucfg, if network is not set to log mode, routing to network will be disabled. Signed-off-by: Saya Sugiura ssugiura@jp.adit-jv.com * Resolve compile warnings Signed-off-by: Saya Sugiura * logstorage: Correctly calculate logstorage cache Signed-off-by: Saya Sugiura * logstorage:update remain file size In CACHE_BASED strategy, the current write offset file should be updated only if the it is less than configured size Signed-off-by: Bui Nguyen Quoc Thanh * LogStorage: Call fsync() before fclose() for ON_MSG sync strategy To sync buffer to file, fsync() is called before fclose() on ON_MSG. Signed-off-by: Saya Sugiura * logstorage: Change path of MessageFilterConfigFile in dlt.conf Set value of configured file_size for checking logstorage file synchronization Clean the created DLT files on every test cases Dlt-daemon cannot run when testing with CTest under source folder due to path of MessageFilterConfigFile is incorrect Change relative path of MessageFilterConfigFile to absolute path in dlt.conf.in Signed-off-by: Le Tin * logstorage:incorrect type of index The variable type of index should not be unsigned if it is possible to be negative. Otherwise, the validation will be wrong Signed-off-by: Bui Nguyen Quoc Thanh --------- Signed-off-by: Felix Herrmann Signed-off-by: Saya Sugiura Signed-off-by: Saya Sugiura ssugiura@jp.adit-jv.com Signed-off-by: Bui Nguyen Quoc Thanh Signed-off-by: Le Tin Co-authored-by: Saya Sugiura Co-authored-by: Felix Herrmann Co-authored-by: Matthias Dangers Co-authored-by: Bui Nguyen Quoc Thanh Co-authored-by: Le Tin --- .gitignore | 4 + CMakeLists.txt | 30 +- doc/design/dlt_offline_logstorage_design.md | 740 ++++++++++++++++++ doc/dlt_offline_logstorage.md | 43 +- src/console/dlt-control-common.c | 12 + src/console/dlt-control-common.h | 2 + src/console/logstorage/dlt-logstorage-ctrl.c | 13 +- src/daemon/dlt-daemon.c | 3 + src/daemon/dlt-daemon.h | 3 +- src/daemon/dlt.conf | 3 + src/daemon/dlt_daemon_client.c | 56 +- src/daemon/dlt_daemon_common.c | 2 +- src/daemon/dlt_daemon_offline_logstorage.c | 35 +- src/daemon/dlt_daemon_offline_logstorage.h | 3 +- src/lib/CMakeLists.txt | 10 +- src/lib/dlt_user.c | 4 +- .../dlt_offline_logstorage.c | 290 ++++++- .../dlt_offline_logstorage.h | 39 +- .../dlt_offline_logstorage_behavior.c | 271 +++++-- ...dlt_offline_logstorage_behavior_internal.h | 9 +- .../dlt_offline_logstorage_internal.h | 2 +- src/shared/dlt_common.c | 2 +- src/shared/dlt_config_file_parser.c | 2 +- tests/CMakeLists.txt | 30 +- tests/component/CMakeLists.txt | 5 + .../component/disable_network/CMakeLists.txt | 46 ++ .../disable_network/disable_network.cpp | 57 ++ tests/component/disable_network/dlt.conf | 7 + .../disable_network/dlt_logstorage.conf | 10 + .../disable_network/dlt_message_filter.conf | 10 + .../lib/context_unreg_forbid/CMakeLists.txt | 22 + .../lib/context_unreg_forbid/dlt.conf.in | 2 + tests/component/logstorage/CMakeLists.txt | 1 + .../logstorage/disable_network/dlt.conf.in | 7 + .../logstorage_filepath/dlt.conf.in | 7 + .../logstorage_fsync/CMakeLists.txt | 31 + .../logstorage/logstorage_fsync/dlt.conf.in | 7 + .../logstorage_fsync/dlt_logstorage.conf | 9 + .../logstorage_fsync/dlt_message_filter.conf | 10 + .../logstorage/logstorage_fsync/logfsync.cpp | 16 + .../logstorage_fsync/logstorage_fsync.cpp | 57 ++ .../logstorage_max_cache_size/dlt.conf.in | 7 + .../logstorage_multi_file/dlt.conf.in | 7 + .../logstorage_one_file/dlt.conf.in | 7 + .../logstorage_filepath/CMakeLists.txt | 45 ++ tests/component/logstorage_filepath/dlt.conf | 7 + .../logstorage_filepath/dlt_logstorage.conf | 17 + .../dlt_message_filter.conf | 10 + .../logstorage_filepath.cpp | 57 ++ .../logstorage_max_cache_size/CMakeLists.txt | 23 + .../logstorage_max_cache_size/dlt.conf | 8 + .../dlt_logstorage.conf | 44 ++ .../dlt_message_filter.conf | 10 + .../logstorage_max_cache_size.cpp | 39 + .../logstorage_multi_file/CMakeLists.txt | 93 +++ .../component/logstorage_multi_file/dlt.conf | 7 + .../logstorage_multi_file/dlt_logstorage.conf | 131 ++++ .../dlt_message_filter.conf | 10 + .../logstorage_multi_file.cpp | 57 ++ .../logstorage_one_file/CMakeLists.txt | 79 ++ tests/component/logstorage_one_file/dlt.conf | 7 + .../logstorage_one_file/dlt_logstorage.conf | 131 ++++ .../dlt_message_filter.conf | 10 + .../logstorage_one_file.cpp | 57 ++ tests/gtest_dlt_daemon_offline_log.cpp | 240 +++++- tests/gtest_dlt_daemon_offline_log.sh | 1 + 66 files changed, 2764 insertions(+), 252 deletions(-) create mode 100644 doc/design/dlt_offline_logstorage_design.md create mode 100644 tests/component/CMakeLists.txt create mode 100644 tests/component/disable_network/CMakeLists.txt create mode 100644 tests/component/disable_network/disable_network.cpp create mode 100644 tests/component/disable_network/dlt.conf create mode 100644 tests/component/disable_network/dlt_logstorage.conf create mode 100644 tests/component/disable_network/dlt_message_filter.conf create mode 100644 tests/component/lib/context_unreg_forbid/CMakeLists.txt create mode 100644 tests/component/lib/context_unreg_forbid/dlt.conf.in create mode 100644 tests/component/logstorage/CMakeLists.txt create mode 100644 tests/component/logstorage/disable_network/dlt.conf.in create mode 100644 tests/component/logstorage/logstorage_filepath/dlt.conf.in create mode 100644 tests/component/logstorage/logstorage_fsync/CMakeLists.txt create mode 100644 tests/component/logstorage/logstorage_fsync/dlt.conf.in create mode 100644 tests/component/logstorage/logstorage_fsync/dlt_logstorage.conf create mode 100644 tests/component/logstorage/logstorage_fsync/dlt_message_filter.conf create mode 100644 tests/component/logstorage/logstorage_fsync/logfsync.cpp create mode 100644 tests/component/logstorage/logstorage_fsync/logstorage_fsync.cpp create mode 100644 tests/component/logstorage/logstorage_max_cache_size/dlt.conf.in create mode 100644 tests/component/logstorage/logstorage_multi_file/dlt.conf.in create mode 100644 tests/component/logstorage/logstorage_one_file/dlt.conf.in create mode 100644 tests/component/logstorage_filepath/CMakeLists.txt create mode 100644 tests/component/logstorage_filepath/dlt.conf create mode 100644 tests/component/logstorage_filepath/dlt_logstorage.conf create mode 100644 tests/component/logstorage_filepath/dlt_message_filter.conf create mode 100644 tests/component/logstorage_filepath/logstorage_filepath.cpp create mode 100644 tests/component/logstorage_max_cache_size/CMakeLists.txt create mode 100644 tests/component/logstorage_max_cache_size/dlt.conf create mode 100644 tests/component/logstorage_max_cache_size/dlt_logstorage.conf create mode 100644 tests/component/logstorage_max_cache_size/dlt_message_filter.conf create mode 100644 tests/component/logstorage_max_cache_size/logstorage_max_cache_size.cpp create mode 100644 tests/component/logstorage_multi_file/CMakeLists.txt create mode 100644 tests/component/logstorage_multi_file/dlt.conf create mode 100644 tests/component/logstorage_multi_file/dlt_logstorage.conf create mode 100644 tests/component/logstorage_multi_file/dlt_message_filter.conf create mode 100644 tests/component/logstorage_multi_file/logstorage_multi_file.cpp create mode 100644 tests/component/logstorage_one_file/CMakeLists.txt create mode 100644 tests/component/logstorage_one_file/dlt.conf create mode 100644 tests/component/logstorage_one_file/dlt_logstorage.conf create mode 100644 tests/component/logstorage_one_file/dlt_message_filter.conf create mode 100644 tests/component/logstorage_one_file/logstorage_one_file.cpp diff --git a/.gitignore b/.gitignore index 0da830a7c..1690250e2 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ include/dlt/dlt_user.h cmake-build-debug/ .vscode/ googletest/ + +# exclude temporary files +cscope.out +*.swp diff --git a/CMakeLists.txt b/CMakeLists.txt index a0255eb51..156791d0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,21 +98,20 @@ set(DLT_USER "covesa" set(DLT_QNX_SLOG_ADAPTER_WAIT_BUFFER_TIMEOUT_MS "100" CACHE STRING "Timeout in milliseconds to wait before messages are dropped when input buffer is full") -option(WITH_DLT_PKGCONFIG "Set to ON to generate pkgconfig .pc files" ON) -option(WITH_DLT_CXX11_EXT "Set to ON to build C++11 extensions" OFF) -option(WITH_DLT_COREDUMPHANDLER "EXPERIMENTAL! Set to ON to build src/core_dump_handler binaries. EXPERIMENTAL" OFF) -option(WITH_DLT_LOGSTORAGE_CTRL_UDEV "PROTOTYPE! Set to ON to build logstorage control with udev support" OFF) -option(WITH_DLT_LOGSTORAGE_GZIP "Set to ON to build logstorage control with gzip compression support" OFF) -option(WITH_DLT_USE_IPv6 "Set to ON for IPv6 support" ON) -option(WITH_DLT_KPI "Set to ON to build src/kpi binaries" OFF) -option(WITH_DLT_FATAL_LOG_TRAP "Set to ON to enable DLT_LOG_FATAL trap(trigger segv inside dlt-user library)" OFF) -option(WITH_UDP_CONNECTION "Set to ON to enable dlt UDP multicast SUPPORT" OFF) -option(WITH_LIB_SHORT_VERSION "Set to ON to build library with only major number in version" OFF) -option(WITH_DLT_DISABLE_MACRO "Set to ON to build code without Macro interface support" OFF) -option(WITH_LEGACY_INCLUDE_PATH "Set to ON to add /dlt to include paths - for the CMake config file, in addition to only " ON) -option(WITH_EXTENDED_FILTERING "Set to OFF to build without extended filtering. - Json filter only supports Linux based system with json-c and QNX" OFF) +option(WITH_DLT_PKGCONFIG "Set to ON to generate pkgconfig .pc files" ON) +option(WITH_DLT_CXX11_EXT "Set to ON to build C++11 extensions" OFF) +option(WITH_DLT_COREDUMPHANDLER "EXPERIMENTAL! Set to ON to build src/core_dump_handler binaries. EXPERIMENTAL" OFF) +option(WITH_DLT_LOGSTORAGE_CTRL_UDEV "PROTOTYPE! Set to ON to build logstorage control application with udev support" OFF) +option(WITH_DLT_LOGSTORAGE_GZIP "Set to ON to build logstorage control application with gzip compression support" OFF) +option(WITH_DLT_USE_IPv6 "Set to ON for IPv6 support" ON) +option(WITH_DLT_KPI "Set to ON to build src/kpi binaries" OFF) +option(WITH_DLT_FATAL_LOG_TRAP "Set to ON to enable DLT_LOG_FATAL trap(trigger segv inside dlt-user library)" OFF) +option(WITH_UDP_CONNECTION "Set to ON to enable dlt UDP multicast SUPPORT" OFF) +option(WITH_LIB_NO_VERSION "Set to ON to build library without any version" OFF) +option(WITH_LIB_SHORT_VERSION "Set to ON to build library with only major number in version" OFF) +option(WITH_DLT_DISABLE_MACRO "Set to ON to build code without Macro interface support" OFF) +option(WITH_LEGACY_INCLUDE_PATH "Set to ON to add /dlt to include paths for the CMake config file, in addition to only " ON) +option(WITH_EXTENDED_FILTERING "Set to OFF to build without extended filtering. Using json filter files is only supported for Linux based system with json-c and QNX." OFF) option(WITH_DLT_DAEMON_VSOCK_IPC "Set to ON to enable VSOCK support in daemon" OFF) option(WITH_DLT_LIB_VSOCK_IPC "Set to ON to enable VSOCK support in library (DLT_IPC is not used in library)" OFF) @@ -473,6 +472,7 @@ message(STATUS "DLT_VSOCK_PORT = ${DLT_VSOCK_PORT}") message(STATUS "WITH_UDP_CONNECTION = ${WITH_UDP_CONNECTION}") message(STATUS "WITH_DLT_QNX_SYSTEM = ${WITH_DLT_QNX_SYSTEM}") message(STATUS "WITH_DLT_NETWORK_TRACE = ${WITH_DLT_NETWORK_TRACE}") +message(STATUS "WITH_LIB_NO_VERSION = ${WITH_LIB_NO_VERSION}") message(STATUS "WITH_LIB_SHORT_VERSION = ${WITH_LIB_SHORT_VERSION}") message(STATUS "WITH_LEGACY_INCLUDE_PATH = ${WITH_LEGACY_INCLUDE_PATH}") message(STATUS "WITH_EXTENDED_FILTERING = ${WITH_EXTENDED_FILTERING}") diff --git a/doc/design/dlt_offline_logstorage_design.md b/doc/design/dlt_offline_logstorage_design.md new file mode 100644 index 000000000..570f6afe9 --- /dev/null +++ b/doc/design/dlt_offline_logstorage_design.md @@ -0,0 +1,740 @@ +# DLT Offline Logstorage Design Specification + +Back to [README.md](../../README.md) + +## Executive Summary + +This document describes DLT Offline Logstorage feature. It includes software +architecture and design. DLT Offline Logstorage offers the possibility to store +application logs on different storage devices by just plug-in the storage device +into the target. The configuration of what log messages will be stored is read +from a special configuration file which has to be installed on the storage +device before inserting into the target. + +Usage is available in [dlt_offline_logstorage.md](../dlt_offline_logstorage.md). + +## Scope + +This document is written to understand design and implementation, and should +help to use DLT Logstorage feature in the correct way. + +## Requirements + +## Design Considerations + +The following points are considered for the design of Offline Logstorage: + +**Reusability** + +The existing implementation of the DLT shall be reused with minor modification +and adaptation of the existing DLT design. + +**Portability** + +It shall be ensured that while updating the DLT source code care is taken not to +alter the platform dependencies of the existing DLT; thereby maintaining the +portability design in DLT. + +**API consistency** + +The interface between DLT Daemon, DLT Client and DLT applications shall not be +changed. + +## Architecture + +This chapter gives an overview of Offline Logstorage architecture inside DLT. +More details of design itself are given in later session. + +### Use Case View + +#### Configuration + +Use Case | Configuration +----- | ---- +Responsibilities | *DLT Daemon*: Apply log level filter, Change Offline Logstorage configuration, Store log message to device, *System Monitoring Instance*: Informs DLT Daemon about storage device +Trigger | Storage device is plugged into the system +Pre-Condition | Storage device contains a configuration file +Result | DLT Daemon is configured to store logs of configured applications into files on storage device +Exceptions | - +Variants | - + +#### Log to storage device + +Use Case | Log to storage device +----- | ---- +Responsibilities | *Application*: Log message, *DLT Daemon*: Apply log level filter, Store log message to device +Trigger | Application starts logging message through DLT interface +Pre-Condition | Storage device inserted and Logstorage configuration done +Result | Log message is stored in file on storage device +Exceptions | - +Variants | - + +#### Log to FLASH storage device + +Use Case | Log to FLASH storage device +----- | ---- +Responsibilities | *Application*: Log message, *DLT Daemon*: Apply log level filter, Store log messages in RAM, Store log message to device on a specific event +Trigger | Application starts logging message through DLT interface +Pre-Condition | DLT Daemon is configured to use a folder on the FLASH storage as Offline Logstorage device +Result | Log message is stored in file on storage device +Exceptions | - +Variants | - + +#### Update Log Level in Passive Node + +Use Case | Update Log Level in Passive Node +----- | ---- +Responsibilities | *User* Creates DLT Logstorage Configuration file, Stores DLT Logstorage Configuration file on a storage device, Notifies DLT Daemon to attach DLT Logstorage device (e.g. via HMI), *DLT Daemon*: Validates DLT Logstorage Configuration File, Sends Log Level change request to Application via connected passive Node DLT Daemon Application (DLT Library), Activates the received Log Level +Trigger | Notification send to DLT Daemon (e.g. via HMI) to activate a DLT Logstorage device +Pre-Condition | Storage device contains a configuration file, Configured storage location is writeable by DLT Daemon +Result | Application has updated the Log Level +Exceptions | DLT Logstorage Configuration file is missing or invalid, Configured storage location is not writable by DLT Daemon, The configured Application is not running, The configured node (ECU Identifier) is not connected +Variants | - + +#### Store Non-Verbose Log message + +Use Case | Store Non-Verbose Log Message +----- | ---- +Responsibilities | *Application*: Sends DLT Non-Verbose Log Message, *DLT Daemon*: Receives DLT Non-Verbose Log Message, Filters DLT Non-Verbose Log Message based on ECU identifier, Writes DLT Non-Verbose Log Message into configured log file +Trigger | Application reaches a state that results in sending a Log Message +Pre-Condition | Log Level is configured, Storage location is writable by DLT Daemon +Result | DLT Non-Verbose Log Message stored in log file +Exceptions | Received Log Message is filtered (no valid filter configuration found) +Variants | - + +### External View +DLT consists of the DLT Daemon which acts as central component of DLT. It is +responsible for receiving logs from applications and forwarding them to +connected DLT clients. In case of Logstorage, the logs are filtered and stored +directly into files on storage devices depending on given configuration. + +![External view](images/logstorage/dlt_logstorage_external.png "External view") + +The DLT Daemon furthermore provides an interface to send control messages to the +DLT Daemon or connected applications. This interface is used by DLT Offline +Logstorage. When the DLT Offline Logstorage Control Application is triggered due +to an attached storage device or executed by another application, it informs the +DLT Daemon about attached storage devices. The DLT Daemon will then read the +configuration file and start storing log messages to the device. The system has +to make sure that the device is mounted as read-write; otherwise no logs will be +stored onto the device. When a used device is removed, the Logstorage Control +application is triggered again and informs the DLT Daemon about the removal. The +DLT Daemon will stop storing logs onto the removed device. The extended +functionality is that the DLT Logstorage Configuration file might contain a +specific Log Level configuration for DLT Applications running on a Passive Node. +In this case, the Gateway DLT Daemon has to send a Log Level Change Control +message to the connected Passive DLT Daemon. The Passive DLT Daemon afterwards +forwards this request to the DLT Application itself. The DLT Application finally +configures its Log Level. Log messages sent by applications running on the +Passive Node are forwarded to the Gateway DLT Daemon via Passive DLT Daemon and +finally stored inside a DLT Logstorage Storage Device. + +## Interface Description + +There are no changes in the interface to DLT applications, but the description +of configuration file for Logstorage logging is given here. Internal design is +explained in later session. + +### Logstorage configuration file + +The Logstorage configuration file will provide the user with configurable +options to setup device settings, log filters and storage locations of the log +messages. To easily implement applications for creating project specific +configuration files, the used file format is INI. An example configuration file +describing all configuration parameters can be found below. Mandatory name of +the configuration file is: ***dlt_logstorage.conf***. + +``` +[FILTER1] +LogAppName=APP1 +ContextName=CON1,CON2 +LogLevel=DLT_LOG_INFO +File=App +FileSize=10000 +NOFiles=10 + +[FILTER2] +LogAppName=TEST +ContextName=.* +LogLevel=DLT_LOG_ERROR +File=Test +FileSize=250000 +NOFiles=5 +EcuID=ECU2 +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 +``` + +As seen in example configuration file, a filter configuration consists of +- A **unique name** of the filter (for a certain storage device) +- **LogAppName**: Name of application to store logs from. Multiple applications + can be separated by ",". ".*" denotes all applications +- **ContextName**: Name or names of contexts to store logs from. Multiple + contexts can be separated by ",". ".*" denotes all contexts of the application +- **LogLevel**: Define log level +- **File**: Base name of the created files that containing the logs. +- **FileSize**: File size in bytes +- **NOFiles**: Number of created files before oldest is deleted and a new one is + created. The numbering will continue. E.g. If 10 files have to be created and + the first is deleted, the next one is *_011_.dlt* +- **EcuID (optional)**: Only handle messages coming from the specified ECU. +- **SyncBehavior (optional)**: Sync behavior of the Filter configuration. It is + possible to add a list of Sync strategies. +- **SpecificSize (optional)**: Size in bytes when messages are synced to files + when SyncBehavior is set to ON\_SPECIFIC\_SIZE + +**Note**: Not allowed is the combination of wildcards for LogAppName and +ContextName if EcuID is not specified. + +``` +[NON-VERBOSE-STORAGE-FILTER1] +EcuID=PASV +File=scc +FileSize=50000 +NOFiles=5 +[NON-VERBOSE-LOGLEVEL-CTRL1] +LogAppName=LOG +ContextName=TEST +LogLevel=DLT_LOG_DEBUG +EcuID=PASV +[NON-VERBOSE-LOGLEVEL-CTRL2] +LogAppName=.* +ContextName=.* +LogLevel=DLT_LOG_WARN +EcuID=PASV +``` + +In case of Non-Verbose Mode, two different configuration sections exist. +*[NON-VERBOSE-STORAGE-FILTER1]* describes where log messages of a Non-Verbose +passive Node (here: PASV) are stored. Furthermore, a configuration section to +control the log level of Non-Verbose applications exists. Either a log level for +a specific application/context can be defined (*[NON-VERBOSE=LOGLEVEL-CTRL1]*) +or the log level of all registered applications can be changed +(*[NON-VERBOSE=LOGLEVEL-CTRL2]*). + +### Offline Logstorage Control messages + +The DLT Daemon can be controlled with a standard set of control messages. To +control Offline Logstorage, the following control messages are added. + +- **DLT_SERVICE_ID_OFFLINE_LOGSTORAGE** + Send request to DLT Daemon to either enable or disable a Logstorage device + defined by its mount path. Conntection Types are: 0-Disconnect, 1-Connect, and + 2-Sync caches + - Parameter: + + ``` + typedef struct + { + uint32_t service_id; /**< service ID */ + char mount_point[DLT_MOUNT_PATH_MAX]; /**< storage device mount point */ + uint8_t connection_type; /**< connection status of the connected device connected/disconnected */ + char comid[DLT_ID_SIZE]; /**< communication interface */ + } DLT_PACKED DltServiceOfflineLogstorage; + ``` + +## Design + +It is not intended to describe the design of DLT itself before explaining the +DLT Offline Logstorage feature. Therefore it is necessary for the reader to have +good understanding of DLT's internal design to understand the design of DLT +Offline Logstorage. + +### Structural View + +![DLT Offline Logstorage inside DLT Daemon](images/logstorage/dlt_logstorage_structural.png "DLT Offline Logstorage inside DLT Daemon") + +DLT Daemon consists mainly of two parts: the LogProducer and a set of +LogConsumers. The LogProducer inside DLT acts as backend to libdlt.so which can +be seen as the implementation of the LogProducer frontend. Log messages are +filtered inside the LogProducer frontend based on the configured log level of +the context. The LogProducer backend inside DLT Daemon maintains tables of +connected applications and contexts to be able to send messages to the connected +DLT applications. This is used by DLT Offline Storage to change the log levels +of applications. A LogConsumer inside DLT Daemon forwards log messages to +connected DLT clients. When a DLT client connects to the Daemon, the DLT Daemon +opens the corresponding interface. In case of a connected DLT Viewer, a +TcpLogConsumer (socket connection over TCP/IP) or a SerialLogConsumer is used. +Each LogConsumer maintains its own ConsumerInfoTable. In case of DLT Offline +Logstorage, no external DLT Client is connected. Then DLT Daemon acts as DLT +Client by itself. This is done by implementing DLT Offline Logstorage as another +LogConsumer. For each LogConsumer (Storage Device) an +OfflineLogstorageConsumerInfoTable with following content is maintained: +- **Log storage file path**: Path to file system location for storing sets of + log files for that configuration. +- **File size**: The maximum size in bytes which each file in the set must reach + before a new file is created. +- **Total number of log files**: The total number of files to be created for the + set of files. If this number is reached, the first file is deleted and a new + file is created. +- **Log level**: The log level which a message needs to have to be stored +- **Application and Context Identifier**: Application and Context names to know + from which applications and contexts logs shall be stored. + +#### Application and context information + +The DLT Daemon maintains a list of applications and a list of contexts that are +running on the same ECU. To be able to set and reset log levels of applications +running on passive nodes, the (Gateway) DLT Daemon also has to store information +about applications and contexts running on passive nodes. This is currently not +possible. + +![Application and Context Information Handling](images/logstorage/dlt_logstorage_ap_ct_hdl.png "Application and Context Information Handling") + +The figure above depicts the updated handling of registered application and +context information. The Dlt Daemon will have a reference to a +DltDaemonApplicationList and DltDaemonContextList, instead of handling the data +itself (pointer to DltDaemonApplication, number of registered applications and +ECU identifier the registered users running on). Furthermore, the APIs to add, +delete, find, etc. applications are updated in a way that the dependency to +DltDaemon structure is removed. As a result, it is possible to instantiate the +application list multiple times (one time for each ECU in the system) without +changing the internal implementation of the list handling. + +### Dynamic View + +#### External components + +##### Interaction of Different Modules for Storing Log Messages + +##### Start Storing Log Messages + +![Interaction of different modules to start storing messages](images/logstorage/dlt_logstorage_start_str_msg.png "Interaction of different modules to start storing messages") + +The above diagram shows the interaction of different modules for triggering +storing of log messages in DLT. The user (tester in sequence diagram) inserts +the external device with a configuration file present in it. On plug-in of that +device, the udev Daemon mounts the device to specific DLT Offline Logstorage +location (/tmp/dltlogs/dltlogsdev\) and subsequently executes DLT +Logstorage Control Application with device number and connection status (in this +case *CONNECTED*) to trigger the DLT Daemon to start storing log messages to the +mounted device. The trigger is sent to the DLT Daemon from the DLT Logstorage +Control Application as a Service Request with the service ID of the +*DLT\_LOG\_STORAGE*. The DLT Daemon reads the configuration file from the device +and updates its OfflineLogstorageConsumerInfoTable entries. Then it calculates +the actual log level to be set at the DLT Application context by calculating the +union of log levels for that context from DLT Clients and all Log Storage +OfflineLogstorageConsumerInfoTables. This means, the lowest needed log level +will be set in the Application. E.g. there are two filter configuration set +storing the same log messages, but one of the configurations has DLT\_LOG\_FATAL, +the other DLT\_LOG\_WARN set. To ensure, that the second filter receives log +messages, DLT\_LOG\_WARN needs to be set in the application as log level. Next, +the DLT Daemon sends a DLT\_USER\_Command to all corresponding Applications to +update the log levels of their contexts. Upon receiving the set log level +command the DLT Application re-adjusts its log level and continues to log +messages with newly set log level. When Log messages are now received at the DLT +Daemon from DLT Applications, the DLT forwards the log messages to Offline +Logstorage and it filters the received messages based on the configuration in +its OfflineLogstorageConsumerInfoTable. Finally, the messages are written into +log files on the mounted device. + +##### Stop Storing of Log Messages + +![Interaction of different modules to stop storing log messages](images/logstorage/dlt_logstorage_stop_str_msg.png "Interaction of different modules to stop storing log messages") + +The above diagram shows the interaction of different modules to stop storing of +log messages in DLT using DLT Offline Logstorage feature. The user unplugs the +external device with a configuration file present in it. On unplug of such +device Udev Daemon executes the DLT Logstorage Control Application with device +number and connection status (in this case *DISCONNECTED*) to stop DLT Offline +Logstorage at DLT Daemon. The DLT Logstorage Control Application then sends a +Service Request to the DLT Daemon to trigger the DLT Daemon to stop logging to +the device to be unplugged. The DLT Daemon updates the +OfflineLogstorageConsumerInfoTable entries and also calculates a new log level +of all Application contexts which are affected by this change. Afterwards, the +DLT Daemon sends a command to all affected applications to update the log level +of their respective contexts. Upon receiving the set log level command, the DLT +application re-adjusts its log level and continues to log messages with newly +set log level. Finally, the device is un-mounted by the Udev Daemon. + +#### MultiNode handling + +##### Retrieve information about running application on passive node + +![Request application status](images/logstorage/dlt_logstorage_get_log_info.png "Request application status") + +The Gateway DLT Daemon needs actual information about current status of DLT +applications running on Passive Node. It might be that applications started or +stopped during system run time, so the GET\_LOG\_INFO request needs to be sent +periodically, because new applications/contexts might be registered in the +meanwhile. + +##### DLT Gateway Configuration + +To control the frequency of Passive Node control requests, another entry is +added to a Passive Node configuration. + +``` +[PassiveNode1] +... +; Send following control messages periodically () +SendPeriodicControl=0x03:5,0x05:10 +``` +By using *SendPeriodicControl* the user is able to control what control messages +shall be sent in a specific interval. If multiple control messages shall be sent +periodically, a comma separated list of commands can be specified. + +##### Store information about passive node applications + +Below diagram depicts update of registered applications and contexts of a +passive node DLT Daemon. Triggered by a GET\_LOG\_INFO request send by the +Gateway DLT Daemon, the passive node DLT Daemon sends a GET\_LOG\_INFO response. +The GET\_LOG\_INFO response does not contain any information about stopped +applications. Because of that, to avoid too much maintenance on Gateway DLT +Daemon, the passive node application and context list is cleared at first. While +parsing the GET\_LOG\_INFO response, applications and contexts are added to the +list again. As a result, the Gateway DLT Daemon always holds up-to-date +information about running DLT users on the passive node. + +![Internal update of passive node users](images/logstorage/dlt_logstorage_update_passive.png "Internal update of passive node users") + +##### Update Log Level of application running on Passive Node + +![Update log level](images/logstorage/dlt_logstorage_update_log_level.png "Update log level") + +Triggered by the DLT Logstorage Control application, the Gateway DLT Daemon +configures a new Logstorage device. When a Log Level change of a DLT Application +running on a passive node is requested, the Gateway DLT Daemon sends a control +request to the Passive DLT Daemon containing the information given in the DLT +Logstorage Configuration file. Finally, the request is forwarded to the actual +DLT Application that updates its Log Level. + +##### Store DLT Non-Verbose message in a DLT Logstorage device + +![Store DLT Non-Verbose message](images/logstorage/dlt_logstorage_str_non-verbose_msg.png "Store DLT Non-Verbose message") + +A DLT message is sent by a DLT Application running on a Passive Node to the +Passive DLT Daemon running on the same node. Because the Gateway DLT Daemon is +connected as DLT Client to the Passive DLT Daemon, the Passive DLT Daemon +forwards the log message to the Gateway DLT Daemon as usual. The Gateway DLT +Daemon itself filters the incoming DLT Non-Verbose message by ECU Identifier +(EcuID) and finally stores the message in a log file on the file system. + +#### Internal components + +![DLT Offline Logstorage -Sequence Diagram](images/logstorage/dlt_logstorage_sequence.png "DLT Offline Logstorage -Sequence Diagram") + +The above depicted sequence diagram shows the different stages involved in DLT +Offline Logstorage. The detailed design is explained through following sections +below. + +##### Configuring DLT and Setup Log Levels of Applications + +![DLT Offline Logstorage - Startup and Configure](images/logstorage/dlt_logstorage_startup_conf.png "DLT Offline Logstorage - Startup and Configure") + +This task involves reading of DLT Offline Logstorage configuration file and +updating the OfflineLogstorageConsumerInfoTable (context information table) with +configuration settings. The configuration files are located at preconfigured +locations or on external storage devices. The DLT Daemon reads the configuration +file from that location, adds entries into the +OfflineLogstorageConsumerInfoTable based on the settings provided in the +configuration file. As shown in the above sequence diagram the OfflineLogstorage +Consumer reads configuration (read\_configuration) from Storage Device and +updates the OfflineLogstorageConsumerInfoTable (add\_update\_table\_entry). +For each OfflineLogstorage Consumer (set of log files or device), an +OfflineLogstorageConsumerInfoTable is maintained. When a DLT application context +is registered, the LogProducer obtains the log level of individual application +context from each OfflineLogstorageConsumerInfoTable, makes a union of it and +sets this level as the log level for the context in the ContextTable. This log +level is in turn sent to the DLT application to ensure that the DLT application +sends all logs to OfflineLogstorage. Otherwise relevant log messages might be +filtered in DLT user library. OfflineLogstorage Consumer will obtain all the +stored configuration settings of each application context from +OfflineLogstorageConsumerInfoTable during logging of message from application. +This set log level will be used for filtering at the LogProducer (inside +libdlt.so). + +**Store filter configuration** + +This section describes more in detail what happens during +*add_update_table_entry()*. Internally, a hash table is set up using the +information from the parsed *dlt_logstorage.conf* file. This file contains +different kinds of data: +- Message information + - Application ID (LogAppName) + - Context ID (ContextName) + - Log level (LogLevel) + - Ecu ID (EcuID) +- Storage information + - Base file name (File) + - File size (FileSize) + - Number of files (NOFiles) + - Synchronization behavior (SyncBehavior) + +The basic idea is to describe a mapping between Message information (used as key +and filter criteria) and storage information (used as data). Furthermore, the +message information is used as filter criteria to decide if a certain message +has to be stored or not. + +##### Setup Application Context Log Level + +![Setup Application Context Log Level](images/logstorage/dlt_logstorage_setup_ap_ct_log_level.png "Setup Application Context Log Level") + +When an application using DLT is started, it registers itself at the DLT daemon. +Afterwards, it registers all its contexts. In case of enabled DLT Offline +Logstorage, the DLT Daemon checks if an entry of the registered Application in +one or multiple of the OfflineLogstorageConsumerInfoTables exits. If one or more +entries for the context are found, a union of all configured log levels is +created. This means, the DLT Daemon chooses the lowest configured log level. +Finally the DLT Daemon updates the log level of the registered context to this +log level by calling *set_user_log_level()*. This ensures that logs of a +configured log level are not filtered within the LogProducer (libdlt.so) and +forwarded to the OfflineLogstorage Consumer. + +##### Storing Log Messages to Devices + +![Store Log Information](images/logstorage/dlt_logstorage_str_msg.png "Store Log Information") + +Storing of log messages to devices involves following tasks: +- **Filtering of Log Information**: When DLT applications log information, the + log information is filtered at the LogProducer (inside libdlt.so) based on the + log level the application is configured to use. This is then forwarded by the + LogProducer (receiver inside DLT Daemon) to the OfflineLogstorage Consumer. On + receiving the log information, the OfflineLogstorage Consumer gets the + configured, application name, context name and log level from its + OfflineLogstorageConsumerInfoTable and filters the log information before + storing into the sets of files on the Storage Device. If the configured log + level obtained from OfflineLogstorageConsumerInfoTable is lesser than the log + level of message and application or context name are not present in the + OfflineLogstorageConsumerInfoTable, the OfflineLogstorage Consumer discards + the log message. *Note*: In case multiple devices, the OfflineLogstorage + Consumer obtains the log level from all OfflineLogstorageConsumerInfoTables. + More details on the implementation can be obtained below. +- **Storing Log Information**: After filtering the relevant log messages, the + OfflineLogstorage Consumer will store the log message in a file on the Storage + Device. + +**Filtering of incoming log messages** + +To filter a log message based on information given in the filter configuration, +a linked list is used. A member *key_list* consists of a combination of +application ID and context ID. Since DLT Offline Logstorage supports wildcards +and lists of IDs, the following cases have to be considered: + +If Ecu Identifier is not specified, Filter configuration contains +1. One application ID (App1) and one context ID (Ctx1): Key = ":App1:Ctx1" +2. One application ID (App1), wildcard for context ID: Key = ":App1:" +3. Wildcard of application ID, One context ID (Ctx1): Key = "::Ctx1" +4. Wildcard of application ID, list of context IDs (Ctx1,Ctx2): Keys="Ctx1"," + Ctx2" and the other way around +5. List of application (App1, App2) and context IDs (Ctx1, Ctx2): all + combinations of application ID and context ID are possible. + Keys = ":App1:Ctx1", ":App1:Ctx2", ":App2:Ctx1", ":App2,Ctx2" +6. Both application ID and context ID is not allowed to be set to wildcard. + +Data of a key value pair contains of all information given in +OfflineLogstorageConsumerInfoTable - apart from application ID and context ID. +When a message arrives at the filter, three checks have to be done. It has to be +checked if: +1. The combination of application and context ID is a valid key +2. The application ID is a valid key +3. The context ID is a valid key + +If one or more keys are valid the message is stored in the file of the +corresponding filter. If not, the incoming message will be ignored. In case of a +configured Ecu Identifier (ECU1), the following Keys are generated: +1. One application ID (App1) and one context ID (Ctx1): Key = "ECU1:App1:Ctx1" +2. One application ID (App1), wildcard for context ID: Key = "ECU1:App1:" +3. Wildcard of application ID, One context ID (Ctx1): Key = "ECU1::Ctx1" +4. Wildcard of application ID, list of context IDs (Ctx1,Ctx2): + Keys=" ECU1::Ctx1"," ECU1::Ctx2" and the other way around +5. List of application (App1, App2) and context IDs (Ctx1, Ctx2): all + combinations of application ID and context ID are possible. + Keys = "ECU1:App1:Ctx1", "ECU1:App1:Ctx2", "ECU1:App2:Ctx1", "ECU1:App2:Ctx2" +6. If application ID and context ID is set to wildcard, the following key is + generated: "ECU1::" +7. If application ID and context ID is not present in configuration file, + the following key is generated: "ECU1::" + +The diagram below shows the steps to be done to find files to store an incoming log message. + +![Steps Log Message Filtering](images/logstorage/dlt_logstorage_msg_filter.png "Steps Log Message Filtering") + +When an incoming message is received, it needs to be checked first if the +message is sent in Verbose or Non-Verbose mode. Depending on the mode, different +keys are created to search for valid filter configurations. In case of +Non-Verbose mode, only the following key can be created; "EcuID::", because a +Non-Verbose message usually does not contain any information about Application +and Context ID. In case of Verbose mode, all valid combinations of EcuID, +Application ID and Context ID are generated. The generated keys are used as +input to find valid configuration that contain information about log level, file +location etc. Using the filter information found in the configuration, the log +message gets stored in a file. + +### DLT Offline Logstorage Cache + +Usually, the DLT Offline Logstorage is used to store log information on an +attached external device as described above. Another use case is to store logs +to an internal storage device as described in Use Case View. In this case, +writing every log message to the storage device must be avoided since FLASH +storage devices have a limited number of write cycles. Therefore, the log +messages have to be buffered and synced to disk based on a certain strategy. + +The following strategies exist: +1. **Write every log message (ON_MSG)**: Each log message is persistently + written to the storage device. +2. **Write on close (ON_DAEMON_EXIT)**: Write data to disk before the DLT Daemon + is stopped. +3. **Write on demand (ON_DEMAND)**: Write data on disk whenever the write is + triggered from an external application. +4. **Write on file size reached (ON_FILE_SIZE)**: The log file size for a + specific filter is specified in the DLT Logstorage configuration file. A + memory region with the same size will be allocated and filled with data. + Whenever the buffer is filled with data, this data is written into a log file. +5. **Write after specific size (ON_SPECIFIC_SIZE)**: This is basically the same + as (4), but writes data into a log file after a the incoming data size reached + the specified "write after" data size. +6. **A combination of the above scenarios**: Combinations with ON\_MSG or + combination of ON\_FILE\_SIZE and ON\_SPECIFIC\_SIZE are not allowed. + +Write every log message is the standard DLT Offline Logstorage strategy which +has been discussed in detail above. All other strategies base on having a log +message cache available. + +#### Write on close strategy + +In this scenario, all log messages are stored in a ring buffer with the size +specified in *FileSize*. When the DLT Daemon is terminated, all logs that belong +to filter configurations having the *ON_DAEMON_EXIT* sync strategy enabled are +synced to disk. This is shown in diagram below. The daemon receives a +termination signal which is handled in the installed signal handler. The main +event loop is stopped and the DLT Daemon cleans up all internal data structures. +It calls the *logstorage_cleanup()* function which itself cleans up all active +Logstorage devices. In this stage, every filter configurations configured with +the *ON_DAEMON_EXIT* flag will sync its cached log messages to disk in a new +log file. + +![Sync on daemon exit](images/logstorage/dlt_logstorage_sync_on_daemon_exit.png "Sync on daemon exit") + +#### Write on demand strategy + +In this scenario, all log messages are stored in a ring buffer with the size +specified in *FileSize*. When the DLT Logstorage Control Application sends a +trigger, all logs that belong to filter configurations having the *ON\_DEMAND* +sync strategy enabled are synced to disk. This is shown in diagram below. The +DLT Logstorage Control Application will send a DLT Daemon control command that +is forwarded by the DLT Daemon to the Offline Logstorage. Two different exist: +If the command is sent without a mount point as parameter, all Logstorage caches +configured with the on demand sync strategy are synced to disk. If the command +is sent with a mount point, only the Logstorage caches of the corresponding +Logstorage device are synced to disk. In case the mount point is not valid, the +DLT Daemon returns an error response to the DLT Logstorage Control application. + +![Sync on demand](images/logstorage/dlt_logstorage_sync_on_demand.png "Sync on demand") + +#### Offline Logstorage Ring buffer cache + +Every Offline Logstorage filter configuration will have its own buffer with a +specific size. If the buffer is full and the content was not synced to disk +before, older log messages will be overwritten from the beginning as shown in +diagram below. + +![DLT Offline Logstorage Ring buffer](images/logstorage/dlt_logstorage_ring_buffer.png "DLT Offline Logstorage Ring buffer") + +#### Strategy initialization + +The user can specify which strategies he wants to add to a filter configuration. +Here it must be ensured that *ON_MSG* cannot be combined with any strategy +based on a Logstorage cache. + +For each filter configuration, depend on the value `File`, a list of newest file +which is keeping the data of newest file name and wrap-around id for corresponding +`File`. + +``` +struct DltNewestFileName +{ + char *file_name; /* The unique name of file in whole a dlt_logstorage.conf */ + char *newest_file; /* The real newest name of file which is associated with filename.*/ + unsigned int wrap_id; /* Identifier of wrap around happened for this file_name */ + DltNewestFileName *next; /* Pointer to next */ +}; +``` + +#### Storage preparation based on strategy + +For each Logstorage configuration, the storage preparation step is executed +once. + +In case of *ON\_MSG" strategy, the file on the storage device is created. +The newest file info must be updated to the working file info after preparation. + + +In case of cache based strategies, the file on the storage device is created and +the Logstorage cache (ring buffer) is initialized. + +Following diagram shows the +difference between caching strategy initialization and non-caching *ON_MSG* +strategy. + +![Storage preparation](images/logstorage/dlt_logstorage_preparation.png "Storage preparation") + +#### Storing log messages based on strategy + +The default behavior of Offline Logstorage writes every log message directly +into a file (*ON_MSG*). In case of caching strategies, the log message is +stored into a ring buffer (refer +[Offline Logstorage Ring buffer cache](#Offline-Logstorage-Ring-buffer-cache)). +Following diagram shows the difference between caching strategy initialization +and non-caching *ON_MSG* strategy. + +![Write log message](images/logstorage/dlt_logstorage_wrt_msg.png "Write log message") + +#### Synchronization based on strategy + +The default behavior of Offline Logstorage syncs the file directly after a log +message is written into the file (*ON_MSG*). Before synchronization to file, +the working log file is compared against the log files to ensure that +the log data is written to the newest file. If they are different each other, +the working log file is closed and try to open the newest one for writing. +fsync() is called before fclose() instead of on every message because invoking +it per message basis has too much impact on performance. + +In case of other log strategies, +the ring buffer is synced to a file depending on the configured sync strategies. +The sync function is called from different places in the Logstorage code. +Therefore, the current situation has to be given as parameter. If the filter +configuration is configured with a specific strategy the ring buffer will be +flushed to a file. If the certain strategy is not configured, the function +returns without actually syncing the ring buffer. The action of update log files +is always performed to ensure that the newest file is used to synchronize the data in ring buffer. +The newest file info must be updated to the working file info after sync. + +![Sync messages](images/logstorage/dlt_logstorage_sync_msg.png "Sync messages") + +Syncing the ring buffer includes additional internal steps as shown in diagram +below. + +![Sync ring buffer](images/logstorage/dlt_logstorage_sync_ring_buffer.png "Sync ring buffer") + +## Security + +The current implementation of DLT Offline Logstorage raises the following +security related problems. +1. DLT Offline Logstorage is designed in a way that it is enough to attach an + external storage device to the target containing a valid configuration file to + receive logs from applications. If corresponding udev rules are installed on + the target the storing of log messages starts immediately. Another possibility + to start storing of log messages is to send a trigger through + *dlt-logstorage-ctrl* application to the DLT Daemon. +2. Furthermore, DLT Offline Logstorage chances the configured log level of + applications, which is needed to fulfill its requirements, but generates + security problems. It in a real production system, it may be not allowed to + receive INFO or VERBOSE messages, but the current implementation does not have + any possibility to avoid certain log levels. + +## Known Limitations + +No. | Description +----- | ---- +1 | A combination of wildcards for Application ID ***and*** Context ID is only possible when EcuID is specified. diff --git a/doc/dlt_offline_logstorage.md b/doc/dlt_offline_logstorage.md index 91ef75b99..5c7a9d4a1 100644 --- a/doc/dlt_offline_logstorage.md +++ b/doc/dlt_offline_logstorage.md @@ -53,6 +53,9 @@ options exist: # Wrap around value for log file count in file name (Default: UINT_MAX) # OfflineLogstorageMaxCounter = 999 +# Don't append counter for NOFiles=1 (Default: 0) +# OfflineLogstorageOptionalIndex = 1 + # Maximal used memory for Logstorage Cache in KB (Default: 30000 KB) # OfflineLogstorageCacheSize = 30000 ``` @@ -71,14 +74,16 @@ LogLevel= # Define log level, e.g. DLT_LOG_INFO or DL 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. +SyncBehavior= # Specify sync strategy. Default: Sync'ed after every message. See Logstorage Ringbuffer Implementation below. EcuID= # Specify ECU identifier SpecificSize= # Store logs in storage devices after specific size is reached. GzipCompression= # Write the logfiles with gzip compression. +OverwriteBehavior= # Specify overwrite strategy. Default: Delete oldest file and continue. See Logstorage Ringbuffer Implementation below. +DisableNetwork= # Specify if the message shall be routed to network client. ``` -The Parameter "SyncBehavior","EcuID" and "SpecificSize" are optional - all -others are mandatory. +The Parameter "SyncBehavior", "OverwriteBehavior", "DisableNetwork", "EcuID" and +"SpecificSize" are optional - all others are mandatory. If both of the parameter "LogAppName" and "ContextName" are set to wildcard or not present in the configuration file, "EcuID" must be specified. @@ -115,6 +120,18 @@ FileSize=250000 NOFiles=5 SyncBehavior=ON_FILE_SIZE,ON_DEMAND EcuID=ECU1 + +[FILTER4] +LogAppName=APP2 +ContextName=.* +LogLevel=DLT_LOG_INFO +File=App2 +FileSize=10000 +NOFiles=5 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW +DisableNetwork=ON ``` In case of Non-Verbose mode, following filters should be used. @@ -245,6 +262,9 @@ The following procedure can be used to test Offline Logstorage: - To check the content of the file open it with dlt-convert or DLT Viewer. +Example sequence can be found under `tests/component/logstorage_one_file` +and `tests/component/logstorage_multi_file`. + ## Logstorage Ring Buffer Implementation The DLT Logstorage is mainly used to store a configurable set of logs on an @@ -277,6 +297,23 @@ Note : 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. 3. In case multiple FILTERs use the same `File` value, it is recommened that the following settings must also have same values: `NOFiles`, `FileSize` and `SpecificSize` +### OverwriteBehavior - What should be discarded? + +The ring buffer behaviour can be modified for specific filters by changing the +OverwriteBehavior. + +The following strategies are implemented: +- DISCARD\_OLD - remove the oldest file before creating a new one(Default) +- DISCARD\_NEW - stop writing and discard all new messages + +### Disable network routing - What should be forwarded? + +Routing to network client (e.g. DLT Viewer) can be changed by the DisableNetwork. + +The following flags are implemented: +- OFF - Forward log messages to network client (Default) +- ON - Do not forward log messages to network client and only log to file + ## Maintain Logstorage Log Level Implementation The log level setting of each user context in the logstorage FILTER will be diff --git a/src/console/dlt-control-common.c b/src/console/dlt-control-common.c index dcdc96eda..d200de49c 100644 --- a/src/console/dlt-control-common.c +++ b/src/console/dlt-control-common.c @@ -141,6 +141,18 @@ void set_ecuid(char *ecuid) } } +void set_conf(char *file_path) +{ + if (file_path != NULL) { + memset(local_filename, 0, DLT_MOUNT_PATH_MAX); + strncpy(local_filename, file_path, DLT_MOUNT_PATH_MAX); + local_filename[DLT_MOUNT_PATH_MAX - 1] = '\0'; + } + else { + pr_error("Argument is NULL\n"); + } +} + int get_timeout(void) { return local_timeout; diff --git a/src/console/dlt-control-common.h b/src/console/dlt-control-common.h index fb1a67556..537faa4fb 100644 --- a/src/console/dlt-control-common.h +++ b/src/console/dlt-control-common.h @@ -73,6 +73,8 @@ void set_verbosity(int); char *get_ecuid(void); void set_ecuid(char *); +void set_conf(char *); + int get_timeout(void); void set_timeout(int); diff --git a/src/console/logstorage/dlt-logstorage-ctrl.c b/src/console/logstorage/dlt-logstorage-ctrl.c index 44f05f15b..87b29e9ba 100644 --- a/src/console/logstorage/dlt-logstorage-ctrl.c +++ b/src/console/logstorage/dlt-logstorage-ctrl.c @@ -409,6 +409,8 @@ static void usage(void) printf(" -S --send-header Send message with serial header (Default: Without serial header)\n"); printf(" -R --resync-header Enable resync serial header\n"); printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity()); + printf(" -C filename DLT daemon configuration file (Default: " CONFIGURATION_FILES_DIR + "/dlt.conf)\n"); } static struct option long_options[] = { @@ -441,7 +443,7 @@ static int parse_args(int argc, char *argv[]) while ((c = getopt_long(argc, argv, - ":s::t:hSRe:p:d::c:v", + ":s::t:hSRe:p:d::c:vC:", long_options, &long_index)) != -1) switch (c) { @@ -495,6 +497,10 @@ static int parse_args(int argc, char *argv[]) set_verbosity(1); pr_verbose("Now in verbose mode.\n"); break; + case 'C': + set_conf(optarg); + pr_verbose("Set %s to read options\n", optarg); + break; case ':': pr_error("Option -%c requires an argument.\n", optopt); usage(); @@ -521,6 +527,10 @@ static int parse_args(int argc, char *argv[]) return -1; } + /* Retrieve ECUID from dlt.conf */ + if (get_ecuid() == NULL) + set_ecuid(NULL); + return 0; } @@ -547,7 +557,6 @@ int main(int argc, char *argv[]) { int ret = 0; - set_ecuid(NULL); set_timeout(DLT_CTRL_TIMEOUT); set_send_serial_header(0); set_resync_serial_header(0); diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c index e0dce59bc..aee392504 100644 --- a/src/daemon/dlt-daemon.c +++ b/src/daemon/dlt-daemon.c @@ -396,6 +396,7 @@ int option_file_parser(DltDaemonLocal *daemon_local) daemon_local->flags.offlineLogstorageDelimiter = '_'; daemon_local->flags.offlineLogstorageMaxCounter = UINT_MAX; daemon_local->flags.offlineLogstorageMaxCounterIdx = 0; + daemon_local->flags.offlineLogstorageOptionalCounter = false; daemon_local->flags.offlineLogstorageCacheSize = 30000; /* 30MB */ dlt_daemon_logstorage_set_logstorage_cache_size( daemon_local->flags.offlineLogstorageCacheSize); @@ -662,6 +663,8 @@ int option_file_parser(DltDaemonLocal *daemon_local) { daemon_local->flags.offlineLogstorageMaxCounter = (unsigned int) atoi(value); daemon_local->flags.offlineLogstorageMaxCounterIdx = (unsigned int) strlen(value); + } else if (strcmp(token, "OfflineLogstorageOptionalIndex") == 0) { + daemon_local->flags.offlineLogstorageOptionalCounter = atoi(value); } else if (strcmp(token, "OfflineLogstorageCacheSize") == 0) { diff --git a/src/daemon/dlt-daemon.h b/src/daemon/dlt-daemon.h index d3bb9785e..d4962244b 100644 --- a/src/daemon/dlt-daemon.h +++ b/src/daemon/dlt-daemon.h @@ -123,7 +123,8 @@ typedef struct char offlineLogstorageDelimiter; /**< (char) Append delimeter character in offline logstorage filename */ unsigned int offlineLogstorageMaxCounter; /**< (int) Maximum offline logstorage file counter index until wraparound */ unsigned int offlineLogstorageMaxCounterIdx; /**< (int) String len of offlineLogstorageMaxCounter*/ - unsigned int offlineLogstorageCacheSize; /**< Max cache size offline logstorage cache */ + unsigned int offlineLogstorageCacheSize; /**< (int) Max cache size offline logstorage cache */ + int offlineLogstorageOptionalCounter; /**< (Boolean) Do not append index to filename if NOFiles=1 */ #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC char appSockPath[DLT_DAEMON_FLAG_MAX]; /**< Path to User socket */ #else /* DLT_DAEMON_USE_FIFO_IPC */ diff --git a/src/daemon/dlt.conf b/src/daemon/dlt.conf index 11a5057fb..6035de30e 100644 --- a/src/daemon/dlt.conf +++ b/src/daemon/dlt.conf @@ -199,6 +199,9 @@ ControlSocketPath = /tmp/dlt-ctrl.sock # Wrap around value for log file count in file name (Default: UINT_MAX) # OfflineLogstorageMaxCounter = 999 +# Don't append counter for NOFiles=1 (Default: 0) +# OfflineLogstorageOptionalIndex = 1 + # Maximal used memory for Logstorage Cache in KB (Default: 30000 KB) # OfflineLogstorageCacheSize = 30000 diff --git a/src/daemon/dlt_daemon_client.c b/src/daemon/dlt_daemon_client.c index 11655a288..c40b39768 100644 --- a/src/daemon/dlt_daemon_client.c +++ b/src/daemon/dlt_daemon_client.c @@ -172,6 +172,7 @@ int dlt_daemon_client_send(int sock, int verbose) { int sent, ret; + int ret_logstorage = 0; static int sent_message_overflow_cnt = 0; if ((daemon == NULL) || (daemon_local == NULL)) { @@ -224,40 +225,47 @@ int dlt_daemon_client_send(int sock, * this need to be checked because the function is dlt_daemon_client_send is called by * newly introduced dlt_daemon_log_internal */ if (daemon_local->flags.offlineLogstorageMaxDevices > 0) - dlt_daemon_logstorage_write(daemon, - &daemon_local->flags, - storage_header, - storage_header_size, - data1, - size1, - data2, - size2); + ret_logstorage = dlt_daemon_logstorage_write(daemon, + &daemon_local->flags, + storage_header, + storage_header_size, + data1, + size1, + data2, + size2); } /* send messages to daemon socket */ if ((daemon->mode == DLT_USER_MODE_EXTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) { #ifdef UDP_CONNECTION_SUPPORT - - if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) - dlt_daemon_udp_dltmsg_multicast(data1, - size1, - data2, - size2, - verbose); + if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) { + /* Forward message to network client if network routing is not disabled */ + if (ret_logstorage != 1) { + dlt_daemon_udp_dltmsg_multicast(data1, + size1, + data2, + size2, + verbose); + } + } #endif if ((sock == DLT_DAEMON_SEND_FORCE) || (daemon->state == DLT_DAEMON_STATE_SEND_DIRECT)) { - sent = dlt_daemon_client_send_all_multiple(daemon, - daemon_local, - data1, - size1, - data2, - size2, - verbose); + /* Forward message to network client if network routing is not disabled */ + if (ret_logstorage != 1) { + sent = dlt_daemon_client_send_all_multiple(daemon, + daemon_local, + data1, + size1, + data2, + size2, + verbose); - if ((sock == DLT_DAEMON_SEND_FORCE) && !sent) - return DLT_DAEMON_ERROR_SEND_FAILED; + if ((sock == DLT_DAEMON_SEND_FORCE) && !sent) { + return DLT_DAEMON_ERROR_SEND_FAILED; + } + } } } diff --git a/src/daemon/dlt_daemon_common.c b/src/daemon/dlt_daemon_common.c index 7820d1fa0..aaed15143 100644 --- a/src/daemon/dlt_daemon_common.c +++ b/src/daemon/dlt_daemon_common.c @@ -972,10 +972,10 @@ DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon, } context = &(user_list->contexts[user_list->num_contexts - 1]); + memset(context, 0, sizeof(DltDaemonContext)); dlt_set_id(context->apid, apid); dlt_set_id(context->ctid, ctid); - context->context_description = NULL; application->num_contexts++; new_context = 1; diff --git a/src/daemon/dlt_daemon_offline_logstorage.c b/src/daemon/dlt_daemon_offline_logstorage.c index 23750154e..d1a98efb6 100644 --- a/src/daemon/dlt_daemon_offline_logstorage.c +++ b/src/daemon/dlt_daemon_offline_logstorage.c @@ -1009,8 +1009,9 @@ int dlt_daemon_logstorage_get_loglevel(DltDaemon *daemon, * @param size2 message extended header size * @param data3 message data buffer * @param size3 message data size + * @return 0 on success, -1 on error, 1 on disable network routing */ -void dlt_daemon_logstorage_write(DltDaemon *daemon, +int dlt_daemon_logstorage_write(DltDaemon *daemon, DltDaemonFlags *user_config, unsigned char *data1, int size1, @@ -1020,6 +1021,7 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, int size3) { int i = 0; + int ret = 0; DltLogStorageUserConfig file_config; if ((daemon == NULL) || (user_config == NULL) || @@ -1028,7 +1030,7 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, dlt_vlog(LOG_DEBUG, "%s: message type is not LOG. Skip storing.\n", __func__); - return; + return -1; /* Log Level changed callback */ } @@ -1036,30 +1038,45 @@ void dlt_daemon_logstorage_write(DltDaemon *daemon, file_config.logfile_timestamp = user_config->offlineLogstorageTimestamp; file_config.logfile_delimiter = user_config->offlineLogstorageDelimiter; file_config.logfile_maxcounter = user_config->offlineLogstorageMaxCounter; + file_config.logfile_optional_counter = user_config->offlineLogstorageOptionalCounter; file_config.logfile_counteridxlen = user_config->offlineLogstorageMaxCounterIdx; - for (i = 0; i < user_config->offlineLogstorageMaxDevices; i++) + for (i = 0; i < user_config->offlineLogstorageMaxDevices; i++) { if (daemon->storage_handle[i].config_status == DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE) { - if (dlt_logstorage_write(&(daemon->storage_handle[i]), + int disable_nw = 0; + if ((ret = dlt_logstorage_write(&(daemon->storage_handle[i]), &file_config, data1, size1, data2, size2, data3, - size3) != 0) { + size3, + &disable_nw)) < 0) { dlt_log(LOG_ERR, "dlt_daemon_logstorage_write: failed. " "Disable storage device\n"); - /* DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS happened, + /* DLT_OFFLINE_LOGSTORAGE_MAX_ERRORS happened, * therefore remove logstorage device */ dlt_logstorage_device_disconnected( &(daemon->storage_handle[i]), DLT_LOGSTORAGE_SYNC_ON_DEVICE_DISCONNECT); } + if (i == 0) { + if (disable_nw == 1) { + ret = 1; + } + } else { + dlt_vlog(LOG_WARNING, + "%s: DisableNetwork is not supported for more than one device yet\n", + __func__); + } } + } + + return ret; } /** @@ -1143,6 +1160,8 @@ int dlt_daemon_logstorage_cleanup(DltDaemon *daemon, daemon_local->flags.offlineLogstorageMaxCounter; (&daemon->storage_handle[i])->uconfig.logfile_timestamp = daemon_local->flags.offlineLogstorageTimestamp; + (&daemon->storage_handle[i])->uconfig.logfile_optional_counter = + daemon_local->flags.offlineLogstorageOptionalCounter; dlt_logstorage_device_disconnected( &daemon->storage_handle[i], @@ -1183,6 +1202,8 @@ int dlt_daemon_logstorage_sync_cache(DltDaemon *daemon, daemon_local->flags.offlineLogstorageMaxCounter; handle->uconfig.logfile_timestamp = daemon_local->flags.offlineLogstorageTimestamp; + handle->uconfig.logfile_optional_counter = + daemon_local->flags.offlineLogstorageOptionalCounter; if (dlt_logstorage_sync_caches(handle) != 0) return DLT_RETURN_ERROR; @@ -1201,6 +1222,8 @@ int dlt_daemon_logstorage_sync_cache(DltDaemon *daemon, daemon_local->flags.offlineLogstorageMaxCounter; daemon->storage_handle[i].uconfig.logfile_timestamp = daemon_local->flags.offlineLogstorageTimestamp; + daemon->storage_handle[i].uconfig.logfile_optional_counter = + daemon_local->flags.offlineLogstorageOptionalCounter; if (dlt_logstorage_sync_caches(&daemon->storage_handle[i]) != 0) return DLT_RETURN_ERROR; diff --git a/src/daemon/dlt_daemon_offline_logstorage.h b/src/daemon/dlt_daemon_offline_logstorage.h index 3ff4116e3..9d55a3768 100644 --- a/src/daemon/dlt_daemon_offline_logstorage.h +++ b/src/daemon/dlt_daemon_offline_logstorage.h @@ -130,8 +130,9 @@ void dlt_daemon_logstorage_update_application_loglevel(DltDaemon *daemon, * @param size2 message extended data size * @param data3 message data buffer * @param size3 message data size + * @return 0 on success, -1 on error, 1 on disable network routing */ -void dlt_daemon_logstorage_write(DltDaemon *daemon, +int dlt_daemon_logstorage_write(DltDaemon *daemon, DltDaemonFlags *user_config, unsigned char *data1, int size1, diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index c2b99191c..a9db723b3 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -61,10 +61,12 @@ if(WITH_LEGACY_INCLUDE_PATH) ) endif() -if(WITH_LIB_SHORT_VERSION) - set_target_properties(dlt PROPERTIES VERSION ${PROJECT_VERSION_MAJOR} SOVERSION ${PROJECT_VERSION_MAJOR}) -else() - set_target_properties(dlt PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) +if(NOT WITH_LIB_NO_VERSION) + if(WITH_LIB_SHORT_VERSION) + set_target_properties(dlt PROPERTIES VERSION ${PROJECT_VERSION_MAJOR} SOVERSION ${PROJECT_VERSION_MAJOR}) + else() + set_target_properties(dlt PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) + endif() endif() add_library(Genivi::dlt ALIAS dlt) diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c index ec4555f57..f435a12ea 100644 --- a/src/lib/dlt_user.c +++ b/src/lib/dlt_user.c @@ -4034,7 +4034,7 @@ DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype) /* Get file size */ struct stat st; fstat(dlt_user.dlt_log_handle, &st); - dlt_vlog(LOG_DEBUG, "%s: Current file size=[%jd]\n", __func__, + dlt_vlog(LOG_DEBUG, "%s: Current file size=[%ld]\n", __func__, st.st_size); /* Check filesize */ @@ -4044,7 +4044,7 @@ DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype) if (msg_size > dlt_user.filesize_max) { dlt_user_file_reach_max = true; dlt_vlog(LOG_ERR, - "%s: File size (%jd bytes) reached to defined maximum size (%d bytes)\n", + "%s: File size (%ld bytes) reached to defined maximum size (%d bytes)\n", __func__, st.st_size, dlt_user.filesize_max); return DLT_RETURN_FILESZERR; } diff --git a/src/offlinelogstorage/dlt_offline_logstorage.c b/src/offlinelogstorage/dlt_offline_logstorage.c index bddd96853..1d8fa8627 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage.c +++ b/src/offlinelogstorage/dlt_offline_logstorage.c @@ -329,7 +329,7 @@ void dlt_logstorage_free(DltLogStorage *handle, int reason) * @param value string given in config file * @return 0 on success, -1 on error */ -DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value) +DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, const char *value) { int i = 0; int y = 0; @@ -337,8 +337,10 @@ DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value) char *tok; int num = 1; - if ((names == NULL) || (value == NULL)) + if ((names == NULL) || (value == NULL)) { + dlt_vlog(LOG_ERR, "%s: Arguments are set to NULL\n", __func__); return -1; + } /* free, alloce'd memory to store new apid/ctid */ if (*names != NULL) { @@ -348,8 +350,11 @@ DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value) len = strlen(value); - if (len == 0) + if (len == 0) { + dlt_vlog(LOG_ERR, "%s: Length of string given in config file is 0\n", + __func__); return -1; + } /* count number of delimiters to get actual number off names */ num = dlt_logstorage_count_ids(value); @@ -357,10 +362,13 @@ DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value) /* need to alloc space for 5 chars, 4 for the name and "," and "\0" */ *names = (char *)calloc(num * 5, sizeof(char)); - if (*names == NULL) + if (*names == NULL) { + dlt_vlog(LOG_ERR, "%s: Cannot allocate memory\n", __func__); return -1; + } - tok = strtok(value, ","); + tok = strdup(value); + tok = strtok(tok, ","); i = 1; @@ -379,6 +387,20 @@ DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value) tok = strtok(NULL, ","); } + free(tok); + + return 0; +} + +DLT_STATIC int dlt_logstorage_set_number(unsigned int *number, unsigned int value) +{ + if ((value == 0) || (value > UINT_MAX)) { + dlt_log(LOG_ERR, "Invalid, is not a number \n"); + return -1; + } + + *number = value; + return 0; } @@ -416,14 +438,7 @@ DLT_STATIC int dlt_logstorage_read_number(unsigned int *number, char *value) size = strtoul(value, NULL, 10); - if ((size == 0) || (size > UINT_MAX)) { - dlt_log(LOG_ERR, "Invalid, is not a number \n"); - return -1; - } - - *number = (unsigned int)size; - - return 0; + return dlt_logstorage_set_number(number, size); } /** @@ -939,12 +954,26 @@ DLT_STATIC int dlt_logstorage_check_ctids(DltLogStorageFilterConfig *config, if ((config == NULL) || (value == NULL)) return -1; - return dlt_logstorage_read_list_of_names(&config->ctids, value); + return dlt_logstorage_read_list_of_names(&config->ctids, (const char*)value); +} + +DLT_STATIC int dlt_logstorage_set_loglevel(int *log_level, + int value) +{ + *log_level = value; + if ((value <= DLT_LOG_DEFAULT) || (value >= DLT_LOG_MAX)) { + *log_level = -1; + dlt_log(LOG_ERR, "Invalid log level \n"); + return -1; + } + return 0; } DLT_STATIC int dlt_logstorage_check_loglevel(DltLogStorageFilterConfig *config, char *value) { + int ll = -1; + if ((config == NULL) || (value == NULL)) return -1; @@ -954,35 +983,30 @@ DLT_STATIC int dlt_logstorage_check_loglevel(DltLogStorageFilterConfig *config, } if (strcmp(value, "DLT_LOG_FATAL") == 0) { - config->log_level = 1; + ll = 1; } else if (strcmp(value, "DLT_LOG_ERROR") == 0) { - config->log_level = 2; + ll = 2; } else if (strcmp(value, "DLT_LOG_WARN") == 0) { - config->log_level = 3; + ll = 3; } else if (strcmp(value, "DLT_LOG_INFO") == 0) { - config->log_level = 4; + ll = 4; } else if (strcmp(value, "DLT_LOG_DEBUG") == 0) { - config->log_level = 5; + ll = 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; + ll = 6; } - return 0; + return dlt_logstorage_set_loglevel(&config->log_level, ll); } DLT_STATIC int dlt_logstorage_check_reset_loglevel(DltLogStorageFilterConfig *config, @@ -1037,8 +1061,10 @@ DLT_STATIC int dlt_logstorage_check_filename(DltLogStorageFilterConfig *config, { int len; - if ((value == NULL) || (strcmp(value, "") == 0)) + if ((value == NULL) || (strcmp(value, "") == 0)) { + dlt_vlog(LOG_ERR, "%s: Arguments are set to NULL\n", __func__); return -1; + } if (config->file_name != NULL) { free(config->file_name); @@ -1047,6 +1073,12 @@ DLT_STATIC int dlt_logstorage_check_filename(DltLogStorageFilterConfig *config, len = strlen(value); + if (len == 0) { + dlt_vlog(LOG_ERR, "%s: Length of string given in config file is 0\n", + __func__); + return -1; + } + /* 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)); @@ -1109,6 +1141,22 @@ DLT_STATIC int dlt_logstorage_check_specificsize(DltLogStorageFilterConfig *conf return dlt_logstorage_read_number(&config->specific_size, value); } +DLT_STATIC int dlt_logstorage_set_sync_strategy(int *sync, + int value) +{ + *sync = value; + + if (value == 0) + { + dlt_log(LOG_WARNING, + "Unknown sync strategies. Set default ON_MSG\n"); + *sync = DLT_LOGSTORAGE_SYNC_ON_MSG; + return 1; + } + + return 0; +} + /** * dlt_logstorage_check_sync_strategy * @@ -1159,6 +1207,70 @@ DLT_STATIC int dlt_logstorage_check_sync_strategy(DltLogStorageFilterConfig *con return 0; } +/** + * dlt_logstorage_check_overwrite_strategy + * + * Evaluate overwrite strategy. The sync strategy is an optional filter + * configuration parameter. + * If the given value cannot be associated with a strategy, the default + * strategy will be assigned. + * + * @param[in] config DltLogStorageFilterConfig + * @param[in] value string given in config file + * @return 0 on success, 1 on unknown value, -1 on error + */ +DLT_STATIC int dlt_logstorage_check_overwrite_strategy(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + return -1; + + if (strcasestr(value, "DISCARD_OLD") != NULL) { + config->overwrite = DLT_LOGSTORAGE_OVERWRITE_DISCARD_OLD; + } else if (strcasestr(value, "DISCARD_NEW") != NULL) { + config->overwrite = DLT_LOGSTORAGE_OVERWRITE_DISCARD_NEW; + } else { + dlt_log(LOG_WARNING, + "Unknown overwrite strategy. Set default DISCARD_OLD\n"); + config->overwrite = DLT_LOGSTORAGE_OVERWRITE_DISCARD_OLD; + return 1; + } + + return 0; +} + +/** + * dlt_logstorage_check_disable_network + * + * Evaluate disable network. The disable network is an optional filter + * configuration parameter. + * If the given value cannot be associated with a flag, the default + * flag will be assigned. + * + * @param[in] config DltLogStorageFilterConfig + * @param[in] value string given in config file + * @return 0 on success, 1 on unknown value, -1 on error + */ +DLT_STATIC int dlt_logstorage_check_disable_network(DltLogStorageFilterConfig *config, + char *value) +{ + if ((config == NULL) || (value == NULL)) + return -1; + + if (strcasestr(value, "ON") != NULL) { + config->disable_network_routing = DLT_LOGSTORAGE_DISABLE_NW_ON; + } else if (strcasestr(value, "OFF") != NULL) { + config->disable_network_routing = DLT_LOGSTORAGE_DISABLE_NW_OFF; + } else { + dlt_log(LOG_WARNING, + "Unknown disable network flag. Set default OFF\n"); + config->disable_network_routing = DLT_LOGSTORAGE_DISABLE_NW_OFF; + return 1; + } + + return 0; +} + /** * dlt_logstorage_check_ecuid * @@ -1234,6 +1346,11 @@ DLT_STATIC DltLogstorageFilterConf .func = dlt_logstorage_check_sync_strategy, .is_opt = 1 }, + [DLT_LOGSTORAGE_FILTER_CONF_OVERWRITEBEHAVIOR] = { + .key = "OverwriteBehavior", + .func = dlt_logstorage_check_overwrite_strategy, + .is_opt = 1 + }, [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { .key = "EcuID", .func = dlt_logstorage_check_ecuid, @@ -1248,6 +1365,11 @@ DLT_STATIC DltLogstorageFilterConf .key = "GzipCompression", .func = dlt_logstorage_check_gzip_compression, .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_DISABLE_NETWORK] = { + .key = "DisableNetwork", + .func = dlt_logstorage_check_disable_network, + .is_opt = 1 } }; @@ -1294,6 +1416,11 @@ DLT_STATIC DltLogstorageFilterConf .func = dlt_logstorage_check_sync_strategy, .is_opt = 1 }, + [DLT_LOGSTORAGE_FILTER_CONF_OVERWRITEBEHAVIOR] = { + .key = NULL, + .func = dlt_logstorage_check_overwrite_strategy, + .is_opt = 1 + }, [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { .key = "EcuID", .func = dlt_logstorage_check_ecuid, @@ -1308,6 +1435,11 @@ DLT_STATIC DltLogstorageFilterConf .key = "GzipCompression", .func = dlt_logstorage_check_gzip_compression, .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_DISABLE_NETWORK] = { + .key = NULL, + .func = dlt_logstorage_check_disable_network, + .is_opt = 1 } }; @@ -1353,6 +1485,11 @@ DLT_STATIC DltLogstorageFilterConf .func = dlt_logstorage_check_sync_strategy, .is_opt = 1 }, + [DLT_LOGSTORAGE_FILTER_CONF_OVERWRITEBEHAVIOR] = { + .key = NULL, + .func = dlt_logstorage_check_overwrite_strategy, + .is_opt = 1 + }, [DLT_LOGSTORAGE_FILTER_CONF_ECUID] = { .key = "EcuID", .func = dlt_logstorage_check_ecuid, @@ -1367,8 +1504,14 @@ DLT_STATIC DltLogstorageFilterConf .key = "GzipCompression", .func = dlt_logstorage_check_gzip_compression, .is_opt = 1 + }, + [DLT_LOGSTORAGE_FILTER_CONF_DISABLE_NETWORK] = { + .key = NULL, + .func = dlt_logstorage_check_disable_network, + .is_opt = 1 } }; + /** * Check filter configuration parameter is valid. * @@ -1506,6 +1649,7 @@ DLT_STATIC int dlt_daemon_offline_setup_filter_properties(DltLogStorage *handle, memset(&tmp_data, 0, sizeof(DltLogStorageFilterConfig)); tmp_data.log_level = DLT_LOG_VERBOSE; tmp_data.reset_log_level = DLT_LOG_OFF; + tmp_data.disable_network_routing = DLT_LOGSTORAGE_DISABLE_NW_OFF; for (i = 0; i < DLT_LOGSTORAGE_FILTER_CONF_COUNT; i++) { ret = dlt_logstorage_get_filter_value(config_file, sec_name, i, value); @@ -1839,7 +1983,7 @@ DLT_STATIC int dlt_logstorage_load_config(DltLogStorage *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) +int dlt_logstorage_device_connected(DltLogStorage *handle, const char *mount_point) { if ((handle == NULL) || (mount_point == NULL)) { dlt_log(LOG_ERR, "Handle error \n"); @@ -1863,8 +2007,13 @@ int dlt_logstorage_device_connected(DltLogStorage *handle, char *mount_point) handle->num_configs = 0; handle->newest_file_list = NULL; - /* Setup logstorage with config file settings */ - return dlt_logstorage_load_config(handle); + switch (handle->config_mode) { + case DLT_LOGSTORAGE_CONFIG_FILE: + /* Setup logstorage with config file settings */ + return dlt_logstorage_load_config(handle); + default: + return -1; + } } /** @@ -2134,17 +2283,27 @@ DLT_STATIC int dlt_logstorage_filter(DltLogStorage *handle, num = dlt_logstorage_get_config(handle, config, apid, ctid, ecuid); if (num == 0) { - dlt_log(LOG_DEBUG, "No valid filter configuration found\n"); + dlt_vlog(LOG_DEBUG, + "%s: No valid filter configuration found for apid=[%.4s] ctid=[%.4s] ecuid=[%.4s]\n", + __func__, apid, ctid, ecuid); return 0; } for (i = 0 ; i < num ; i++) { if (config[i] == NULL) + { + dlt_vlog(LOG_DEBUG, + "%s: config[%d] is NULL, continue the filter loop\n", + __func__, i); continue; + } /* filter on log level */ if (log_level > config[i]->log_level) { + dlt_vlog(LOG_DEBUG, + "%s: Requested log level (%d) is higher than config[%d]->log_level (%d). Set the config to NULL and continue the filter loop\n", + __func__, log_level, i, config[i]->log_level); config[i] = NULL; continue; } @@ -2152,7 +2311,12 @@ DLT_STATIC int 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, DLT_ID_SIZE) != 0) + { + dlt_vlog(LOG_DEBUG, + "%s: ECUID does not match (Requested=%s, config[%d]=%s). Set the config to NULL and continue the filter loop\n", + __func__, ecuid, i, config[i]->ecuid); config[i] = NULL; + } } } @@ -2173,6 +2337,7 @@ DLT_STATIC int dlt_logstorage_filter(DltLogStorage *handle, * @param size2 Size of extended message body * @param data3 Data buffer of message body * @param size3 Size of message body + * @param disable_nw Flag to disable network routing * @return 0 on success or write errors < max write errors, -1 on error */ int dlt_logstorage_write(DltLogStorage *handle, @@ -2182,7 +2347,8 @@ int dlt_logstorage_write(DltLogStorage *handle, unsigned char *data2, int size2, unsigned char *data3, - int size3) + int size3, + int *disable_nw) { DltLogStorageFilterConfig *config[DLT_CONFIG_FILE_SECTIONS_MAX] = { 0 }; @@ -2228,7 +2394,7 @@ int dlt_logstorage_write(DltLogStorage *handle, /* 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"); + dlt_vlog(LOG_ERR, "%s: DLT message header is too small\n", __func__); return 0; } @@ -2243,7 +2409,9 @@ int dlt_logstorage_write(DltLogStorage *handle, extendedHeader->ctid, extraHeader->ecu, log_level); if ((num == 0) || (num == -1)) { - dlt_log(LOG_DEBUG, "No valid filter configuration found!\n"); + dlt_vlog(LOG_DEBUG, + "%s: No valid filter configuration found for apid=[%.4s] ctid=[%.4s] ecuid=[%.4s]!\n", + __func__, extendedHeader->apid, extendedHeader->ctid, extraHeader->ecu); return 0; } } @@ -2273,12 +2441,41 @@ int dlt_logstorage_write(DltLogStorage *handle, for (i = 0; i < num; i++) { if (config[i] == NULL) + { + dlt_vlog(LOG_DEBUG, + "%s: config[%d] is NULL. Continue the filter loop\n", + __func__, i); continue; + } /* If file name is not present, the filter is non verbose control filter * hence skip storing */ if (config[i]->file_name == NULL) + { + dlt_vlog(LOG_DEBUG, + "%s: config[%d]->file_name is NULL, which equals to non verbose control filter. Continue the filter loop\n", + __func__, i); continue; + } + + /* Disable network routing */ + if ((config[i]->disable_network_routing & DLT_LOGSTORAGE_DISABLE_NW_ON) > 0) { + *disable_nw = 1; + if (config[i]->ecuid == NULL) + dlt_vlog(LOG_DEBUG, "%s: Disable routing to network for ApId-CtId-EcuId [%s]-[%s]-[]\n", __func__, + config[i]->apids, config[i]->ctids); + else + dlt_vlog(LOG_DEBUG, "%s: Disable routing to network for ApId-CtId-EcuId [%s]-[%s]-[%s]\n", __func__, + config[i]->apids, config[i]->ctids, config[i]->ecuid); + } + + if (config[i]->skip == 1) + { + dlt_vlog(LOG_DEBUG, + "%s: config[%d] (filename=%s) is skipped. Continue the filter loop\n", + __func__, i, config[i]->file_name); + continue; + } tmp = handle->newest_file_list; while (tmp) { @@ -2310,8 +2507,13 @@ int dlt_logstorage_write(DltLogStorage *handle, size1 + size2 + size3, tmp); - if (config[i]->sync == DLT_LOGSTORAGE_SYNC_UNSET || - config[i]->sync == DLT_LOGSTORAGE_SYNC_ON_MSG) { + if (ret == 0 && config[i]->skip == 1) { + continue; + } + + if ((ret == 0) && + (config[i]->sync == DLT_LOGSTORAGE_SYNC_UNSET || + config[i]->sync == DLT_LOGSTORAGE_SYNC_ON_MSG)) { /* It is abnormal if working file is still NULL after preparation. */ if (!config[i]->working_file_name) { dlt_vlog(LOG_ERR, "Failed to prepare working file for %s\n", @@ -2376,7 +2578,7 @@ int dlt_logstorage_write(DltLogStorage *handle, handle->write_errors += 1; if (handle->write_errors >= - DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS) + DLT_OFFLINE_LOGSTORAGE_MAX_ERRORS) err = -1; dlt_log(LOG_ERR, @@ -2384,8 +2586,18 @@ int dlt_logstorage_write(DltLogStorage *handle, } } else { - dlt_log(LOG_ERR, - "dlt_logstorage_write: Unable to prepare.\n"); + handle->prepare_errors += 1; + + if (handle->prepare_errors >= + DLT_OFFLINE_LOGSTORAGE_MAX_ERRORS) { + config[i]->skip = 1; + dlt_vlog(LOG_WARNING, + "%s: Unable to prepare. Skip filename [%s] because maxmimum trial has been reached.\n", + __func__, config[i]->file_name); + } else { + dlt_vlog(LOG_ERR, + "%s: Unable to prepare.\n", __func__); + } } } diff --git a/src/offlinelogstorage/dlt_offline_logstorage.h b/src/offlinelogstorage/dlt_offline_logstorage.h index 0a48f216f..d5d74fc2e 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage.h +++ b/src/offlinelogstorage/dlt_offline_logstorage.h @@ -69,8 +69,8 @@ #define DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES 2 /* sync logstorage caches */ -#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_MAX_KEY_LEN 15 /* Maximum size for key */ +#define DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN 100 /* Maximum file name length of the log file including path under mount point */ #define DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN 4 #define DLT_OFFLINE_LOGSTORAGE_GZ_FILE_EXTENSION_LEN 7 @@ -85,17 +85,16 @@ DLT_OFFLINE_LOGSTORAGE_INDEX_LEN + \ DLT_OFFLINE_LOGSTORAGE_FILE_EXTENSION_LEN + 1) -#define DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN 50 #define DLT_OFFLINE_LOGSTORAGE_CONFIG_FILE_NAME "dlt_logstorage.conf" /* +3 because of device number and \0 */ #define DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN (DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN + \ - DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN + 3) + DLT_MOUNT_PATH_MAX + 3) #define DLT_OFFLINE_LOGSTORAGE_MAX(A, B) ((A) > (B) ? (A) : (B)) #define DLT_OFFLINE_LOGSTORAGE_MIN(A, B) ((A) < (B) ? (A) : (B)) -#define DLT_OFFLINE_LOGSTORAGE_MAX_WRITE_ERRORS 5 +#define DLT_OFFLINE_LOGSTORAGE_MAX_ERRORS 5 #define DLT_OFFLINE_LOGSTORAGE_MAX_KEY_NUM 8 #define DLT_OFFLINE_LOGSTORAGE_CONFIG_SECTION "FILTER" @@ -115,6 +114,18 @@ #define DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(S, s) ((S)&(s)) +/* Offline Logstorage overwrite strategies */ +#define DLT_LOGSTORAGE_OVERWRITE_ERROR -1 /* error case */ +#define DLT_LOGSTORAGE_OVERWRITE_UNSET 0 /* strategy not set */ +#define DLT_LOGSTORAGE_OVERWRITE_DISCARD_OLD 1 /* default, discard old */ +#define DLT_LOGSTORAGE_OVERWRITE_DISCARD_NEW (1 << 1) /* discard new */ + +/* Offline Logstorage disable network routing */ +#define DLT_LOGSTORAGE_DISABLE_NW_ERROR -1 /* error case */ +#define DLT_LOGSTORAGE_DISABLE_NW_UNSET 0 /* not set */ +#define DLT_LOGSTORAGE_DISABLE_NW_OFF 1 /* default, enable network routing */ +#define DLT_LOGSTORAGE_DISABLE_NW_ON (1 << 1) /* disable network routing */ + /* logstorage max cache */ extern unsigned int g_logstorage_cache_max; /* current logstorage cache size */ @@ -135,6 +146,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 */ + int logfile_optional_counter; /* Don't append counter for num_files=1 */ } DltLogStorageUserConfig; typedef struct DltLogStorageFileList @@ -170,6 +182,8 @@ struct DltLogStorageFilterConfig 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 */ + int overwrite; /* Overwrite strategy */ + int skip; /* Flag to skip file logging if DISCARD_NEW */ char *ecuid; /* ECU identifier */ unsigned int gzip_compression; /* Toggle if log files should be gzip compressed */ /* callback function for filter configurations */ @@ -202,6 +216,7 @@ struct DltLogStorageFilterConfig 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 */ DltLogStorageFileList *records; /* File name list */ + int disable_network_routing; /* Flag to disable routing to network client */ }; typedef struct DltLogStorageFilterList DltLogStorageFilterList; @@ -214,6 +229,10 @@ struct DltLogStorageFilterList DltLogStorageFilterList *next; /* Pointer to next */ }; +typedef enum { + DLT_LOGSTORAGE_CONFIG_FILE = 0, /* Use dlt-logstorage.conf file from device */ +} DltLogStorageConfigMode; + typedef struct { DltLogStorageFilterList *config_list; /* List of all filters */ @@ -222,9 +241,11 @@ typedef struct 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 prepare_errors; /* number of prepare errors */ int write_errors; /* number of write errors */ DltNewestFileName *newest_file_list; /* List of newest file name */ int maintain_logstorage_loglevel; /* Permission to maintain the logstorage loglevel*/ + DltLogStorageConfigMode config_mode; /* Configuration Mechanism */ } DltLogStorage; typedef struct { @@ -253,9 +274,11 @@ typedef enum { DLT_LOGSTORAGE_FILTER_CONF_FILESIZE, DLT_LOGSTORAGE_FILTER_CONF_NOFILES, DLT_LOGSTORAGE_FILTER_CONF_SYNCBEHAVIOR, + DLT_LOGSTORAGE_FILTER_CONF_OVERWRITEBEHAVIOR, DLT_LOGSTORAGE_FILTER_CONF_ECUID, DLT_LOGSTORAGE_FILTER_CONF_SPECIFIC_SIZE, DLT_LOGSTORAGE_FILTER_CONF_GZIP_COMPRESSION, + DLT_LOGSTORAGE_FILTER_CONF_DISABLE_NETWORK, DLT_LOGSTORAGE_FILTER_CONF_COUNT } DltLogstorageFilterConfType; @@ -270,7 +293,7 @@ typedef enum { * @return 0 on success, -1 on error */ int dlt_logstorage_device_connected(DltLogStorage *handle, - char *mount_point); + const char *mount_point); /** * dlt_logstorage_device_disconnected @@ -330,6 +353,7 @@ int dlt_logstorage_get_loglevel_by_key(DltLogStorage *handle, char *key); * @param size2 Size of extended message body * @param data3 Data buffer of message body * @param size3 Size of message body + * @param disable_nw Flag to disable network routing * @return 0 on success or write errors < max write errors, -1 on error */ int dlt_logstorage_write(DltLogStorage *handle, @@ -339,7 +363,8 @@ int dlt_logstorage_write(DltLogStorage *handle, unsigned char *data2, int size2, unsigned char *data3, - int size3); + int size3, + int *disable_nw); /** * dlt_logstorage_sync_caches diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior.c b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c index 396e48fc7..a84461bc5 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage_behavior.c +++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "dlt_common.h" #include "dlt_offline_logstorage.h" @@ -71,46 +72,60 @@ DLT_STATIC void dlt_logstorage_concat_logfile_name(char *log_file_name, const ch * timestamp: yyyy-mm-dd-hh-mm-ss (enabled/disabled in dlt.conf) * index: Index len depends on wrap around value in dlt.conf * ex: wrap around = 99, index will 01..99 + * (enabled/disabled in dlt.conf) * - * @param log_file_name contains complete logfile name - * @param file_config User configurations for log file - * @param name file name given in configuration file - * @param idx continous index of log files + * @param[out] log_file_name target buffer for the complete logfile name. + * it needs to fit DLT_MOUNT_PATH_MAX chars + * @param[in] file_config User configurations for log file + * @param[in] name file name given in configuration file + * @param[in] num_files max files given in configuration file + * @param[in] idx continous index of log files * @ return None */ void dlt_logstorage_log_file_name(char *log_file_name, DltLogStorageUserConfig *file_config, - DltLogStorageFilterConfig *filter_config, - int idx) + const DltLogStorageFilterConfig *filter_config, + const char *name, + const int num_files, + const int idx) { if ((log_file_name == NULL) || (file_config == NULL) || (filter_config == NULL)) return; - char file_index[10] = { '\0' }; + const char delim = file_config->logfile_delimiter; + int index_width = file_config->logfile_counteridxlen; - /* create log file name */ - memset(log_file_name, '\0', DLT_MOUNT_PATH_MAX * sizeof(char)); - dlt_logstorage_concat_logfile_name(log_file_name, filter_config->file_name); - dlt_logstorage_concat_logfile_name(log_file_name, &file_config->logfile_delimiter); + if (file_config->logfile_maxcounter == UINT_MAX) { + index_width = 0; + } - snprintf(file_index, 10, "%d", idx); + const char * suffix = ".dlt"; + const int smax = DLT_MOUNT_PATH_MAX - strlen(suffix) - 1; + int spos = 0; + log_file_name[spos] = '\0'; + int rt; - if (file_config->logfile_maxcounter != UINT_MAX) { - /* Setup 0's to be appended in file index until max index len*/ - unsigned int digit_idx = 0; - unsigned int i = 0; - snprintf(file_index, 10, "%d", idx); - digit_idx = strlen(file_index); + /* Append file name */ + spos += strlen(name); + dlt_logstorage_concat_logfile_name(log_file_name, filter_config->file_name); - if (file_config->logfile_counteridxlen > digit_idx) - { - for (i = 0 ; i < (file_config->logfile_counteridxlen - digit_idx) ; i++) - dlt_logstorage_concat_logfile_name(log_file_name, "0"); + /* Append index */ + /* Do not append if there is only one file and optional index mode is true*/ + if (!(num_files == 1 && file_config->logfile_optional_counter)) { + rt = snprintf(log_file_name+spos, smax-spos, "%c%0*d", delim, index_width, idx); + if (rt >= smax-spos) { + dlt_vlog(LOG_WARNING, "%s: snprintf truncation %s\n", __func__, log_file_name); + spos = smax; + } else if (rt < 0) { + dlt_vlog(LOG_ERR, "%s: snprintf error rt=%d\n", __func__, rt); + const char *fmt_err = "fmt_err"; + memcpy(log_file_name, fmt_err, strlen(fmt_err)+1); + spos = strlen(fmt_err) + 1; + } else { + spos += rt; } } - dlt_logstorage_concat_logfile_name(log_file_name, file_index); - /* Add time stamp if user has configured */ if (file_config->logfile_timestamp) { char stamp[DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1] = { 0 }; @@ -122,7 +137,7 @@ void dlt_logstorage_log_file_name(char *log_file_name, n = snprintf(stamp, DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1, "%c%04d%02d%02d-%02d%02d%02d", - file_config->logfile_delimiter, + delim, 1900 + tm_info.tm_year, 1 + tm_info.tm_mon, tm_info.tm_mday, @@ -298,6 +313,9 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, unsigned int current_idx = 0; DltLogStorageFileList *n = NULL; DltLogStorageFileList *n1 = NULL; + char storage_path[DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN + 1] = { '\0' }; + char file_name[DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + 1] = { '\0' }; + char* dir = NULL; if ((config == NULL) || (file_config == NULL) || @@ -305,14 +323,37 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, (config->file_name == NULL)) return -1; - cnt = scandir(path, &files, 0, alphasort); + strncpy(storage_path, path, DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN); + + if (strstr(config->file_name, "/") != NULL) { + /* Append directory path */ + char tmpdir[DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + 1] = { '\0' }; + char tmpfile[DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + 1] = { '\0' }; + char *file; + strncpy(tmpdir, config->file_name, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN); + strncpy(tmpfile, config->file_name, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN); + dir = dirname(tmpdir); + file = basename(tmpfile); + if ((strlen(path) + strlen(dir)) > DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN) { + dlt_vlog(LOG_ERR, "%s: Directory name [%s] is too long to store (file name [%s])\n", + __func__, dir, file); + return -1; + } + strncat(storage_path, dir, DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN - strlen(dir)); + strncpy(file_name, file, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN); + } else { + strncpy(file_name, config->file_name, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN); + } + + cnt = scandir(storage_path, &files, 0, alphasort); if (cnt < 0) { - dlt_vlog(LOG_ERR, "%s: Failed to scan directory\n", __func__); + dlt_vlog(LOG_ERR, "%s: Failed to scan directory [%s] for file name [%s]\n", + __func__, storage_path, file_name); return -1; } - dlt_vlog(LOG_DEBUG, "%s: Scanned [%d] files from %s\n", __func__, cnt, path); + dlt_vlog(LOG_DEBUG, "%s: Scanned [%d] files from %s\n", __func__, cnt, storage_path); /* In order to have a latest status of file list, * the existing records must be deleted before updating @@ -343,17 +384,34 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, } for (i = 0; i < cnt; i++) { + const char* suffix = ".dlt"; int len = 0; - int fname_len = 0; - len = strlen(config->file_name); - fname_len = strlen(files[i]->d_name); + len = strlen(file_name); + + dlt_vlog(LOG_DEBUG, + "%s: Scanned file name=[%s], filter file name=[%s]\n", + __func__, files[i]->d_name, file_name); + if (strncmp(files[i]->d_name, file_name, len) == 0) { + if (config->num_files == 1 && file_config->logfile_optional_counter) { + /* .dlt or _.dlt */ + if ((files[i]->d_name[len] == suffix[0]) || + (file_config->logfile_timestamp && + (files[i]->d_name[len] == file_config->logfile_delimiter))) { + current_idx = 1; + } else { + continue; + } + } else { + /* _idx.dlt or _idx_.dlt */ + if (files[i]->d_name[len] == file_config->logfile_delimiter) { + current_idx = dlt_logstorage_get_idx_of_log_file(file_config, config, + files[i]->d_name); + } else { + continue; + } + } - if ((strncmp(files[i]->d_name, config->file_name, len) == 0) && - (files[i]->d_name[len] == file_config->logfile_delimiter) && - (fname_len > suffix_len && strncmp(&files[i]->d_name[fname_len - suffix_len], suffix, suffix_len) == 0)) - { DltLogStorageFileList **tmp = NULL; - current_idx = dlt_logstorage_get_idx_of_log_file(file_config, config, files[i]->d_name); if (config->records == NULL) { config->records = malloc(sizeof(DltLogStorageFileList)); @@ -381,7 +439,14 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, } } - (*tmp)->name = strdup(files[i]->d_name); + char tmpfile[DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN + 1] = { '\0' }; + if (dir != NULL) { + /* Append directory path */ + strcat(tmpfile, dir); + strcat(tmpfile, "/"); + } + strcat(tmpfile, files[i]->d_name); + (*tmp)->name = strdup(tmpfile); (*tmp)->idx = current_idx; (*tmp)->next = NULL; check++; @@ -389,7 +454,7 @@ int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig *file_config, } dlt_vlog(LOG_DEBUG, "%s: After dir scan: [%d] files of [%s]\n", __func__, - check, config->file_name); + check, file_name); if (ret == 0) { max_idx = dlt_logstorage_sort_file_name(&config->records); @@ -459,26 +524,27 @@ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int msg_size, - bool is_update_required) + bool is_update_required, + bool is_sync) { int ret = 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' }; + char absolute_file_path[DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN + 1] = { '\0' }; + char storage_path[DLT_MOUNT_PATH_MAX + 1] = { '\0' }; + char file_name[DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN + 1] = { '\0' }; unsigned int num_log_files = 0; struct stat s; DltLogStorageFileList **tmp = NULL; DltLogStorageFileList **newest = NULL; - char file_name[DLT_MOUNT_PATH_MAX + 1] = { '\0' }; if (config == NULL) return -1; - if (strlen(dev_path) > DLT_OFFLINE_LOGSTORAGE_CONFIG_DIR_PATH_LEN) { + if (strlen(dev_path) > DLT_MOUNT_PATH_MAX) { 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); + snprintf(storage_path, DLT_MOUNT_PATH_MAX, "%s/", dev_path); /* check if there are already files stored */ if (config->records == NULL || is_update_required) { @@ -500,7 +566,12 @@ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, /* need new file*/ if (num_log_files == 0) { - dlt_logstorage_log_file_name(file_name, file_config, config, 1); + dlt_logstorage_log_file_name(file_name, + file_config, + config, + config->file_name, + config->num_files, + 1); /* concatenate path and file and open absolute path */ strcat(absolute_file_path, storage_path); @@ -543,8 +614,12 @@ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *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 file stats is read and, either + * is_sync is true and (other than ON_MSG sync behavior and current size is less than configured size) or + * msg_size fit into the size (ON_MSG or par of cache needs to be written into new file), open it */ + if ((ret == 0) && + ((is_sync && (s.st_size < (int)config->file_size)) || + (!is_sync && (s.st_size + msg_size <= (int)config->file_size)))) { dlt_logstorage_open_log_output_file(config, absolute_file_path, "a"); config->current_write_file_offset = s.st_size; } @@ -563,7 +638,12 @@ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, config->wrap_id += 1; } - dlt_logstorage_log_file_name(file_name, file_config, config, idx); + dlt_logstorage_log_file_name(file_name, + file_config, + config, + config->file_name, + config->num_files, + idx); /* concatenate path and file and open absolute path */ memset(absolute_file_path, @@ -588,7 +668,7 @@ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, __func__, absolute_file_path, num_log_files, config->num_files); } - dlt_logstorage_open_log_output_file(config, absolute_file_path, "a"); + config->log = fopen(absolute_file_path, "w+"); dlt_vlog(LOG_DEBUG, "%s: Filename and Index after updating [%s]-[%u]\n", @@ -610,25 +690,29 @@ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, /* check if number of log files exceeds configured max value */ if (num_log_files > config->num_files) { - /* delete oldest */ - DltLogStorageFileList **head = &config->records; - DltLogStorageFileList *n = *head; - memset(absolute_file_path, - 0, - sizeof(absolute_file_path) / sizeof(char)); - strcat(absolute_file_path, storage_path); - strcat(absolute_file_path, (*head)->name); - dlt_vlog(LOG_DEBUG, - "%s: Remove '%s' (num_log_files: %u, config->num_files:%u)\n", - __func__, absolute_file_path, num_log_files, - config->num_files); - remove(absolute_file_path); - free((*head)->name); - (*head)->name = NULL; - *head = n->next; - n->next = NULL; - free(n); + if (!(config->num_files == 1 && file_config->logfile_optional_counter)) { + /* delete oldest */ + DltLogStorageFileList **head = &config->records; + DltLogStorageFileList *n = *head; + memset(absolute_file_path, + 0, + sizeof(absolute_file_path) / sizeof(char)); + strcat(absolute_file_path, storage_path); + strcat(absolute_file_path, (*head)->name); + dlt_vlog(LOG_DEBUG, + "%s: Remove '%s' (num_log_files: %d, config->num_files:%d, file_name:%s)\n", + __func__, absolute_file_path, num_log_files, + config->num_files, config->file_name); + remove(absolute_file_path); + + free((*head)->name); + (*head)->name = NULL; + *head = n->next; + n->next = NULL; + free(n); + } } + } } @@ -701,8 +785,8 @@ DLT_STATIC int dlt_logstorage_find_last_dlt_header(void *ptr, const char magic[] = {'D', 'L', 'T', 0x01}; const char *cache = (char*)ptr + offset; - unsigned int i; - for (i = cnt; i > 0; i--) { + int i; + for (i = cnt - (DLT_ID_SIZE - 1) ; i > 0; i--) { if ((cache[i] == 'D') && (strncmp(&cache[i], magic, 4) == 0)) return i; } @@ -848,11 +932,15 @@ DLT_STATIC int dlt_logstorage_sync_to_file(DltLogStorageFilterConfig *config, config->current_write_file_offset = 0; if (dlt_logstorage_open_log_file(config, file_config, - dev_path, count, true) != 0) { + dev_path, count, true, true) != 0) { dlt_vlog(LOG_ERR, "%s: failed to open log file\n", __func__); return -1; } + if (config->skip == 1) { + return 0; + } + remain_file_size = config->file_size - config->current_write_file_offset; if (count > remain_file_size) @@ -894,12 +982,17 @@ DLT_STATIC int dlt_logstorage_sync_to_file(DltLogStorageFilterConfig *config, /* Prepare log file */ if (config->log == NULL) { - if (dlt_logstorage_prepare_on_msg(config, file_config, dev_path, - count, NULL) != 0) + if (dlt_logstorage_open_log_file(config, file_config, dev_path, + count, true, false) != 0) { - dlt_vlog(LOG_ERR, "%s: failed to prepare log file\n", __func__); + dlt_vlog(LOG_ERR, "%s: failed to open log file\n", __func__); return -1; } + + if (config->skip == 1) + { + return 0; + } } ret = dlt_logstorage_write_to_log((uint8_t *)config->cache + start_offset + start_index, count, 1, config); @@ -938,7 +1031,7 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, if ((config == NULL) || (file_config == NULL) || (dev_path == NULL) || (newest_file_info == NULL)) { - dlt_vlog(LOG_DEBUG, "Wrong paratemters\n"); + dlt_vlog(LOG_INFO, "%s: Wrong paratemters\n", __func__); return -1; } @@ -963,7 +1056,8 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, file_config, dev_path, log_msg_size, - true); + true, + false); } else { /* already open, check size and create a new file if needed */ ret = fstat(config->fd, &s); @@ -979,6 +1073,16 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, (strcmp(config->working_file_name, newest_file_info->newest_file) != 0) || (config->wrap_id < newest_file_info->wrap_id)) { + /* Sync only if on_msg */ + if ((config->sync == DLT_LOGSTORAGE_SYNC_ON_MSG) || + (config->sync == DLT_LOGSTORAGE_SYNC_UNSET)) { + if (fsync(fileno(config->log)) != 0) { + if (errno != ENOSYS) { + dlt_vlog(LOG_ERR, "%s: failed to sync log file\n", __func__); + } + } + } + dlt_logstorage_close_file(config); /* Sync the wrap id and working file name before opening log file */ @@ -995,15 +1099,15 @@ int dlt_logstorage_prepare_on_msg(DltLogStorageFilterConfig *config, file_config, dev_path, log_msg_size, - true); + true, + false); } else { /*everything is prepared */ ret = 0; } } else { - dlt_log(LOG_ERR, - "dlt_logstorage_prepare_log_file: stat() failed.\n"); + dlt_vlog(LOG_ERR, "%s: stat() failed.\n", __func__); ret = -1; } } @@ -1194,8 +1298,15 @@ int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, sizeof(DltLogStorageCacheFooter)) > g_logstorage_cache_max) { - dlt_log(LOG_ERR, "Max size of Logstorage Cache already used."); + dlt_vlog(LOG_ERR, + "%s: Max size of Logstorage Cache already used. (ApId=[%s] CtId=[%s]) \n", + __func__, config->apids, config->ctids); return -1; + } else { + dlt_vlog(LOG_DEBUG, + "%s: Logstorage total: %d , requested cache size: %d, max: %d (ApId=[%s] CtId=[%s])\n", + __func__, g_logstorage_cache_size, cache_size, + g_logstorage_cache_max, config->apids, config->ctids); } /* create cache */ @@ -1209,7 +1320,7 @@ int dlt_logstorage_prepare_msg_cache(DltLogStorageFilterConfig *config, else { /* update current used cache size */ - g_logstorage_cache_size = cache_size + sizeof(DltLogStorageCacheFooter); + g_logstorage_cache_size += cache_size + sizeof(DltLogStorageCacheFooter); } } diff --git a/src/offlinelogstorage/dlt_offline_logstorage_behavior_internal.h b/src/offlinelogstorage/dlt_offline_logstorage_behavior_internal.h index ee72ea729..fbc22ae65 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage_behavior_internal.h +++ b/src/offlinelogstorage/dlt_offline_logstorage_behavior_internal.h @@ -51,8 +51,10 @@ void dlt_logstorage_log_file_name(char *log_file_name, DltLogStorageUserConfig *file_config, - DltLogStorageFilterConfig *filter_config, - int idx); + const DltLogStorageFilterConfig *filter_config, + const char *name, + const int num_files, + const int idx); unsigned int dlt_logstorage_sort_file_name(DltLogStorageFileList **head); @@ -71,7 +73,8 @@ int dlt_logstorage_open_log_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, char *dev_path, int msg_size, - bool is_update_required); + bool is_update_required, + bool is_sync); DLT_STATIC int dlt_logstorage_sync_to_file(DltLogStorageFilterConfig *config, DltLogStorageUserConfig *file_config, diff --git a/src/offlinelogstorage/dlt_offline_logstorage_internal.h b/src/offlinelogstorage/dlt_offline_logstorage_internal.h index 269ccdb65..6c659b99e 100644 --- a/src/offlinelogstorage/dlt_offline_logstorage_internal.h +++ b/src/offlinelogstorage/dlt_offline_logstorage_internal.h @@ -70,7 +70,7 @@ DLT_STATIC int dlt_logstorage_read_number(unsigned int *number, char *value); DLT_STATIC int dlt_logstorage_read_bool(unsigned int *boolean, char *value); -DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, char *value); +DLT_STATIC int dlt_logstorage_read_list_of_names(char **names, const char *value); DLT_STATIC int dlt_logstorage_check_apids(DltLogStorageFilterConfig *config, char *value); diff --git a/src/shared/dlt_common.c b/src/shared/dlt_common.c index c9e8cafa6..a699f396d 100644 --- a/src/shared/dlt_common.c +++ b/src/shared/dlt_common.c @@ -872,7 +872,7 @@ DltReturnValue dlt_message_payload(DltMessage *msg, char *text, size_t textlengt if (textlength < (((unsigned int)datalength * 3) + 20)) { dlt_vlog(LOG_WARNING, "String does not fit binary data (available=%d, required=%d) !\n", - (int) textlength, (datalength * 3) + 20); + (int)textlength, (datalength * 3) + 20); return DLT_RETURN_ERROR; } diff --git a/src/shared/dlt_config_file_parser.c b/src/shared/dlt_config_file_parser.c index e2ae5a0da..dc8d25f14 100644 --- a/src/shared/dlt_config_file_parser.c +++ b/src/shared/dlt_config_file_parser.c @@ -430,7 +430,7 @@ DltConfigFile *dlt_config_file_init(char *file_name) DltConfigFile *file; FILE *hdl = NULL; - if ((file_name == NULL) || (strlen(file_name) >= DLT_CONFIG_FILE_PATH_MAX_LEN)) { + if ((file_name == NULL) || (strlen(file_name) >= DLT_PATH_MAX)) { dlt_log(LOG_ERR, "Given configuration file invalid\n"); return NULL; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index af4b60748..057c2cac8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,9 +1,3 @@ -# Setup testing -enable_testing() - -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isystem ${gtest_SOURCE_DIR}/include") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${gtest_SOURCE_DIR}/include -std=gnu++0x") - configure_file(${PROJECT_SOURCE_DIR}/tests/testfile.dlt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/testfilter.txt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/testfile_filetransfer.txt ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) @@ -66,25 +60,23 @@ if(WITH_DLT_SHM_ENABLE) endif() foreach(target IN LISTS TARGET_LIST) - set(target_SRCS ${target}) + set(target_SRCS ${target}.cpp) add_executable(${target} ${target_SRCS} ${systemd_SRCS}) - target_link_libraries(${target} ${DLT_DAEMON_LIBRARIES} ${ZLIB_LIBRARY}) - if(EXISTS ${PROJECT_SOURCE_DIR}/tests/${target}.sh) - configure_file(${PROJECT_SOURCE_DIR}/tests/${target}.sh ${PROJECT_BINARY_DIR}/tests COPYONLY) + target_link_libraries(${target} ${DLT_DAEMON_LIBRARIES}) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${target}.sh) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${target}.sh ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) add_test(NAME ${target} - COMMAND /bin/sh -e -c "\ - sh $.sh ; \ - $ || TESTS_FAILED=1 && TESTS_FAILED=0 \ - sleep 0.5 ; \ - killall -v dlt-daemon || echo 'Could not find any daemon to kill' ; - exit $TESTS_FAILED") - set_tests_properties(${target} PROPERTIES ENVIRONMENT "PATH=$:$ENV{PATH}; \ - DLT_UT_DAEMON_PATH=$") + COMMAND /bin/sh -e -c "\ + sh $.sh ; \ + $ || TESTS_FAILED=1 && TESTS_FAILED=0 \ + sleep 0.5 ; \ + killall -v $ || echo 'Could not find any daemon to kill' ; + exit $TESTS_FAILED") + set_tests_properties(${target} PROPERTIES ENVIRONMENT "PATH=$:$ENV{PATH}") else() add_test(NAME ${target} COMMAND ${target}) endif() - set_tests_properties(${target} PROPERTIES TIMEOUT "${seconds}") endforeach() ##################### diff --git a/tests/component/CMakeLists.txt b/tests/component/CMakeLists.txt new file mode 100644 index 000000000..12f183cfb --- /dev/null +++ b/tests/component/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(logstorage_filepath) +add_subdirectory(logstorage_one_file) +add_subdirectory(logstorage_multi_file) +add_subdirectory(logstorage_max_cache_size) +add_subdirectory(disable_network) diff --git a/tests/component/disable_network/CMakeLists.txt b/tests/component/disable_network/CMakeLists.txt new file mode 100644 index 000000000..09be8c7fd --- /dev/null +++ b/tests/component/disable_network/CMakeLists.txt @@ -0,0 +1,46 @@ +set(NAME disable_network) + +add_executable(${NAME} ${NAME}.cpp) +target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/) +target_link_libraries(${NAME} PRIVATE dlt) + +set(APPID "DSNW") +set(MESSAGE_FILTER_CONFIGURATION_FILE ${CMAKE_CURRENT_SOURCE_DIR}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf) + +add_test(NAME ${NAME} COMMAND /bin/sh -e -c "\ +if [ ${CMAKE_CURRENT_SOURCE_DIR} != ${CMAKE_CURRENT_BINARY_DIR} ]; +then cp ${CMAKE_CURRENT_SOURCE_DIR}/dlt_logstorage.conf ${CMAKE_CURRENT_BINARY_DIR}/; +fi +rm -rf ${CMAKE_CURRENT_BINARY_DIR}/*.dlt +$ -c ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf & +sleep 0.1 +$ -o ${CMAKE_CURRENT_BINARY_DIR}/dlt-receive.dlt localhost & +sleep 0.1 +$ -c 2 & +sleep 1 +killall $ +killall $ +sleep 0.5 +echo 'Result from network' +$ -a ${CMAKE_CURRENT_BINARY_DIR}/dlt-receive.dlt +echo 'Result from file' +$ -a ${CMAKE_CURRENT_BINARY_DIR}/${APPID}.dlt +") + +set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CTEST_LD_PATHS}") + +set_tests_properties(${NAME} PROPERTIES PASS_REGULAR_EXPRESSION "\ +Result from network.*\ +ECU1 DSNW CT02 log info V 4 \\[Log message 2 # 0\\].*\ +ECU1 DSNW CT02 log info V 4 \\[Log message 2 # 200\\].*\ +Result from file.*\ +ECU1 DSNW CT01 log info V 4 \\[Log message 1 # 0\\].*\ +ECU1 DSNW CT01 log info V 4 \\[Log message 1 # 22\\].*\ +") +set_tests_properties(${NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "\ +Result from network.*\ +ECU1 DSNW CT01 log info V 4 \\[Log message 1 #.*\ +Result from file.*\ +ECU1 DSNW CT02 log info V 4 \\[Log message 2 #.*\ +") diff --git a/tests/component/disable_network/disable_network.cpp b/tests/component/disable_network/disable_network.cpp new file mode 100644 index 000000000..44c27110e --- /dev/null +++ b/tests/component/disable_network/disable_network.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include "dlt/dlt.h" +#include "dlt/dlt_user_macros.h" + +int main(int argc, char *argv[]) +{ + int i = 0; + int c = 0; + int num_context = 4; + int max_msg = 200; + + while ((c = getopt(argc, argv, "c:n:")) != -1) { + switch (c) { + case 'c': + { + num_context = atoi(optarg); + break; + } + case 'n': + { + max_msg = atoi(optarg); + break; + } + default: + { + break; + } + } + } + + DLT_DECLARE_CONTEXT(ctx[num_context]); + + DLT_REGISTER_APP("DSNW", "APP: Disable network routing"); + for(i = 0; i < num_context; i++) { + char ctid[DLT_ID_SIZE + 1], ctdesc[255]; + snprintf(ctid, DLT_ID_SIZE + 1, "CT%02d", i + 1); + snprintf(ctdesc, 255, "Test Context %02d", i + 1); + DLT_REGISTER_CONTEXT(ctx[i], ctid, ctdesc); + } + + for (i = 0; i <= max_msg; i++) { + for (int j = 0; j < num_context; j++) { + DLT_LOG(ctx[j], DLT_LOG_INFO, DLT_STRING("Log message"), DLT_UINT32(j + 1), DLT_STRING("#"), DLT_UINT32(i)); + } + struct timespec tv = {0, 1000000}; + nanosleep(&tv, NULL); + } + + for (i = 0; i < num_context; i++) { + DLT_UNREGISTER_CONTEXT(ctx[i]); + } + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + + return EXIT_SUCCESS; +} diff --git a/tests/component/disable_network/dlt.conf b/tests/component/disable_network/dlt.conf new file mode 100644 index 000000000..2e6183faf --- /dev/null +++ b/tests/component/disable_network/dlt.conf @@ -0,0 +1,7 @@ +MessageFilterConfigFile = ../../../../tests/component/disable_network/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 diff --git a/tests/component/disable_network/dlt_logstorage.conf b/tests/component/disable_network/dlt_logstorage.conf new file mode 100644 index 000000000..7f045ee73 --- /dev/null +++ b/tests/component/disable_network/dlt_logstorage.conf @@ -0,0 +1,10 @@ +[FILTER1] +LogAppName=DSNW +ContextName=CT01 +LogLevel=DLT_LOG_INFO +File=DSNW +FileSize=2000 +NOFiles=1 +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW +DisableNetwork=ON diff --git a/tests/component/disable_network/dlt_message_filter.conf b/tests/component/disable_network/dlt_message_filter.conf new file mode 100644 index 000000000..71a7edd05 --- /dev/null +++ b/tests/component/disable_network/dlt_message_filter.conf @@ -0,0 +1,10 @@ +[General] +Name = Genivi-LogMode +DefaultLevel = 100 + +[Filter1] +Name = Both +Level = 100 +Clients = * +ControlMessages = * +Injections = * diff --git a/tests/component/lib/context_unreg_forbid/CMakeLists.txt b/tests/component/lib/context_unreg_forbid/CMakeLists.txt new file mode 100644 index 000000000..ae13c4cbf --- /dev/null +++ b/tests/component/lib/context_unreg_forbid/CMakeLists.txt @@ -0,0 +1,22 @@ +set(NAME context_unreg_forbid) +set(MESSAGE_FILTER_CONFIGURATION_FILE ${CMAKE_CURRENT_SOURCE_DIR}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf) + +add_executable(${NAME} ${NAME}.cpp) +target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/) + +target_link_libraries(${NAME} PRIVATE dlt) + +add_test(NAME ${NAME} COMMAND /bin/sh -e -c "\ +$ -c ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf & +sleep 0.2 +$ & +sleep 0.1 +killall $ +sleep 0.5 +") + +set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CTEST_LD_PATHS}") + +set_tests_properties(${NAME} PROPERTIES PASS_REGULAR_EXPRESSION "\ +dlt_unregister_context: Contexts and application are already unregistered") diff --git a/tests/component/lib/context_unreg_forbid/dlt.conf.in b/tests/component/lib/context_unreg_forbid/dlt.conf.in new file mode 100644 index 000000000..b3eabc528 --- /dev/null +++ b/tests/component/lib/context_unreg_forbid/dlt.conf.in @@ -0,0 +1,2 @@ +MessageFilterConfigFile = @MESSAGE_FILTER_CONFIGURATION_FILE@/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock \ No newline at end of file diff --git a/tests/component/logstorage/CMakeLists.txt b/tests/component/logstorage/CMakeLists.txt new file mode 100644 index 000000000..9f50123ff --- /dev/null +++ b/tests/component/logstorage/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(logstorage_fsync) diff --git a/tests/component/logstorage/disable_network/dlt.conf.in b/tests/component/logstorage/disable_network/dlt.conf.in new file mode 100644 index 000000000..8f6fd8d8f --- /dev/null +++ b/tests/component/logstorage/disable_network/dlt.conf.in @@ -0,0 +1,7 @@ +MessageFilterConfigFile = @MESSAGE_FILTER_CONFIGURATION_FILE@/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 \ No newline at end of file diff --git a/tests/component/logstorage/logstorage_filepath/dlt.conf.in b/tests/component/logstorage/logstorage_filepath/dlt.conf.in new file mode 100644 index 000000000..8f6fd8d8f --- /dev/null +++ b/tests/component/logstorage/logstorage_filepath/dlt.conf.in @@ -0,0 +1,7 @@ +MessageFilterConfigFile = @MESSAGE_FILTER_CONFIGURATION_FILE@/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 \ No newline at end of file diff --git a/tests/component/logstorage/logstorage_fsync/CMakeLists.txt b/tests/component/logstorage/logstorage_fsync/CMakeLists.txt new file mode 100644 index 000000000..230f4e222 --- /dev/null +++ b/tests/component/logstorage/logstorage_fsync/CMakeLists.txt @@ -0,0 +1,31 @@ +set(NAME logstorage_fsync) + +# Build c-mock function fsync +add_library(logfsync SHARED logfsync.cpp) +target_link_libraries(logfsync PRIVATE ${CMAKE_DL_LIBS}) + +# Build test itself +add_executable(${NAME} ${NAME}.cpp) +target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/) + +target_link_libraries(${NAME} PRIVATE dlt) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt_logstorage.conf ${CMAKE_CURRENT_BINARY_DIR}) + +set(APPID "FSNC") +set(MESSAGE_FILTER_CONFIGURATION_FILE ${CMAKE_CURRENT_SOURCE_DIR}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf) + +add_test(NAME ${NAME} COMMAND /bin/sh -e -c "\ +rm -f ${CMAKE_CURRENT_BINARY_DIR}/${APPID}*.dlt +$ -c ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf & +sleep 0.2 +$ -c 1 -n 100 & +sleep 0.1 +killall $ +sleep 0.5 +") + +set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CTEST_LD_PATHS};LD_PRELOAD=$") + +set_tests_properties(${NAME} PROPERTIES PASS_REGULAR_EXPRESSION "fsync") diff --git a/tests/component/logstorage/logstorage_fsync/dlt.conf.in b/tests/component/logstorage/logstorage_fsync/dlt.conf.in new file mode 100644 index 000000000..8f6fd8d8f --- /dev/null +++ b/tests/component/logstorage/logstorage_fsync/dlt.conf.in @@ -0,0 +1,7 @@ +MessageFilterConfigFile = @MESSAGE_FILTER_CONFIGURATION_FILE@/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 \ No newline at end of file diff --git a/tests/component/logstorage/logstorage_fsync/dlt_logstorage.conf b/tests/component/logstorage/logstorage_fsync/dlt_logstorage.conf new file mode 100644 index 000000000..5e7c537a0 --- /dev/null +++ b/tests/component/logstorage/logstorage_fsync/dlt_logstorage.conf @@ -0,0 +1,9 @@ +[FILTER1] +LogAppName=FSNC +ContextName=CT01 +LogLevel=DLT_LOG_INFO +File=FSNC +FileSize=2000 +NOFiles=1 +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW diff --git a/tests/component/logstorage/logstorage_fsync/dlt_message_filter.conf b/tests/component/logstorage/logstorage_fsync/dlt_message_filter.conf new file mode 100644 index 000000000..71a7edd05 --- /dev/null +++ b/tests/component/logstorage/logstorage_fsync/dlt_message_filter.conf @@ -0,0 +1,10 @@ +[General] +Name = Genivi-LogMode +DefaultLevel = 100 + +[Filter1] +Name = Both +Level = 100 +Clients = * +ControlMessages = * +Injections = * diff --git a/tests/component/logstorage/logstorage_fsync/logfsync.cpp b/tests/component/logstorage/logstorage_fsync/logfsync.cpp new file mode 100644 index 000000000..0a808caa7 --- /dev/null +++ b/tests/component/logstorage/logstorage_fsync/logfsync.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +typedef int (*orig_fsync_t)(int); + +extern "C" int fsync(int fd) +{ + static orig_fsync_t orig_fsync = (orig_fsync_t)dlsym(RTLD_NEXT, "fsync"); + + // Could also track fd-name mappings by wrapping open/close + // Maybe also print current filesize to know exactly when the sync occured + fprintf(stderr, "%s: fd=%d\n", __func__, fd); + + return orig_fsync(fd); +} \ No newline at end of file diff --git a/tests/component/logstorage/logstorage_fsync/logstorage_fsync.cpp b/tests/component/logstorage/logstorage_fsync/logstorage_fsync.cpp new file mode 100644 index 000000000..53075ec35 --- /dev/null +++ b/tests/component/logstorage/logstorage_fsync/logstorage_fsync.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include "dlt/dlt.h" +#include "dlt/dlt_user_macros.h" + +int main(int argc, char *argv[]) +{ + int i = 0; + int c = 0; + int num_context = 4; + int max_msg = 200; + + while ((c = getopt(argc, argv, "c:n:")) != -1) { + switch (c) { + case 'c': + { + num_context = atoi(optarg); + break; + } + case 'n': + { + max_msg = atoi(optarg); + break; + } + default: + { + break; + } + } + } + + DLT_DECLARE_CONTEXT(ctx[num_context]); + + DLT_REGISTER_APP("FSNC", "CT: Logstorage fsync"); + for(i = 0; i < num_context; i++) { + char ctid[DLT_ID_SIZE + 1], ctdesc[255]; + snprintf(ctid, DLT_ID_SIZE + 1, "CT%02d", i + 1); + snprintf(ctdesc, 255, "Test Context %02d", i + 1); + DLT_REGISTER_CONTEXT(ctx[i], ctid, ctdesc); + } + + for (i = 0; i <= max_msg; i++) { + for (int j = 0; j < num_context; j++) { + DLT_LOG(ctx[j], DLT_LOG_INFO, DLT_STRING("Log message"), DLT_UINT32(j + 1), DLT_STRING("#"), DLT_UINT32(i)); + } + struct timespec tv = {0, 1000000}; + nanosleep(&tv, NULL); + } + + for (i = 0; i < num_context; i++) { + DLT_UNREGISTER_CONTEXT(ctx[i]); + } + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + + return EXIT_SUCCESS; +} diff --git a/tests/component/logstorage/logstorage_max_cache_size/dlt.conf.in b/tests/component/logstorage/logstorage_max_cache_size/dlt.conf.in new file mode 100644 index 000000000..8f6fd8d8f --- /dev/null +++ b/tests/component/logstorage/logstorage_max_cache_size/dlt.conf.in @@ -0,0 +1,7 @@ +MessageFilterConfigFile = @MESSAGE_FILTER_CONFIGURATION_FILE@/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 \ No newline at end of file diff --git a/tests/component/logstorage/logstorage_multi_file/dlt.conf.in b/tests/component/logstorage/logstorage_multi_file/dlt.conf.in new file mode 100644 index 000000000..8f6fd8d8f --- /dev/null +++ b/tests/component/logstorage/logstorage_multi_file/dlt.conf.in @@ -0,0 +1,7 @@ +MessageFilterConfigFile = @MESSAGE_FILTER_CONFIGURATION_FILE@/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 \ No newline at end of file diff --git a/tests/component/logstorage/logstorage_one_file/dlt.conf.in b/tests/component/logstorage/logstorage_one_file/dlt.conf.in new file mode 100644 index 000000000..8f6fd8d8f --- /dev/null +++ b/tests/component/logstorage/logstorage_one_file/dlt.conf.in @@ -0,0 +1,7 @@ +MessageFilterConfigFile = @MESSAGE_FILTER_CONFIGURATION_FILE@/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 \ No newline at end of file diff --git a/tests/component/logstorage_filepath/CMakeLists.txt b/tests/component/logstorage_filepath/CMakeLists.txt new file mode 100644 index 000000000..a1a7ba563 --- /dev/null +++ b/tests/component/logstorage_filepath/CMakeLists.txt @@ -0,0 +1,45 @@ +set(NAME logstorage_filepath) + +add_executable(${NAME} ${NAME}.cpp) +target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/) +target_link_libraries(${NAME} PRIVATE dlt) + +set(CTXNUM 2) +set(MESSAGE_FILTER_CONFIGURATION_FILE ${CMAKE_CURRENT_SOURCE_DIR}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf) + +add_test(NAME ${NAME} COMMAND /bin/sh -e -c "\ +if [ ${CMAKE_CURRENT_SOURCE_DIR} != ${CMAKE_CURRENT_BINARY_DIR} ]; +then cp ${CMAKE_CURRENT_SOURCE_DIR}/dlt_logstorage.conf ${CMAKE_CURRENT_BINARY_DIR}/; +fi +rm -rf ${CMAKE_CURRENT_BINARY_DIR}/test +rm -rf ${CMAKE_CURRENT_BINARY_DIR}/aa +mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/test +$ -c ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf & +sleep 0.2 +$ -c ${CTXNUM} & +sleep 1 +killall $ +sleep 0.5 +if [ `find ${CMAKE_CURRENT_BINARY_DIR}/aa -name 'FPTH_FAIL.dlt'` ]; +then echo 'FPTH_FAIL.dlt exists'; +$ -a ${CMAKE_CURRENT_BINARY_DIR}/aa/FPTH_FAIL.dlt; +fi +if [ `find ${CMAKE_CURRENT_BINARY_DIR}/test -name 'FPTH_OK.dlt'` ]; +then echo 'FPTH_OK.dlt exists'; +$ -a ${CMAKE_CURRENT_BINARY_DIR}/test/FPTH_OK.dlt; +fi +") + +set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CTEST_LD_PATHS}") + +set_tests_properties(${NAME} PROPERTIES PASS_REGULAR_EXPRESSION +"Skip filename \\[aa/FPTH_FAIL\\] because maxmimum trial has been reached..*\ +FPTH_OK.dlt exists.*\ +ECU1 FPTH CT02 log info V 4 \\[Log message 2 # 200\\]\ +") + +set_tests_properties(${NAME} PROPERTIES FAIL_REGULAR_EXPRESSION +"FPTH_FAIL.dlt exists\ +ECU1 FPTH CT01 log info V 4 \\[Log message 1\ +") diff --git a/tests/component/logstorage_filepath/dlt.conf b/tests/component/logstorage_filepath/dlt.conf new file mode 100644 index 000000000..b982735c8 --- /dev/null +++ b/tests/component/logstorage_filepath/dlt.conf @@ -0,0 +1,7 @@ +MessageFilterConfigFile = ../../../../tests/component/logstorage_filepath/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 diff --git a/tests/component/logstorage_filepath/dlt_logstorage.conf b/tests/component/logstorage_filepath/dlt_logstorage.conf new file mode 100644 index 000000000..aff2f6290 --- /dev/null +++ b/tests/component/logstorage_filepath/dlt_logstorage.conf @@ -0,0 +1,17 @@ +[FILTER1] +LogAppName=FPTH +ContextName=CT01 +LogLevel=DLT_LOG_INFO +File=aa/FPTH_FAIL +FileSize=2000 +NOFiles=1 +EcuID=ECU1 + +[FILTER2] +LogAppName=FPTH +ContextName=CT02 +LogLevel=DLT_LOG_INFO +File=test/FPTH_OK +FileSize=2000 +NOFiles=1 +EcuID=ECU1 diff --git a/tests/component/logstorage_filepath/dlt_message_filter.conf b/tests/component/logstorage_filepath/dlt_message_filter.conf new file mode 100644 index 000000000..71a7edd05 --- /dev/null +++ b/tests/component/logstorage_filepath/dlt_message_filter.conf @@ -0,0 +1,10 @@ +[General] +Name = Genivi-LogMode +DefaultLevel = 100 + +[Filter1] +Name = Both +Level = 100 +Clients = * +ControlMessages = * +Injections = * diff --git a/tests/component/logstorage_filepath/logstorage_filepath.cpp b/tests/component/logstorage_filepath/logstorage_filepath.cpp new file mode 100644 index 000000000..5d4e11205 --- /dev/null +++ b/tests/component/logstorage_filepath/logstorage_filepath.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include "dlt/dlt.h" +#include "dlt/dlt_user_macros.h" + +int main(int argc, char *argv[]) +{ + int i = 0; + int c = 0; + int num_context = 4; + int max_msg = 200; + + while ((c = getopt(argc, argv, "c:n:")) != -1) { + switch (c) { + case 'c': + { + num_context = atoi(optarg); + break; + } + case 'n': + { + max_msg = atoi(optarg); + break; + } + default: + { + break; + } + } + } + + DLT_DECLARE_CONTEXT(ctx[num_context]); + + DLT_REGISTER_APP("FPTH", "Logstorage filepath"); + for(i = 0; i < num_context; i++) { + char ctid[DLT_ID_SIZE + 1], ctdesc[255]; + snprintf(ctid, DLT_ID_SIZE + 1, "CT%02d", i + 1); + snprintf(ctdesc, 255, "Test Context %02d", i + 1); + DLT_REGISTER_CONTEXT(ctx[i], ctid, ctdesc); + } + + for (i = 0; i <= max_msg; i++) { + for (int j = 0; j < num_context; j++) { + DLT_LOG(ctx[j], DLT_LOG_INFO, DLT_STRING("Log message"), DLT_UINT32(j + 1), DLT_STRING("#"), DLT_UINT32(i)); + } + struct timespec tv = {0, 1000000}; + nanosleep(&tv, NULL); + } + + for (i = 0; i < num_context; i++) { + DLT_UNREGISTER_CONTEXT(ctx[i]); + } + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + + return EXIT_SUCCESS; +} diff --git a/tests/component/logstorage_max_cache_size/CMakeLists.txt b/tests/component/logstorage_max_cache_size/CMakeLists.txt new file mode 100644 index 000000000..c0c4020a6 --- /dev/null +++ b/tests/component/logstorage_max_cache_size/CMakeLists.txt @@ -0,0 +1,23 @@ +set(NAME logstorage_max_cache_size) +set(MESSAGE_FILTER_CONFIGURATION_FILE ${CMAKE_CURRENT_SOURCE_DIR}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf) + +add_executable(${NAME} ${NAME}.cpp) +target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/) +target_link_libraries(${NAME} PRIVATE dlt) + +add_test(NAME ${NAME} COMMAND /bin/sh -e -c " +if [ ${CMAKE_CURRENT_SOURCE_DIR} != ${CMAKE_CURRENT_BINARY_DIR} ]; +then cp ${CMAKE_CURRENT_SOURCE_DIR}/dlt_logstorage.conf ${CMAKE_CURRENT_BINARY_DIR}/; +fi +$ -c ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf & +sleep 0.5 +$ +sleep 0.5 +killall $") + +set(PASSEXPRESSION "Max size of Logstorage Cache already used") + +set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CTEST_LD_PATHS}") +set_tests_properties(${NAME} PROPERTIES PASS_REGULAR_EXPRESSION ${PASSEXPRESSION}) + diff --git a/tests/component/logstorage_max_cache_size/dlt.conf b/tests/component/logstorage_max_cache_size/dlt.conf new file mode 100644 index 000000000..fba4c0077 --- /dev/null +++ b/tests/component/logstorage_max_cache_size/dlt.conf @@ -0,0 +1,8 @@ +MessageFilterConfigFile = ../../../../tests/component/logstorage_max_cache_size/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 +OfflineLogstorageCacheSize = 70 diff --git a/tests/component/logstorage_max_cache_size/dlt_logstorage.conf b/tests/component/logstorage_max_cache_size/dlt_logstorage.conf new file mode 100644 index 000000000..d367d4f7d --- /dev/null +++ b/tests/component/logstorage_max_cache_size/dlt_logstorage.conf @@ -0,0 +1,44 @@ +[FILTER1] +LogAppName=LMAX +ContextName=CT01 +LogLevel=DLT_LOG_INFO +File=LMAXSTOP +FileSize=20000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER2] +LogAppName=LMAX +ContextName=CT02 +LogLevel=DLT_LOG_INFO +File=LMAX +FileSize=20000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER3] +LogAppName=LMAX +ContextName=CT03 +LogLevel=DLT_LOG_INFO +File=LMAXFILESTOP +FileSize=20000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER4] +LogAppName=LMAX +ContextName=CT04 +LogLevel=DLT_LOG_INFO +File=LMAXFILE +FileSize=20000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + diff --git a/tests/component/logstorage_max_cache_size/dlt_message_filter.conf b/tests/component/logstorage_max_cache_size/dlt_message_filter.conf new file mode 100644 index 000000000..71a7edd05 --- /dev/null +++ b/tests/component/logstorage_max_cache_size/dlt_message_filter.conf @@ -0,0 +1,10 @@ +[General] +Name = Genivi-LogMode +DefaultLevel = 100 + +[Filter1] +Name = Both +Level = 100 +Clients = * +ControlMessages = * +Injections = * diff --git a/tests/component/logstorage_max_cache_size/logstorage_max_cache_size.cpp b/tests/component/logstorage_max_cache_size/logstorage_max_cache_size.cpp new file mode 100644 index 000000000..81c25fc42 --- /dev/null +++ b/tests/component/logstorage_max_cache_size/logstorage_max_cache_size.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include "dlt/dlt.h" +#include "dlt/dlt_user_macros.h" + +int main() +{ + int i = 0; + int num_context = 4; + int max_msg = 20; + + DLT_DECLARE_CONTEXT(ctx[num_context]); + + DLT_REGISTER_APP("LMAX", "CT: Logstorage max cache size"); + for(i = 0; i < num_context; i++) { + char ctid[DLT_ID_SIZE + 1], ctdesc[255]; + snprintf(ctid, DLT_ID_SIZE + 1, "CT%02d", i + 1); + snprintf(ctdesc, 255, "Test Context %02d", i + 1); + DLT_REGISTER_CONTEXT(ctx[i], ctid, ctdesc); + } + + for (i = 0; i <= max_msg; i++) { + for (int j = 0; j < num_context; j++) { + DLT_LOG(ctx[j], DLT_LOG_INFO, DLT_STRING("Max Cache Size: Log message"), DLT_UINT32(j + 1), DLT_STRING("#")); + } + struct timespec tv = {0, 1000000}; + nanosleep(&tv, NULL); + } + + for (i = 0; i < num_context; i++) { + DLT_UNREGISTER_CONTEXT(ctx[i]); + } + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + + sleep(3); + + return EXIT_SUCCESS; +} diff --git a/tests/component/logstorage_multi_file/CMakeLists.txt b/tests/component/logstorage_multi_file/CMakeLists.txt new file mode 100644 index 000000000..3dcd90ddf --- /dev/null +++ b/tests/component/logstorage_multi_file/CMakeLists.txt @@ -0,0 +1,93 @@ +set(NAME logstorage_multi_file) + +add_executable(${NAME} ${NAME}.cpp) +target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/) +target_link_libraries(${NAME} PRIVATE dlt) + +set(CTXNUM 12) +set(MESSAGE_FILTER_CONFIGURATION_FILE ${CMAKE_CURRENT_SOURCE_DIR}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf) + +add_test(NAME ${NAME} COMMAND /bin/sh -e -c "\ +if [ ${CMAKE_CURRENT_SOURCE_DIR} != ${CMAKE_CURRENT_BINARY_DIR} ]; +then cp ${CMAKE_CURRENT_SOURCE_DIR}/dlt_logstorage.conf ${CMAKE_CURRENT_BINARY_DIR}/; +fi +rm -f ${CMAKE_CURRENT_BINARY_DIR}/MLTI*.dlt +$ -c ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf & +sleep 0.2 +$ -c ${CTXNUM} & +sleep 0.1 +$ -s -C ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf +sleep 2 +killall $ +sleep 0.5 +if [ `stat -c%s MLTISTOP_1.dlt` -gt 1000 ]; then echo 'MLTISTOP_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTISTOP_2.dlt` -gt 1000 ]; then echo 'MLTISTOP_2.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTI_18.dlt` -gt 1000 ]; then echo 'MLTI_18.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTI_19.dlt` -gt 1000 ]; then echo 'MLTI_19.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIFILESTOP_1.dlt` -gt 1000 ]; then echo 'MLTIFILESTOP_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIFILESTOP_2.dlt` -gt 1000 ]; then echo 'MLTIFILESTOP_2.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIFILE_17.dlt` -gt 1000 ]; then echo 'MLTIFILE_17.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIFILE_18.dlt` -gt 1000 ]; then echo 'MLTIFILE_18.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIDEMANDSTOP_1.dlt` -gt 1000 ]; then echo 'MLTIDEMANDSTOP_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIDEMAND_1.dlt` -gt 1000 ]; then echo 'MLTIDEMAND_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIEXITSTOP_1.dlt` -gt 1000 ]; then echo 'MLTIEXITSTOP_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTIEXIT_1.dlt` -gt 1000 ]; then echo 'MLTIEXIT_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTISPSTOP_1.dlt` -gt 1000 ]; then echo 'MLTISPSTOP_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTISPSTOP_2.dlt` -gt 1000 ]; then echo 'MLTISPSTOP_2.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTISP_17.dlt` -gt 1000 ]; then echo 'MLTISP_17.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTISP_18.dlt` -gt 1000 ]; then echo 'MLTISP_18.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTICOMBSTOP_1.dlt` -gt 1000 ]; then echo 'MLTIEXITSTOP_1.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTICOMBSTOP_2.dlt` -gt 1000 ]; then echo 'MLTICOMBSTOP_2.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTICOMB_18.dlt` -gt 1000 ]; then echo 'MLTIEXIT_18.dlt is bigger than 1000'; fi +if [ `stat -c%s MLTICOMB_19.dlt` -gt 1000 ]; then echo 'MLTIEXIT_19.dlt is bigger than 1000'; fi +$ -a MLTISTOP_1.dlt +$ -a MLTISTOP_2.dlt +$ -a MLTI_18.dlt +$ -a MLTI_19.dlt +$ -a MLTIFILESTOP_1.dlt +$ -a MLTIFILESTOP_2.dlt +$ -a MLTIFILE_17.dlt +$ -a MLTIFILE_18.dlt +$ -a MLTIDEMANDSTOP_1.dlt +$ -a MLTIDEMAND_1.dlt +$ -a MLTIEXITSTOP_1.dlt +$ -a MLTIEXIT_1.dlt +$ -a MLTISPSTOP_1.dlt +$ -a MLTISPSTOP_2.dlt +$ -a MLTISP_17.dlt +$ -a MLTISP_18.dlt +$ -a MLTICOMBSTOP_1.dlt +$ -a MLTICOMBSTOP_2.dlt +$ -a MLTICOMB_18.dlt +$ -a MLTICOMB_19.dlt +") + +set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CTEST_LD_PATHS}") + +# List of values which shall appear in log messages of each filters +# The order corresponds to dlt_logstorage.conf filter order +# If the filter shall be disabled, -1 is set +set(PASSVALUES 0 200 0 183 70 70 200 200 0 183 0 200) +set(PASSEXPRESSION "dlt_logstorage_open_log_file: logstorage limit reached, stopping capture for filter: MLTIS") +set(FAILVALUES 200 0 200 0 200 200 0 0 200 0 200 0) +set(FAILEXPRESSION "MLTI.*.dlt is bigger than 1000") +set(CTX 0) + +while(CTX LESS CTXNUM) + list(GET PASSVALUES ${CTX} PVAL) + list(GET FAILVALUES ${CTX} FVAL) + MATH(EXPR CTX "${CTX} + 1") + if(NOT ${VAL} EQUAL -1) + STRING(LENGTH "${CTX}" CTXLEN) + if(CTXLEN LESS 2) + SET(CTXID "0${CTX}") + else() + SET(CTXID "${CTX}") + endif() + string(APPEND PASSEXPRESSION ".*ECU1 MLTI CT${CTXID} log info V 4 \\[Log message ${CTX} # ${PVAL}\\]") + string(APPEND FAILEXPRESSION ".*ECU1 MLTI CT${CTXID} log info V 4 \\[Log message ${CTX} # ${FVAL}\\]") + endif() +endwhile() +set_tests_properties(${NAME} PROPERTIES PASS_REGULAR_EXPRESSION ${PASSEXPRESSION}) +set_tests_properties(${NAME} PROPERTIES FAIL_REGULAR_EXPRESSION ${FAILEXPRESSION}) diff --git a/tests/component/logstorage_multi_file/dlt.conf b/tests/component/logstorage_multi_file/dlt.conf new file mode 100644 index 000000000..684828ce2 --- /dev/null +++ b/tests/component/logstorage_multi_file/dlt.conf @@ -0,0 +1,7 @@ +MessageFilterConfigFile = ../../../../tests/component/logstorage_multi_file/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 diff --git a/tests/component/logstorage_multi_file/dlt_logstorage.conf b/tests/component/logstorage_multi_file/dlt_logstorage.conf new file mode 100644 index 000000000..53c99eb3b --- /dev/null +++ b/tests/component/logstorage_multi_file/dlt_logstorage.conf @@ -0,0 +1,131 @@ +[FILTER1] +LogAppName=MLTI +ContextName=CT01 +LogLevel=DLT_LOG_INFO +File=MLTISTOP +FileSize=1000 +NOFiles=2 +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER2] +LogAppName=MLTI +ContextName=CT02 +LogLevel=DLT_LOG_INFO +File=MLTI +FileSize=1000 +NOFiles=2 +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER3] +LogAppName=MLTI +ContextName=CT03 +LogLevel=DLT_LOG_INFO +File=MLTIFILESTOP +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER4] +LogAppName=MLTI +ContextName=CT04 +LogLevel=DLT_LOG_INFO +File=MLTIFILE +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER5] +LogAppName=MLTI +ContextName=CT05 +LogLevel=DLT_LOG_INFO +File=MLTIDEMANDSTOP +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_DEMAND +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER6] +LogAppName=MLTI +ContextName=CT06 +LogLevel=DLT_LOG_INFO +File=MLTIDEMAND +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_DEMAND +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER7] +LogAppName=MLTI +ContextName=CT07 +LogLevel=DLT_LOG_INFO +File=MLTIEXITSTOP +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER8] +LogAppName=MLTI +ContextName=CT08 +LogLevel=DLT_LOG_INFO +File=MLTIEXIT +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER9] +LogAppName=MLTI +ContextName=CT09 +LogLevel=DLT_LOG_INFO +File=MLTISPSTOP +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_SPECIFIC_SIZE +SpecificSize=300 +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER10] +LogAppName=MLTI +ContextName=CT10 +LogLevel=DLT_LOG_INFO +File=MLTISP +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_SPECIFIC_SIZE +SpecificSize=300 +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER11] +LogAppName=MLTI +ContextName=CT11 +LogLevel=DLT_LOG_INFO +File=MLTICOMBSTOP +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_FILE_SIZE,ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER12] +LogAppName=MLTI +ContextName=CT12 +LogLevel=DLT_LOG_INFO +File=MLTICOMB +FileSize=1000 +NOFiles=2 +SyncBehavior=ON_FILE_SIZE,ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD diff --git a/tests/component/logstorage_multi_file/dlt_message_filter.conf b/tests/component/logstorage_multi_file/dlt_message_filter.conf new file mode 100644 index 000000000..71a7edd05 --- /dev/null +++ b/tests/component/logstorage_multi_file/dlt_message_filter.conf @@ -0,0 +1,10 @@ +[General] +Name = Genivi-LogMode +DefaultLevel = 100 + +[Filter1] +Name = Both +Level = 100 +Clients = * +ControlMessages = * +Injections = * diff --git a/tests/component/logstorage_multi_file/logstorage_multi_file.cpp b/tests/component/logstorage_multi_file/logstorage_multi_file.cpp new file mode 100644 index 000000000..43877484f --- /dev/null +++ b/tests/component/logstorage_multi_file/logstorage_multi_file.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include "dlt/dlt.h" +#include "dlt/dlt_user_macros.h" + +int main(int argc, char *argv[]) +{ + int i = 0; + int c = 0; + int num_context = 4; + int max_msg = 200; + + while ((c = getopt(argc, argv, "c:n:")) != -1) { + switch (c) { + case 'c': + { + num_context = atoi(optarg); + break; + } + case 'n': + { + max_msg = atoi(optarg); + break; + } + default: + { + break; + } + } + } + + DLT_DECLARE_CONTEXT(ctx[num_context]); + + DLT_REGISTER_APP("MLTI", "CT: Logstorage multi file"); + for(i = 0; i < num_context; i++) { + char ctid[DLT_ID_SIZE + 1], ctdesc[255]; + snprintf(ctid, DLT_ID_SIZE + 1, "CT%02d", i + 1); + snprintf(ctdesc, 255, "Test Context %02d", i + 1); + DLT_REGISTER_CONTEXT(ctx[i], ctid, ctdesc); + } + + for (i = 0; i <= max_msg; i++) { + for (int j = 0; j < num_context; j++) { + DLT_LOG(ctx[j], DLT_LOG_INFO, DLT_STRING("Log message"), DLT_UINT32(j + 1), DLT_STRING("#"), DLT_UINT32(i)); + } + struct timespec tv = {0, 1000000}; + nanosleep(&tv, NULL); + } + + for (i = 0; i < num_context; i++) { + DLT_UNREGISTER_CONTEXT(ctx[i]); + } + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + + return EXIT_SUCCESS; +} diff --git a/tests/component/logstorage_one_file/CMakeLists.txt b/tests/component/logstorage_one_file/CMakeLists.txt new file mode 100644 index 000000000..60c94e781 --- /dev/null +++ b/tests/component/logstorage_one_file/CMakeLists.txt @@ -0,0 +1,79 @@ +set(NAME logstorage_one_file) + +add_executable(${NAME} ${NAME}.cpp) +target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/) + +target_link_libraries(${NAME} PRIVATE dlt) + +set(CTXNUM 12) +set(MESSAGE_FILTER_CONFIGURATION_FILE ${CMAKE_CURRENT_SOURCE_DIR}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf) + +add_test(NAME ${NAME} COMMAND /bin/sh -e -c "\ +if [ ${CMAKE_CURRENT_SOURCE_DIR} != ${CMAKE_CURRENT_BINARY_DIR} ]; +then cp ${CMAKE_CURRENT_SOURCE_DIR}/dlt_logstorage.conf ${CMAKE_CURRENT_BINARY_DIR}/; +fi +rm -f ${CMAKE_CURRENT_BINARY_DIR}/LONE*.dlt +$ -c ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf & +sleep 0.2 +$ -c ${CTXNUM} & +sleep 0.1 +$ -s -C ${CMAKE_CURRENT_SOURCE_DIR}/dlt.conf +sleep 1 +killall $ +sleep 0.5 +if [ `stat -c%s LONESTOP.dlt` -gt 2000 ]; then echo 'LONESTOP.dlt is bigger than 2000'; fi +if [ `stat -c%s LONE.dlt` -gt 2000 ]; then echo 'LONE.dlt is bigger than 2000'; fi +if [ `stat -c%s LONEFILESTOP.dlt` -gt 2000 ]; then echo 'LONEFILESTOP.dlt is bigger than 2000'; fi +if [ `stat -c%s LONEFILE.dlt` -gt 2000 ]; then echo 'LONEFILE.dlt is bigger than 2000'; fi +if [ `stat -c%s LONEDEMANDSTOP.dlt` -gt 2000 ]; then echo 'LONEDEMANDSTOP.dlt is bigger than 2000'; fi +if [ `stat -c%s LONEDEMAND.dlt` -gt 2000 ]; then echo 'LONEDEMAND.dlt is bigger than 2000'; fi +if [ `stat -c%s LONEEXITSTOP.dlt` -gt 2000 ]; then echo 'LONEEXITSTOP.dlt is bigger than 2000'; fi +if [ `stat -c%s LONEEXIT.dlt` -gt 2000 ]; then echo 'LONEEXIT.dlt is bigger than 2000'; fi +if [ `stat -c%s LONESPSTOP.dlt` -gt 2000 ]; then echo 'LONESPSTOP.dlt is bigger than 2000'; fi +if [ `stat -c%s LONESP.dlt` -gt 2000 ]; then echo 'LONESP.dlt is bigger than 2000'; fi +if [ `stat -c%s LONECOMBSTOP.dlt` -gt 2000 ]; then echo 'LONECOMBSTOP.dlt is bigger than 2000'; fi +if [ `stat -c%s LONECOMB.dlt` -gt 2000 ]; then echo 'LONECOMB.dlt is bigger than 2000'; fi +$ -a LONESTOP.dlt +$ -a LONE.dlt +$ -a LONEFILESTOP.dlt +$ -a LONEFILE.dlt +$ -a LONEDEMANDSTOP.dlt +$ -a LONEDEMAND.dlt +$ -a LONEEXITSTOP.dlt +$ -a LONEEXIT.dlt +$ -a LONESPSTOP.dlt +$ -a LONESP.dlt +$ -a LONECOMBSTOP.dlt +$ -a LONECOMB.dlt +") + +set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CTEST_LD_PATHS}") + +# List of values which shall appear in log messages of each filters +# The order corresponds to dlt_logstorage.conf filter order +# If the filter shall be disabled, -1 is set +set(PASSVALUES 0 200 0 183 60 60 200 200 0 199 0 200) +set(PASSEXPRESSION "dlt_logstorage_open_log_file: logstorage limit reached, stopping capture for filter: LONE") +set(FAILVALUES 200 0 200 0 200 200 0 0 200 0 200 0) +set(FAILEXPRESSION "LONE.*.dlt is bigger than 2000") +set(CTX 0) + +while(CTX LESS CTXNUM) + list(GET PASSVALUES ${CTX} PVAL) + list(GET FAILVALUES ${CTX} FVAL) + MATH(EXPR CTX "${CTX} + 1") + if(NOT ${VAL} EQUAL -1) + STRING(LENGTH "${CTX}" CTXLEN) + if(CTXLEN LESS 2) + SET(CTXID "0${CTX}") + else() + SET(CTXID "${CTX}") + endif() + string(APPEND PASSEXPRESSION ".*ECU1 LONE CT${CTXID} log info V 4 \\[Log message ${CTX} # ${PVAL}\\]") + string(APPEND FAILEXPRESSION ".*ECU1 LONE CT${CTXID} log info V 4 \\[Log message ${CTX} # ${FVAL}\\]") + endif() +endwhile() + +set_tests_properties(${NAME} PROPERTIES PASS_REGULAR_EXPRESSION ${PASSEXPRESSION}) +set_tests_properties(${NAME} PROPERTIES FAIL_REGULAR_EXPRESSION ${FAILEXPRESSION}) diff --git a/tests/component/logstorage_one_file/dlt.conf b/tests/component/logstorage_one_file/dlt.conf new file mode 100644 index 000000000..f6b901726 --- /dev/null +++ b/tests/component/logstorage_one_file/dlt.conf @@ -0,0 +1,7 @@ +MessageFilterConfigFile = ../../../../tests/component/logstorage_one_file/dlt_message_filter.conf +ControlSocketPath = ./dlt-ctrl.sock + +OfflineLogstorageTimestamp = 0 +OfflineLogstorageMaxDevices = 1 +OfflineLogstorageDirPath = . +OfflineLogstorageOptionalIndex = 1 diff --git a/tests/component/logstorage_one_file/dlt_logstorage.conf b/tests/component/logstorage_one_file/dlt_logstorage.conf new file mode 100644 index 000000000..44ba32db4 --- /dev/null +++ b/tests/component/logstorage_one_file/dlt_logstorage.conf @@ -0,0 +1,131 @@ +[FILTER1] +LogAppName=LONE +ContextName=CT01 +LogLevel=DLT_LOG_INFO +File=LONESTOP +FileSize=2000 +NOFiles=1 +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER2] +LogAppName=LONE +ContextName=CT02 +LogLevel=DLT_LOG_INFO +File=LONE +FileSize=2000 +NOFiles=1 +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER3] +LogAppName=LONE +ContextName=CT03 +LogLevel=DLT_LOG_INFO +File=LONEFILESTOP +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER4] +LogAppName=LONE +ContextName=CT04 +LogLevel=DLT_LOG_INFO +File=LONEFILE +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER5] +LogAppName=LONE +ContextName=CT05 +LogLevel=DLT_LOG_INFO +File=LONEDEMANDSTOP +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_DEMAND +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER6] +LogAppName=LONE +ContextName=CT06 +LogLevel=DLT_LOG_INFO +File=LONEDEMAND +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_DEMAND +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER7] +LogAppName=LONE +ContextName=CT07 +LogLevel=DLT_LOG_INFO +File=LONEEXITSTOP +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER8] +LogAppName=LONE +ContextName=CT08 +LogLevel=DLT_LOG_INFO +File=LONEEXIT +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER9] +LogAppName=LONE +ContextName=CT09 +LogLevel=DLT_LOG_INFO +File=LONESPSTOP +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_SPECIFIC_SIZE +SpecificSize=700 +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER10] +LogAppName=LONE +ContextName=CT10 +LogLevel=DLT_LOG_INFO +File=LONESP +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_SPECIFIC_SIZE +SpecificSize=700 +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD + +[FILTER11] +LogAppName=LONE +ContextName=CT11 +LogLevel=DLT_LOG_INFO +File=LONECOMBSTOP +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE,ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_NEW + +[FILTER12] +LogAppName=LONE +ContextName=CT12 +LogLevel=DLT_LOG_INFO +File=LONECOMB +FileSize=2000 +NOFiles=1 +SyncBehavior=ON_FILE_SIZE,ON_DAEMON_EXIT +EcuID=ECU1 +OverwriteBehavior=DISCARD_OLD diff --git a/tests/component/logstorage_one_file/dlt_message_filter.conf b/tests/component/logstorage_one_file/dlt_message_filter.conf new file mode 100644 index 000000000..71a7edd05 --- /dev/null +++ b/tests/component/logstorage_one_file/dlt_message_filter.conf @@ -0,0 +1,10 @@ +[General] +Name = Genivi-LogMode +DefaultLevel = 100 + +[Filter1] +Name = Both +Level = 100 +Clients = * +ControlMessages = * +Injections = * diff --git a/tests/component/logstorage_one_file/logstorage_one_file.cpp b/tests/component/logstorage_one_file/logstorage_one_file.cpp new file mode 100644 index 000000000..6610702a9 --- /dev/null +++ b/tests/component/logstorage_one_file/logstorage_one_file.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include "dlt/dlt.h" +#include "dlt/dlt_user_macros.h" + +int main(int argc, char *argv[]) +{ + int i = 0; + int c = 0; + int num_context = 4; + int max_msg = 200; + + while ((c = getopt(argc, argv, "c:n:")) != -1) { + switch (c) { + case 'c': + { + num_context = atoi(optarg); + break; + } + case 'n': + { + max_msg = atoi(optarg); + break; + } + default: + { + break; + } + } + } + + DLT_DECLARE_CONTEXT(ctx[num_context]); + + DLT_REGISTER_APP("LONE", "CT: Logstorage one file"); + for(i = 0; i < num_context; i++) { + char ctid[DLT_ID_SIZE + 1], ctdesc[255]; + snprintf(ctid, DLT_ID_SIZE + 1, "CT%02d", i + 1); + snprintf(ctdesc, 255, "Test Context %02d", i + 1); + DLT_REGISTER_CONTEXT(ctx[i], ctid, ctdesc); + } + + for (i = 0; i <= max_msg; i++) { + for (int j = 0; j < num_context; j++) { + DLT_LOG(ctx[j], DLT_LOG_INFO, DLT_STRING("Log message"), DLT_UINT32(j + 1), DLT_STRING("#"), DLT_UINT32(i)); + } + struct timespec tv = {0, 1000000}; + nanosleep(&tv, NULL); + } + + for (i = 0; i < num_context; i++) { + DLT_UNREGISTER_CONTEXT(ctx[i]); + } + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + + return EXIT_SUCCESS; +} diff --git a/tests/gtest_dlt_daemon_offline_log.cpp b/tests/gtest_dlt_daemon_offline_log.cpp index 9a2e7f65b..06cce109b 100644 --- a/tests/gtest_dlt_daemon_offline_log.cpp +++ b/tests/gtest_dlt_daemon_offline_log.cpp @@ -10,6 +10,8 @@ * History : 30-Jun-2016 */ #include +#include +#include int connectServer(void); @@ -559,9 +561,9 @@ TEST(t_dlt_logstorage_device_connected, normal) handle.write_errors = 0; handle.config_list = NULL; handle.newest_file_list = NULL; - strncpy(handle.device_mount_point, "/tmp", DLT_MOUNT_PATH_MAX); + handle.config_mode = DLT_LOGSTORAGE_CONFIG_FILE; - EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_device_connected(&handle, handle.device_mount_point)); + EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_device_connected(&handle, "/tmp")); } TEST(t_dlt_logstorage_device_connected, null) @@ -707,12 +709,8 @@ TEST(t_dlt_logstorage_write, normal) char file_name[] = "file_name"; DltLogStorage handle; DltLogStorageUserConfig uconfig; - unsigned char data1[] = "123"; - int size1 = 3; - unsigned char data2[] = "123"; - int size2 = 3; - unsigned char data3[] = "123"; - int size3 = 3; + unsigned char data[] = "123"; + int size = 3; handle.connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; handle.config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; handle.config_list = NULL; @@ -727,16 +725,43 @@ TEST(t_dlt_logstorage_write, normal) char key1[] = "::5678\000\000\000\000"; char key2[] = ":1234:5678"; int num_keys = 1; + int disable_nw = 0; + + DltMessage msg; + DltUserHeader userheader; + int log_level = 4; + dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG); + dlt_message_init(&msg, 0); + msg.storageheader = (DltStorageHeader *)msg.headerbuffer; + dlt_set_storageheader(msg.storageheader, ecuid); + msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); + msg.standardheader->htyp = DLT_HTYP_PROTOCOL_VERSION1|DLT_HTYP_UEH; + msg.standardheader->mcnt = 0; + dlt_message_set_extraparameters(&msg, 0); + msg.extendedheader = (DltExtendedHeader *)(msg.headerbuffer + + sizeof(DltStorageHeader) + + sizeof(DltStandardHeader) + + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); + msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | + ((log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) | DLT_MSIN_VERB; + msg.extendedheader->noar = 1; + dlt_set_id(msg.extendedheader->apid, apid); + dlt_set_id(msg.extendedheader->ctid, ctid); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key0, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key1, num_keys, &value, &(handle.config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key2, num_keys, &value, &(handle.config_list))); - EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write(&handle, &uconfig, data1, size1, data2, size2, data3, size3)); + EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write(&handle, &uconfig, + (unsigned char*)&(userheader), sizeof(DltUserHeader), + msg.headerbuffer + sizeof(DltStorageHeader), + msg.headersize - sizeof(DltStorageHeader), + data, size, &disable_nw)); + dlt_message_free(&msg, 0); } TEST(t_dlt_logstorage_write, null) { - EXPECT_EQ(0, dlt_logstorage_write(NULL, NULL, NULL, 1, NULL, 1, NULL, 1)); + EXPECT_EQ(0, dlt_logstorage_write(NULL, NULL, NULL, 1, NULL, 1, NULL, 1, 0)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_sync_caches*/ @@ -772,24 +797,73 @@ TEST(t_dlt_logstorage_log_file_name, normal) memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); file_config.logfile_delimiter = '/'; file_config.logfile_maxcounter = 0; - file_config.logfile_timestamp = 1; + file_config.logfile_timestamp = 0; file_config.logfile_counteridxlen = 10; - int cmpRes = 0; char name[] = "log"; DltLogStorageFilterConfig filter_config; memset(&filter_config, 0, sizeof(filter_config)); filter_config.file_name = &name[0]; - dlt_logstorage_log_file_name(log_file_name, &file_config, &filter_config, 0); - cmpRes = strncmp(log_file_name, "log/0000000000", 14); + dlt_logstorage_log_file_name(log_file_name, &file_config, &filter_config, "log", 10, 0); + EXPECT_EQ(std::string("log/0000000000.dlt"), log_file_name); + + file_config.logfile_counteridxlen = 3; + file_config.logfile_delimiter = '_'; + dlt_logstorage_log_file_name(log_file_name, &file_config, &filter_config, "log", 9, 98); + EXPECT_EQ(std::string("log_098.dlt"), log_file_name); +} + +TEST(t_dlt_logstorage_log_file_name, tmsp) +{ + char log_file_name[DLT_MOUNT_PATH_MAX] = { '\0' }; + DltLogStorageUserConfig file_config; + memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); + file_config.logfile_delimiter = '_'; + file_config.logfile_maxcounter = 9; + file_config.logfile_timestamp = 1; + file_config.logfile_counteridxlen = 2; + char name[] = "log"; + + DltLogStorageFilterConfig filter_config; + memset(&filter_config, 0, sizeof(filter_config)); + filter_config.file_name = &name[0]; + + dlt_logstorage_log_file_name(log_file_name, &file_config, &filter_config, "log", 8, 4); + + // log_04_20210810-094602.dlt + std::regex r("log_04_\\d{8}-\\d{6}\\.dlt"); + std::cmatch m; + EXPECT_TRUE(std::regex_search(log_file_name, m, r)); +} + +TEST(t_dlt_logstorage_log_file_name, optional_index) +{ + char log_file_name[DLT_MOUNT_PATH_MAX]; + DltLogStorageUserConfig file_config; + memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); + file_config.logfile_delimiter = '_'; + file_config.logfile_maxcounter = 1; + file_config.logfile_timestamp = 0; + file_config.logfile_counteridxlen = 4; + file_config.logfile_optional_counter = true; + char name[] = "APID"; + + DltLogStorageFilterConfig filter_config; + memset(&filter_config, 0, sizeof(filter_config)); + filter_config.file_name = &name[0]; + + dlt_logstorage_log_file_name(log_file_name, &file_config, &filter_config, "APID", 1, 0); + EXPECT_EQ(std::string("APID.dlt"), log_file_name); - EXPECT_EQ(0, cmpRes); + dlt_logstorage_log_file_name(log_file_name, &file_config, &filter_config, "APID", 2, 0); + EXPECT_EQ(std::string("APID_0000.dlt"), log_file_name); } TEST(t_dlt_logstorage_log_file_name, null) { - dlt_logstorage_log_file_name(NULL, NULL, NULL, 0); + char name[] = "log"; + dlt_logstorage_log_file_name(NULL, NULL, NULL, name, 0, 0); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_sort_file_name*/ @@ -946,7 +1020,7 @@ TEST(t_dlt_logstorage_rearrange_file_name, null) TEST(t_dlt_logstorage_get_idx_of_log_file, normal) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 1; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -973,7 +1047,7 @@ TEST(t_dlt_logstorage_get_idx_of_log_file, null) TEST(t_dlt_logstorage_storage_dir_info, normal) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 1; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -998,7 +1072,8 @@ TEST(t_dlt_logstorage_storage_dir_info, null) TEST(t_dlt_logstorage_open_log_file, normal) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); + file_config.logfile_timestamp = 0; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -1013,19 +1088,26 @@ TEST(t_dlt_logstorage_open_log_file, normal) config.records = NULL; config.working_file_name = NULL; config.wrap_id = 0; + config.file_size = 50; + char tmp_file[100] = ""; - EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_open_log_file(&config, &file_config, path, 1, true)); + EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_open_log_file(&config, &file_config, path, 1, true, false)); + EXPECT_STREQ("Test_01.dlt", config.working_file_name); + EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_open_log_file(&config, &file_config, path, 1, true, true)); + EXPECT_STREQ("Test_01.dlt", config.working_file_name); + sprintf(tmp_file, "%s/%s", path, config.working_file_name); + remove(tmp_file); } TEST(t_dlt_logstorage_open_log_file, null) { - EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_open_log_file(NULL, NULL, NULL, 0, true)); + EXPECT_EQ(DLT_RETURN_ERROR, dlt_logstorage_open_log_file(NULL, NULL, NULL, 0, true, false)); } /* Begin Method: dlt_logstorage::t_dlt_logstorage_prepare_on_msg*/ TEST(t_dlt_logstorage_prepare_on_msg, normal1) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 1; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -1054,7 +1136,7 @@ TEST(t_dlt_logstorage_prepare_on_msg, normal1) TEST(t_dlt_logstorage_prepare_on_msg, normal2) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 1; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -1096,7 +1178,7 @@ TEST(t_dlt_logstorage_prepare_on_msg, normal2) TEST(t_dlt_logstorage_prepare_on_msg, normal3) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 1; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -1145,7 +1227,7 @@ TEST(t_dlt_logstorage_prepare_on_msg, null) TEST(t_dlt_logstorage_write_on_msg, normal) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 1; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -1173,9 +1255,13 @@ TEST(t_dlt_logstorage_write_on_msg, normal) newest_file_name.wrap_id = 0; newest_file_name.next = NULL; + char tmp_file[100] = ""; + EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_on_msg(&config, &file_config, path, 1, &newest_file_name)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write_on_msg(&config, &file_config, path, data1, size, data2, size, data3, size)); + sprintf(tmp_file, "%s/%s", path, config.working_file_name); + remove(tmp_file); } #ifdef DLT_LOGSTORAGE_USE_GZIP @@ -1225,10 +1311,11 @@ TEST(t_dlt_logstorage_write_on_msg, null) TEST(t_dlt_logstorage_sync_on_msg, normal) { DltLogStorageFilterConfig config; + memset(&config, 0, sizeof(DltLogStorageFilterConfig)); DltLogStorageUserConfig file_config; + memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); char apids; char ctids; - memset(&config, 0, sizeof(DltLogStorageFilterConfig)); config.apids = &apids; config.ctids = &ctids; config.file_name = (char *)"Test"; @@ -1250,7 +1337,7 @@ TEST(t_dlt_logstorage_sync_on_msg, null) TEST(t_dlt_logstorage_prepare_msg_cache, normal) { DltLogStorageUserConfig file_config; - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 1; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 2; file_config.logfile_counteridxlen = 2; @@ -1272,6 +1359,10 @@ TEST(t_dlt_logstorage_prepare_msg_cache, normal) config.working_file_name = NULL; config.wrap_id = 0; g_logstorage_cache_max = 16; + newest_info.file_name = (char *)"Test"; + newest_info.newest_file = (char *)"Test_003_20200728_191132.dlt"; + newest_info.wrap_id = 0; + newest_info.next = NULL; EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_prepare_msg_cache(&config, &file_config, path, 1, &newest_info)); @@ -1622,10 +1713,8 @@ TEST(t_dlt_daemon_logstorage_write, normal) uconfig.offlineLogstorageMaxCounter = 5; uconfig.offlineLogstorageMaxCounterIdx = 1; uconfig.offlineLogstorageMaxDevices = 1; - unsigned char data1[] = "123"; - unsigned char data2[] = "123"; - unsigned char data3[] = "123"; - int size = 10 * sizeof(uint32_t); + unsigned char data[] = "123"; + int size = 3; daemon.storage_handle->connection_type = DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED; daemon.storage_handle->config_status = DLT_OFFLINE_LOGSTORAGE_CONFIG_DONE; daemon.storage_handle->config_list = NULL; @@ -1635,20 +1724,46 @@ TEST(t_dlt_daemon_logstorage_write, normal) value.ctids = ctid; value.ecuid = ecuid; value.file_name = file_name; - char key0[] = "1234:\000\000\000\000"; - char key1[] = ":5678\000\000\000\000"; - char key2[] = "1234:5678"; + char key0[] = ":1234:\000\000\000\000"; + char key1[] = "::5678\000\000\000\000"; + char key2[] = ":1234:5678"; int num_keys = 1; + DltMessage msg; + DltUserHeader userheader; + int log_level = 4; + dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG); + dlt_message_init(&msg, 0); + msg.storageheader = (DltStorageHeader *)msg.headerbuffer; + dlt_set_storageheader(msg.storageheader, ecuid); + msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); + msg.standardheader->htyp = DLT_HTYP_PROTOCOL_VERSION1|DLT_HTYP_UEH; + msg.standardheader->mcnt = 0; + dlt_message_set_extraparameters(&msg, 0); + msg.extendedheader = (DltExtendedHeader *)(msg.headerbuffer + + sizeof(DltStorageHeader) + + sizeof(DltStandardHeader) + + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)); + msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | + ((log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) | DLT_MSIN_VERB; + msg.extendedheader->noar = 1; + dlt_set_id(msg.extendedheader->apid, apid); + dlt_set_id(msg.extendedheader->ctid, ctid); + EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key0, num_keys, &value, &(daemon.storage_handle->config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key1, num_keys, &value, &(daemon.storage_handle->config_list))); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_list_add(key2, num_keys, &value, &(daemon.storage_handle->config_list))); - EXPECT_NO_THROW(dlt_daemon_logstorage_write(&daemon, &uconfig, data1, size, data2, size, data3, size)); + EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_logstorage_write(&daemon, &uconfig, + (unsigned char*)&(userheader), sizeof(DltUserHeader), + msg.headerbuffer + sizeof(DltStorageHeader), + msg.headersize - sizeof(DltStorageHeader), + data, size)); + dlt_message_free(&msg, 0); } TEST(t_dlt_daemon_logstorage_write, null) { - EXPECT_NO_THROW(dlt_daemon_logstorage_write(NULL, NULL, NULL, 0, NULL, 0, NULL, 0)); + EXPECT_EQ(-1, dlt_daemon_logstorage_write(NULL, NULL, NULL, 0, NULL, 0, NULL, 0)); } /* Begin Method: dlt_logstorage::t_dlt_daemon_logstorage_setup_internal_storage*/ @@ -1701,8 +1816,8 @@ TEST(t_dlt_daemon_logstorage_cleanup, normal) DltDaemonLocal daemon_local; daemon_local.flags.offlineLogstorageMaxDevices = 1; DltLogStorage storage_handle; + memset(&storage_handle, 0, sizeof(DltLogStorage)); daemon.storage_handle = &storage_handle; - daemon.storage_handle->config_status = 0; EXPECT_EQ(DLT_RETURN_OK, dlt_daemon_logstorage_cleanup(&daemon, &daemon_local, 0)); } @@ -1835,7 +1950,7 @@ TEST(t_dlt_logstorage_sync_to_file, normal) { DltLogStorageUserConfig file_config; memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); - file_config.logfile_timestamp = 191132; + file_config.logfile_timestamp = 0; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 6; file_config.logfile_counteridxlen = 2; @@ -1857,7 +1972,7 @@ TEST(t_dlt_logstorage_sync_to_file, normal) config.file_size = 50; g_logstorage_cache_max = 16; unsigned int size = 10; - unsigned char data1[10] = "dlt_data0"; + unsigned char data1[10] = {'a', 'b', 'D', 'L', 'T', 0x01 , 'c', 'd', 'e', 'f'}; unsigned char data2[10] = "dlt_data1"; unsigned char data3[10] = "dlt_data2"; newest_info.wrap_id = 0; @@ -1875,8 +1990,29 @@ TEST(t_dlt_logstorage_sync_to_file, normal) EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_sync_to_file(&config, &file_config, path, footer, footer->last_sync_offset, footer->offset)); + std::stringstream file_path; + file_path << path << "/" << config.working_file_name; + std::ifstream f(file_path.str()); + if (f.is_open()) + { + std::string line; + EXPECT_TRUE(std::getline(f, line)); + int idx = -2; + // First 2 characters should not appear + for (auto i=2; i < 10; i++) + EXPECT_TRUE(line[i+idx] == data1[i]); + idx += 10; + for (auto i=0; i < 10; i++) + EXPECT_TRUE(line[i+idx] == data2[i]); + idx += 10; + for (auto i=0; i < 10; i++) + EXPECT_TRUE(line[i+idx] == data3[i]); + f.close(); + } free(config.cache); config.cache = NULL; + std::string tmp_file = file_path.str(); + remove(tmp_file.c_str()); } } @@ -1891,7 +2027,6 @@ TEST(t_dlt_logstorage_sync_msg_cache, normal) { DltLogStorageUserConfig file_config; memset(&file_config, 0, sizeof(DltLogStorageUserConfig)); - file_config.logfile_timestamp = 191132; file_config.logfile_timestamp = 0; file_config.logfile_delimiter = { '_' }; file_config.logfile_maxcounter = 8; @@ -1916,7 +2051,7 @@ TEST(t_dlt_logstorage_sync_msg_cache, normal) g_logstorage_cache_max = 16; unsigned int size = 10; - unsigned char data1[10] = "dlt_dataA"; + unsigned char data1[10] = {'a', 'b', 'D', 'L', 'T', 0x01 , 'c', 'd', 'e', 'f'};; unsigned char data2[10] = "dlt_dataB"; unsigned char data3[10] = "dlt_dataC"; @@ -1927,8 +2062,29 @@ TEST(t_dlt_logstorage_sync_msg_cache, normal) EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_write_msg_cache(&config, &file_config, path, data1, size, data2, size, data3, size)); EXPECT_EQ(DLT_RETURN_OK, dlt_logstorage_sync_msg_cache(&config, &file_config, path, DLT_LOGSTORAGE_SYNC_ON_DEMAND)); + std::stringstream file_path; + file_path << path << "/" << config.working_file_name; + std::ifstream f(file_path.str()); + if (f.is_open()) + { + std::string line; + EXPECT_TRUE(std::getline(f, line)); + int idx = -2; + // First 2 characters should not appear + for (auto i=2; i < 10; i++) + EXPECT_TRUE(line[i+idx] == data1[i]); + idx += 10; + for (auto i=0; i < 10; i++) + EXPECT_TRUE(line[i+idx] == data2[i]); + idx += 10; + for (auto i=0; i < 10; i++) + EXPECT_TRUE(line[i+idx] == data3[i]); + f.close(); + } free(config.cache); config.cache = NULL; + std::string tmp_file = file_path.str(); + remove(tmp_file.c_str()); } } @@ -1986,7 +2142,7 @@ int main(int argc, char **argv) return -1; } - if (cpid) { + if (!cpid) { int i = GTEST_SOCKS_ACCEPTED; int j, optval = 1; char buffer[256]; diff --git a/tests/gtest_dlt_daemon_offline_log.sh b/tests/gtest_dlt_daemon_offline_log.sh index 704feb7ae..5e51f7ae9 100755 --- a/tests/gtest_dlt_daemon_offline_log.sh +++ b/tests/gtest_dlt_daemon_offline_log.sh @@ -23,6 +23,7 @@ cleanup() tmpPath=/tmp cd $tmpPath rm -rf $tmpPath/dlt_logstorage.conf + rm -rf $tmpPath/Test*.dlt return 0 }