summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Weber <37300320+danielweber2018@users.noreply.github.com>2023-03-10 15:31:48 +0100
committerGitHub <noreply@github.com>2023-03-10 15:31:48 +0100
commit363d433a5dac141020cef4f698f60644fe4a202c (patch)
tree6d21d2447309ca9e4a76fb3c70d36b216d1ef753 /src
parent3b8a82ffae22c51bb02c11e669754983e8aabd5a (diff)
downloadDLT-daemon-363d433a5dac141020cef4f698f60644fe4a202c.tar.gz
logfile: exhance internal dlt logging by introducing size limits (#369)
Enhance dlt logging such that multiple files are used as it is done for the offline traces. Add limit-specific config values for logging. For this purpose the pattern of index-based file names is used only. This approach of logging to multiple files and rotating in order to keep the limits ensures that dlt logs take care of available space on the underlying file system and do not grow infinitely. Signed-off-by: Daniel Weber <daniel.w.weber@daimler.com> Co-authored-by: Oleg Tropmann <oleg.tropmann@daimler.com>
Diffstat (limited to 'src')
-rw-r--r--src/console/dlt-convert.c11
-rw-r--r--src/daemon/CMakeLists.txt1
-rw-r--r--src/daemon/dlt-daemon.c52
-rw-r--r--src/daemon/dlt-daemon.h11
-rw-r--r--src/daemon/dlt.conf9
-rw-r--r--src/gateway/dlt_gateway.c3
-rw-r--r--src/lib/CMakeLists.txt1
-rw-r--r--src/shared/dlt_common.c156
-rw-r--r--src/shared/dlt_multiple_files.c499
-rw-r--r--src/shared/dlt_offline_trace.c397
10 files changed, 724 insertions, 416 deletions
diff --git a/src/console/dlt-convert.c b/src/console/dlt-convert.c
index b97a11f..8c72b60 100644
--- a/src/console/dlt-convert.c
+++ b/src/console/dlt-convert.c
@@ -126,17 +126,6 @@ void usage()
printf(" -t Handling input compressed files (tar.gz)\n");
}
-char *get_filename_ext(const char *filename)
-{
- if (filename == NULL)
- fprintf(stderr, "ERROR: %s: invalid arguments\n", __FUNCTION__);
-
- char *dot = strrchr(filename, '.');
- if(!dot || dot == filename)
- return "";
- return dot + 1;
-}
-
void empty_dir(const char *dir)
{
struct dirent **files = { 0 };
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index f7aaa26..9916bb4 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -32,6 +32,7 @@ set(dlt_daemon_SRCS
${PROJECT_SOURCE_DIR}/src/lib/dlt_client.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_common.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_config_file_parser.c
+ ${PROJECT_SOURCE_DIR}/src/shared/dlt_multiple_files.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_offline_trace.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_protocol.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_user_shared.c
diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c
index c8a8506..ee0f772 100644
--- a/src/daemon/dlt-daemon.c
+++ b/src/daemon/dlt-daemon.c
@@ -46,6 +46,8 @@
#endif
#include <sys/stat.h>
#include <sys/time.h>
+#include <libgen.h>
+
#if defined(linux) && defined(__NR_statx)
# include <linux/stat.h>
#endif
@@ -338,7 +340,7 @@ int option_file_parser(DltDaemonLocal *daemon_local)
daemon_local->flags.offlineTraceDirectory[0] = 0;
daemon_local->flags.offlineTraceFileSize = 1000000;
daemon_local->flags.offlineTraceMaxSize = 4000000;
- daemon_local->flags.offlineTraceFilenameTimestampBased = 1;
+ daemon_local->flags.offlineTraceFilenameTimestampBased = true;
daemon_local->flags.loggingMode = DLT_LOG_TO_CONSOLE;
daemon_local->flags.loggingLevel = LOG_INFO;
@@ -356,6 +358,9 @@ int option_file_parser(DltDaemonLocal *daemon_local)
dlt_vlog(LOG_WARNING, "%s: snprintf truncation/error(%ld) %s\n",
__func__, n, daemon_local->flags.loggingFilename);
}
+ daemon_local->flags.enableLoggingFileLimit = false;
+ daemon_local->flags.loggingFileSize = 250000;
+ daemon_local->flags.loggingFileMaxSize = 1000000;
daemon_local->timeoutOnSend = 4;
daemon_local->RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE;
@@ -514,7 +519,7 @@ int option_file_parser(DltDaemonLocal *daemon_local)
}
else if (strcmp(token, "LoggingMode") == 0)
{
- daemon_local->flags.loggingMode = atoi(value);
+ daemon_local->flags.loggingMode = (DltLoggingMode)atoi(value);
/*printf("Option: %s=%s\n",token,value); */
}
else if (strcmp(token, "LoggingLevel") == 0)
@@ -530,6 +535,18 @@ int option_file_parser(DltDaemonLocal *daemon_local)
daemon_local->flags.loggingFilename[sizeof(daemon_local->flags.loggingFilename) - 1] = 0;
/*printf("Option: %s=%s\n",token,value); */
}
+ else if (strcmp(token, "EnableLoggingFileLimit") == 0)
+ {
+ daemon_local->flags.enableLoggingFileLimit = (bool)atoi(value);
+ }
+ else if (strcmp(token, "LoggingFileSize") == 0)
+ {
+ daemon_local->flags.loggingFileSize = atoi(value);
+ }
+ else if (strcmp(token, "LoggingFileMaxSize") == 0)
+ {
+ daemon_local->flags.loggingFileMaxSize = atoi(value);
+ }
else if (strcmp(token, "TimeOutOnSend") == 0)
{
daemon_local->timeoutOnSend = atoi(value);
@@ -578,7 +595,7 @@ int option_file_parser(DltDaemonLocal *daemon_local)
}
else if (strcmp(token, "OfflineTraceFileNameTimestampBased") == 0)
{
- daemon_local->flags.offlineTraceFilenameTimestampBased = atoi(value);
+ daemon_local->flags.offlineTraceFilenameTimestampBased = (bool)atoi(value);
/*printf("Option: %s=%s\n",token,value); */
}
else if (strcmp(token, "SendECUSoftwareVersion") == 0)
@@ -941,7 +958,10 @@ int main(int argc, char *argv[])
dlt_log_set_filename(daemon_local.flags.loggingFilename);
dlt_log_set_level(daemon_local.flags.loggingLevel);
DltReturnValue log_init_result =
- dlt_log_init(daemon_local.flags.loggingMode);
+ dlt_log_init_multiple_logfiles_support(daemon_local.flags.loggingMode,
+ daemon_local.flags.enableLoggingFileLimit,
+ daemon_local.flags.loggingFileSize,
+ daemon_local.flags.loggingFileMaxSize);
if (log_init_result != DLT_RETURN_OK) {
fprintf(stderr, "Failed to init internal logging\n");
@@ -1126,6 +1146,8 @@ int main(int argc, char *argv[])
dlt_log(LOG_NOTICE, "Leaving DLT daemon\n");
+ dlt_log_free();
+
return 0;
} /* main() */
@@ -1171,7 +1193,12 @@ int dlt_daemon_local_init_p1(DltDaemon *daemon, DltDaemonLocal *daemon_local, in
/* Re-Initialize internal logging facility after fork */
dlt_log_set_filename(daemon_local->flags.loggingFilename);
dlt_log_set_level(daemon_local->flags.loggingLevel);
- dlt_log_init(daemon_local->flags.loggingMode);
+ // 'free' dlt logging and corresponding file handle before re-initializing
+ dlt_log_free();
+ dlt_log_init_multiple_logfiles_support(daemon_local->flags.loggingMode,
+ daemon_local->flags.enableLoggingFileLimit,
+ daemon_local->flags.loggingFileSize,
+ daemon_local->flags.loggingFileMaxSize);
/* initialise structure to use DLT file */
ret = dlt_file_init(&(daemon_local->file), daemon_local->flags.vflag);
@@ -1218,11 +1245,14 @@ int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, in
/* init offline trace */
if (((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) &&
daemon_local->flags.offlineTraceDirectory[0]) {
- if (dlt_offline_trace_init(&(daemon_local->offlineTrace),
- daemon_local->flags.offlineTraceDirectory,
- daemon_local->flags.offlineTraceFileSize,
- daemon_local->flags.offlineTraceMaxSize,
- daemon_local->flags.offlineTraceFilenameTimestampBased) == -1) {
+ if (multiple_files_buffer_init(&(daemon_local->offlineTrace),
+ daemon_local->flags.offlineTraceDirectory,
+ daemon_local->flags.offlineTraceFileSize,
+ daemon_local->flags.offlineTraceMaxSize,
+ daemon_local->flags.offlineTraceFilenameTimestampBased,
+ false,
+ DLT_OFFLINETRACE_FILENAME_BASE,
+ DLT_OFFLINETRACE_FILENAME_EXT) == -1) {
dlt_log(LOG_ERR, "Could not initialize offline trace\n");
return -1;
}
@@ -1786,7 +1816,7 @@ void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, i
/* free shared memory */
if (daemon_local->flags.offlineTraceDirectory[0])
- dlt_offline_trace_free(&(daemon_local->offlineTrace));
+ multiple_files_buffer_free(&(daemon_local->offlineTrace));
/* Ignore result */
dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag);
diff --git a/src/daemon/dlt-daemon.h b/src/daemon/dlt-daemon.h
index 071562f..cc879cb 100644
--- a/src/daemon/dlt-daemon.h
+++ b/src/daemon/dlt-daemon.h
@@ -69,6 +69,7 @@
#include <limits.h> /* for NAME_MAX */
#include <sys/time.h>
+#include <stdarg.h>
#include "dlt_daemon_common.h"
#include "dlt_user_shared.h"
@@ -103,10 +104,13 @@ typedef struct
char offlineTraceDirectory[DLT_DAEMON_FLAG_MAX]; /**< (String: Directory) Store DLT messages to local directory (Default: /etc/dlt.conf) */
int offlineTraceFileSize; /**< (int) Maximum size in bytes of one trace file (Default: 1000000) */
int offlineTraceMaxSize; /**< (int) Maximum size of all trace files (Default: 4000000) */
- int offlineTraceFilenameTimestampBased; /**< (int) timestamp based or index based (Default: 1 Timestamp based) */
- int loggingMode; /**< (int) The logging console for internal logging of dlt-daemon (Default: 0) */
+ bool offlineTraceFilenameTimestampBased; /**< (Boolean) timestamp based or index based (Default: true=Timestamp based) */
+ DltLoggingMode loggingMode; /**< (int) The logging console for internal logging of dlt-daemon (Default: 0) */
int loggingLevel; /**< (int) The logging level for internal logging of dlt-daemon (Default: 6) */
char loggingFilename[DLT_DAEMON_FLAG_MAX]; /**< (String: Filename) The logging filename if internal logging mode is log to file (Default: /tmp/log) */
+ bool enableLoggingFileLimit; /**< (Boolean) Indicate whether size of logging file(s) is limited (Default: false) */
+ int loggingFileSize; /**< (int) Maximum size in bytes of one logging file (Default: 250000) */
+ int loggingFileMaxSize; /**< (int) Maximum size in bytes of all logging files (Default: 1000000) */
int sendECUSoftwareVersion; /**< (Boolean) Send ECU software version perdiodically */
char pathToECUSoftwareVersion[DLT_DAEMON_FLAG_MAX]; /**< (String: Filename) The file from which to read the ECU version from. */
int sendTimezone; /**< (Boolean) Send Timezone perdiodically */
@@ -154,7 +158,8 @@ typedef struct
DltShm dlt_shm; /**< Shared memory handling */
unsigned char *recv_buf_shm; /**< buffer for receive message from shm */
#endif
- DltOfflineTrace offlineTrace; /**< Offline trace handling */
+ MultipleFilesRingBuffer offlineTrace; /**< Offline trace handling */
+ MultipleFilesRingBuffer dltLogging; /**< Dlt logging handling */
int timeoutOnSend;
unsigned long RingbufferMinSize;
unsigned long RingbufferMaxSize;
diff --git a/src/daemon/dlt.conf b/src/daemon/dlt.conf
index 777aa82..11a5057 100644
--- a/src/daemon/dlt.conf
+++ b/src/daemon/dlt.conf
@@ -50,6 +50,15 @@ LoggingLevel = 6
# if WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK is set as compile flag
LoggingFilename = /tmp/dlt.log
+# Indicate whether size of logging file(s) is limited (Default: 0)
+EnableLoggingFileLimit = 0
+
+# Maximum size in bytes of one logging file (Default: 250000)
+# LoggingFileSize = 250000
+
+# Maximum size in bytes of all logging files (Default: 1000000)
+# LoggingFileMaxSize = 1000000
+
# Timeout on send to client (sec)
TimeOutOnSend = 4
diff --git a/src/gateway/dlt_gateway.c b/src/gateway/dlt_gateway.c
index 2b4f070..3d832ce 100644
--- a/src/gateway/dlt_gateway.c
+++ b/src/gateway/dlt_gateway.c
@@ -669,6 +669,9 @@ int dlt_gateway_configure(DltGateway *gateway, char *config_file, int verbose)
/* read configuration file */
file = dlt_config_file_init(config_file);
+ if(file == NULL) {
+ return DLT_RETURN_ERROR;
+ }
/* get number of entries and allocate memory to store information */
ret = dlt_config_file_get_num_sections(file, &num_sections);
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 3293376..e6d6334 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -19,6 +19,7 @@ set(dlt_LIB_SRCS
dlt_filetransfer.c
dlt_env_ll.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_common.c
+ ${PROJECT_SOURCE_DIR}/src/shared/dlt_multiple_files.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_protocol.c
${PROJECT_SOURCE_DIR}/src/shared/dlt_user_shared.c
)
diff --git a/src/shared/dlt_common.c b/src/shared/dlt_common.c
index 97766f7..cbbe99a 100644
--- a/src/shared/dlt_common.c
+++ b/src/shared/dlt_common.c
@@ -31,6 +31,7 @@
#include <time.h> /* for localtime_r(), strftime() */
#include <limits.h> /* for NAME_MAX */
#include <inttypes.h> /* for PRI formatting macro */
+#include <libgen.h> /* dirname */
#include <stdarg.h>
#include <err.h>
@@ -41,6 +42,7 @@
#include "dlt_user_shared.h"
#include "dlt_common.h"
#include "dlt_common_cfg.h"
+#include "dlt_multiple_files.h"
#include "dlt_version.h"
@@ -84,6 +86,17 @@ static bool print_with_attributes = false;
int logging_mode = DLT_LOG_TO_STDERR;
FILE *logging_handle = NULL;
+//use ohandle as an indicator that multiple files logging is active
+MultipleFilesRingBuffer multiple_files_ring_buffer = {
+ .directory={0},
+ .filename={0},
+ .fileSize=0,
+ .maxSize=0,
+ .filenameTimestampBased=false,
+ .filenameBase={0},
+ .filenameExt={0},
+ .ohandle=-1};
+
char *message_type[] = { "log", "app_trace", "nw_trace", "control", "", "", "", "" };
char *log_info[] = { "", "fatal", "error", "warn", "info", "debug", "verbose", "", "", "", "", "", "", "", "", "" };
char *trace_type[] = { "", "variable", "func_in", "func_out", "state", "vfb", "", "", "", "", "", "", "", "", "", "" };
@@ -1816,34 +1829,114 @@ void dlt_print_with_attributes(bool state)
DltReturnValue dlt_log_init(int mode)
{
+ return dlt_log_init_multiple_logfiles_support((DltLoggingMode)mode, false, 0, 0);
+}
+
+DltReturnValue dlt_log_init_multiple_logfiles_support(const DltLoggingMode mode, const bool enable_multiple_logfiles,
+ const int logging_file_size, const int logging_files_max_size)
+{
if ((mode < DLT_LOG_TO_CONSOLE) || (mode > DLT_LOG_DROPPED)) {
- dlt_user_printf("Wrong parameter for mode: %d\n", mode);
+ dlt_vlog(LOG_WARNING, "Wrong parameter for mode: %d\n", mode);
return DLT_RETURN_WRONG_PARAMETER;
}
logging_mode = mode;
- if (logging_mode == DLT_LOG_TO_FILE) {
- /* internal logging to file */
- logging_handle = fopen(logging_filename, "a");
+ if (logging_mode != DLT_LOG_TO_FILE) {
+ return DLT_RETURN_OK;
+ }
- if (logging_handle == NULL) {
- dlt_user_printf("Internal log file %s cannot be opened!\n", logging_filename);
- return DLT_RETURN_ERROR;
+ if (enable_multiple_logfiles) {
+ dlt_user_printf("configure dlt logging using file limits\n");
+ int result = dlt_log_init_multiple_logfiles(logging_file_size, logging_files_max_size);
+ if (result == DLT_RETURN_OK) {
+ return DLT_RETURN_OK;
}
+ dlt_user_printf("dlt logging for limits fails with error code=%d, use logging without limits as fallback\n", result);
+ return dlt_log_init_single_logfile();
+ } else {
+ dlt_user_printf("configure dlt logging without file limits\n");
+ return dlt_log_init_single_logfile();
}
+}
+DltReturnValue dlt_log_init_single_logfile()
+{
+ /* internal logging to file */
+ errno = 0;
+ logging_handle = fopen(logging_filename, "a");
+
+ if (logging_handle == NULL) {
+ dlt_user_printf("Internal log file %s cannot be opened, error: %s\n", logging_filename, strerror(errno));
+ return DLT_RETURN_ERROR;
+ }
return DLT_RETURN_OK;
}
+DltReturnValue dlt_log_init_multiple_logfiles(const int logging_file_size, const int logging_files_max_size)
+{
+ char path_logging_filename[PATH_MAX + 1];
+ strncpy(path_logging_filename, logging_filename, PATH_MAX);
+ path_logging_filename[PATH_MAX] = 0;
+
+ const char *directory = dirname(path_logging_filename);
+ if (directory[0]) {
+ char basename_logging_filename[NAME_MAX + 1];
+ strncpy(basename_logging_filename, logging_filename, NAME_MAX);
+ basename_logging_filename[NAME_MAX] = 0;
+
+ const char *file_name = basename(basename_logging_filename);
+ char filename_base[NAME_MAX];
+ if (!dlt_extract_base_name_without_ext(file_name, filename_base, sizeof(filename_base))) return DLT_RETURN_ERROR;
+
+ const char *filename_ext = get_filename_ext(file_name);
+ if (!filename_ext) return DLT_RETURN_ERROR;
+
+ DltReturnValue result = multiple_files_buffer_init(
+ &multiple_files_ring_buffer,
+ directory,
+ logging_file_size,
+ logging_files_max_size,
+ false,
+ true,
+ filename_base,
+ filename_ext);
+
+ return result;
+ }
+
+ return DLT_RETURN_ERROR;
+}
+
void dlt_log_free(void)
{
- if (logging_mode == DLT_LOG_TO_FILE && logging_handle)
+ if (logging_mode == DLT_LOG_TO_FILE) {
+ if (dlt_is_log_in_multiple_files_active()) {
+ dlt_log_free_multiple_logfiles();
+ } else {
+ dlt_log_free_single_logfile();
+ }
+ }
+}
+
+void dlt_log_free_single_logfile()
+{
+ if (logging_handle)
fclose(logging_handle);
}
+void dlt_log_free_multiple_logfiles()
+{
+ if (DLT_RETURN_ERROR == multiple_files_buffer_free(&multiple_files_ring_buffer)) return;
+
+ // reset indicator of multiple files usage
+ multiple_files_ring_buffer.ohandle = -1;
+}
+
int dlt_user_printf(const char *format, ...)
{
+ if (format == NULL) return -1;
+
va_list args;
va_start(args, format);
@@ -1922,9 +2015,13 @@ DltReturnValue dlt_log(int prio, char *s)
#endif
break;
case DLT_LOG_TO_FILE:
-
/* log to file */
- if (logging_handle) {
+
+ if (dlt_is_log_in_multiple_files_active()) {
+ dlt_log_multiple_files_write(sFormatString, (unsigned int)sTimeSpec.tv_sec,
+ (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s);
+ }
+ else if (logging_handle) {
fprintf(logging_handle, sFormatString, (unsigned int)sTimeSpec.tv_sec,
(unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s);
fflush(logging_handle);
@@ -4308,3 +4405,42 @@ int dlt_execute_command(char *filename, char *command, ...)
free(args);
return ret;
}
+
+char *get_filename_ext(const char *filename)
+{
+ if (filename == NULL) {
+ fprintf(stderr, "ERROR: %s: invalid arguments\n", __FUNCTION__);
+ return NULL;
+ }
+
+ char *dot = strrchr(filename, '.');
+ return (!dot || dot == filename) ? NULL : dot;
+}
+
+bool dlt_extract_base_name_without_ext(const char* const abs_file_name, char* base_name, long base_name_len) {
+ if (abs_file_name == NULL || base_name == NULL) return false;
+
+ const char* last_separator = strrchr(abs_file_name, '.');
+ if (!last_separator) return false;
+ long length = last_separator - abs_file_name;
+ length = length > base_name_len ? base_name_len : length;
+
+ strncpy(base_name, abs_file_name, length);
+ base_name[length] = '\0';
+ return true;
+}
+
+void dlt_log_multiple_files_write(const char* format, ...)
+{
+ char output_string[2048] = { 0 };
+ va_list args;
+ va_start (args, format);
+ vsnprintf(output_string, 2047, format, args);
+ va_end (args);
+ multiple_files_buffer_write(&multiple_files_ring_buffer, (unsigned char*)output_string, strlen(output_string));
+}
+
+bool dlt_is_log_in_multiple_files_active()
+{
+ return multiple_files_ring_buffer.ohandle > -1;
+}
diff --git a/src/shared/dlt_multiple_files.c b/src/shared/dlt_multiple_files.c
new file mode 100644
index 0000000..754fd1e
--- /dev/null
+++ b/src/shared/dlt_multiple_files.c
@@ -0,0 +1,499 @@
+/*
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2022, Daimler TSS GmbH
+ *
+ * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+ *
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License (MPL), v. 2.0.
+ * If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * For further information see https://www.covesa.global/.
+ */
+
+/*!
+ * \author
+ * Oleg Tropmann <oleg.tropmann@daimler.com>
+ * Daniel Weber <daniel.w.weber@daimler.com>
+ *
+ * \copyright Copyright © 2022 Daimler TSS GmbH. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt_daemon_log.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <syslog.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include <dlt_multiple_files.h>
+#include "dlt_common.h"
+
+unsigned int multiple_files_buffer_storage_dir_info(const char *path, const char *file_name,
+ char *newest, char *oldest)
+{
+ int i = 0;
+ unsigned int num_log_files = 0;
+ struct dirent **files = { 0 };
+ char *tmp_old = NULL;
+ char *tmp_new = NULL;
+
+ if ((path == NULL) || (file_name == NULL) || (newest == NULL) || (oldest == NULL)) {
+ fprintf(stderr, "multiple_files_buffer_storage_dir_info: Invalid parameter(s)");
+ return 0;
+ }
+
+ const int file_cnt = scandir(path, &files, NULL, alphasort);
+ if (file_cnt <= 0) return 0;
+
+ for (i = 0; i < file_cnt; i++) {
+ int len = 0;
+ len = strlen(file_name);
+
+ if ((strncmp(files[i]->d_name, file_name, len) == 0) &&
+ (files[i]->d_name[len] == MULTIPLE_FILES_FILENAME_INDEX_DELIM[0])) {
+ num_log_files++;
+
+ if ((tmp_old == NULL) || (strlen(tmp_old) >= strlen(files[i]->d_name))) {
+ if (tmp_old == NULL) {
+ tmp_old = files[i]->d_name;
+ } else if (strlen(tmp_old) > strlen(files[i]->d_name)) {
+ /* when file name is smaller, it is older */
+ tmp_old = files[i]->d_name;
+ } else if (strcmp(tmp_old, files[i]->d_name) > 0) {
+ /* filename length is equal, do a string compare */
+ tmp_old = files[i]->d_name;
+ }
+ }
+
+ if ((tmp_new == NULL) || (strlen(tmp_new) <= strlen(files[i]->d_name))) {
+ if (tmp_new == NULL) {
+ tmp_new = files[i]->d_name;
+ } else if (strlen(tmp_new) < strlen(files[i]->d_name)) {
+ /* when file name is longer, it is younger */
+ tmp_new = files[i]->d_name;
+ } else if (strcmp(tmp_new, files[i]->d_name) < 0) {
+ tmp_new = files[i]->d_name;
+ }
+ }
+ }
+ }
+
+ if (num_log_files > 0) {
+ if ((tmp_old != NULL) && (strlen(tmp_old) < NAME_MAX)) {
+ strncpy(oldest, tmp_old, NAME_MAX);
+ oldest[NAME_MAX] = '\0';
+ } else if ((tmp_old != NULL) && (strlen(tmp_old) >= NAME_MAX)) {
+ printf("length mismatch of file %s\n", tmp_old);
+ }
+
+ if ((tmp_new != NULL) && (strlen(tmp_new) < NAME_MAX)) {
+ strncpy(newest, tmp_new, NAME_MAX);
+ oldest[NAME_MAX] = '\0';
+ } else if ((tmp_new != NULL) && (strlen(tmp_new) >= NAME_MAX)) {
+ printf("length mismatch of file %s\n", tmp_new);
+ }
+ }
+
+ /* free scandir result */
+ for (i = 0; i < file_cnt; i++) free(files[i]);
+
+ free(files);
+
+ return num_log_files;
+}
+
+void multiple_files_buffer_file_name(MultipleFilesRingBuffer *files_buffer, const size_t length, const unsigned int idx)
+{
+ char file_index[11]; /* UINT_MAX = 4294967295 -> 10 digits */
+ snprintf(file_index, sizeof(file_index), "%010u", idx);
+
+ /* create log file name */
+ char* file_name = files_buffer->filename;
+ memset(file_name, 0, length * sizeof(char));
+
+ const size_t size = length - strlen(file_name) - 1;
+ strncat(file_name, files_buffer->filenameBase, size);
+ strncat(file_name, MULTIPLE_FILES_FILENAME_INDEX_DELIM, size);
+ strncat(file_name, file_index, size);
+ strncat(file_name, files_buffer->filenameExt, size);
+}
+
+unsigned int multiple_files_buffer_get_idx_of_log_file(char *file)
+{
+ if ((file == NULL) || (file[0] == '\0')) return 0;
+
+ const char d[2] = MULTIPLE_FILES_FILENAME_INDEX_DELIM;
+ char *token;
+
+ token = strtok(file, d);
+ /* we are interested in 2. token because of log file name */
+ token = strtok(NULL, d);
+
+ return token != NULL ? strtol(token, NULL, 10) : 0;
+}
+
+DltReturnValue multiple_files_buffer_create_new_file(MultipleFilesRingBuffer *files_buffer)
+{
+ if (files_buffer == NULL) {
+ fprintf(stderr, "multiple files buffer not set\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ time_t t;
+ struct tm tmp;
+ char file_path[PATH_MAX + 1];
+ unsigned int idx = 0;
+ int ret = 0;
+
+ /* set filename */
+ if (files_buffer->filenameTimestampBased) {
+ /* timestamp format: "yyyymmdd_hhmmss" */
+ char timestamp[16];
+ t = time(NULL);
+ tzset();
+ localtime_r(&t, &tmp);
+
+ strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", &tmp);
+
+ ret = snprintf(files_buffer->filename, sizeof(files_buffer->filename), "%s%s%s%s",
+ files_buffer->filenameBase,
+ MULTIPLE_FILES_FILENAME_TIMESTAMP_DELIM, timestamp,
+ files_buffer->filenameExt);
+
+ if ((ret < 0) || ((size_t)ret >= (int)sizeof(files_buffer->filename))) {
+ fprintf(stderr, "filename cannot be concatenated\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ ret = snprintf(file_path, sizeof(file_path), "%s/%s",
+ files_buffer->directory, files_buffer->filename);
+
+ if ((ret < 0) || ((size_t)ret >= (int)sizeof(file_path))) {
+ fprintf(stderr, "file path cannot be concatenated\n");
+ return DLT_RETURN_ERROR;
+ }
+ }
+ else {
+ char newest[NAME_MAX + 1] = { 0 };
+ char oldest[NAME_MAX + 1] = { 0 };
+ /* targeting newest file, ignoring number of files in dir returned */
+ if (0 == multiple_files_buffer_storage_dir_info(files_buffer->directory,
+ files_buffer->filenameBase,
+ newest,
+ oldest)) {
+ printf("No multiple files found\n");
+ }
+
+ idx = multiple_files_buffer_get_idx_of_log_file(newest) + 1;
+
+ multiple_files_buffer_file_name(files_buffer, sizeof(files_buffer->filename), idx);
+ ret = snprintf(file_path, sizeof(file_path), "%s/%s",
+ files_buffer->directory, files_buffer->filename);
+
+ if ((ret < 0) || (ret >= NAME_MAX)) {
+ fprintf(stderr, "filename cannot be concatenated\n");
+ return DLT_RETURN_ERROR;
+ }
+ }
+
+ /* open DLT output file */
+ errno = 0;
+ files_buffer->ohandle = open(file_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IROTH); /* mode: wb */
+
+ if (files_buffer->ohandle == -1) {
+ /* file cannot be opened */
+ fprintf(stderr, "file %s cannot be created, error: %s\n", file_path, strerror(errno));
+ return DLT_RETURN_ERROR;
+ }
+
+ return DLT_RETURN_OK;
+}
+
+ssize_t multiple_files_buffer_get_total_size(const MultipleFilesRingBuffer *files_buffer)
+{
+ if (files_buffer == NULL) {
+ fprintf(stderr, "multiple files buffer not set\n");
+ return -1;
+ }
+
+ struct dirent *dp;
+ char filename[PATH_MAX + 1];
+ ssize_t size = 0;
+ struct stat status;
+
+ /* go through all dlt files in directory */
+ DIR *dir = opendir(files_buffer->directory);
+ if (!dir) {
+ fprintf(stderr, "directory %s cannot be opened, error=%s\n", files_buffer->directory, strerror(errno));
+ return -1;
+ }
+
+ while ((dp = readdir(dir)) != NULL) {
+ // consider files matching with a specific base name and a particular extension
+ if (strstr(dp->d_name, files_buffer->filenameBase) && strstr(dp->d_name, files_buffer->filenameExt)) {
+ int res = snprintf(filename, sizeof(filename), "%s/%s", files_buffer->directory, dp->d_name);
+
+ /* if the total length of the string is greater than the buffer, silently forget it. */
+ /* snprintf: a return value of size or more means that the output was truncated */
+ /* if an output error is encountered, a negative value is returned. */
+ if (((unsigned int)res < sizeof(filename)) && (res > 0)) {
+ errno = 0;
+ if (0 == stat(filename, &status))
+ size += status.st_size;
+ else
+ fprintf(stderr, "file %s cannot be stat-ed, error=%s\n", filename, strerror(errno));
+ }
+ }
+ }
+
+ closedir(dir);
+
+ /* return size */
+ return size;
+}
+
+int multiple_files_buffer_delete_oldest_file(MultipleFilesRingBuffer *files_buffer)
+{
+ if (files_buffer == NULL) {
+ fprintf(stderr, "multiple files buffer not set\n");
+ return -1; /* ERROR */
+ }
+
+ struct dirent *dp;
+ char filename[PATH_MAX + 1];
+ char filename_oldest[PATH_MAX + 1];
+ unsigned long size_oldest = 0;
+ struct stat status;
+ time_t time_oldest = 0;
+ int index_oldest = INT_MAX;
+
+ filename[0] = 0;
+ filename_oldest[0] = 0;
+
+ /* go through all dlt files in directory */
+ DIR *dir = opendir(files_buffer->directory);
+
+ if(!dir)
+ return -1;
+
+ while ((dp = readdir(dir)) != NULL) {
+ if (strstr(dp->d_name, files_buffer->filenameBase) && strstr(dp->d_name, files_buffer->filenameExt)) {
+ int res = snprintf(filename, sizeof(filename), "%s/%s", files_buffer->directory, dp->d_name);
+
+ /* if the total length of the string is greater than the buffer, silently forget it. */
+ /* snprintf: a return value of size or more means that the output was truncated */
+ /* if an output error is encountered, a negative value is returned. */
+ if (((unsigned int) res >= sizeof(filename)) || (res <= 0)) {
+ printf("Filename for delete oldest too long. Skip file.\n");
+ continue;
+ }
+
+ if (files_buffer->filenameTimestampBased) {
+ errno = 0;
+ if (0 == stat(filename, &status)) {
+ if ((time_oldest == 0) || (status.st_mtime < time_oldest)) {
+ time_oldest = status.st_mtime;
+ size_oldest = status.st_size;
+ strncpy(filename_oldest, filename, PATH_MAX);
+ filename_oldest[PATH_MAX] = 0;
+ }
+ } else {
+ printf("Old file %s cannot be stat-ed, error=%s\n", filename, strerror(errno));
+ }
+ } else {
+ //index based
+ const int index = multiple_files_buffer_get_idx_of_log_file(filename);
+ if (index < index_oldest) {
+ index_oldest = index;
+ snprintf(filename, sizeof(filename), "%s/%s", files_buffer->directory, dp->d_name);
+ strncpy(filename_oldest, filename, PATH_MAX);
+ filename_oldest[PATH_MAX] = 0;
+ }
+ }
+ }
+ }
+
+ closedir(dir);
+
+ /* delete file */
+ if (filename_oldest[0]) {
+ if (remove(filename_oldest)) {
+ fprintf(stderr, "Remove file %s failed! error=%s\n", filename_oldest, strerror(errno));
+ return -1; /* ERROR */
+ }
+ } else {
+ fprintf(stderr, "No file to be removed!\n");
+ return -1; /* ERROR */
+ }
+
+ /* return size of deleted file*/
+ return size_oldest;
+}
+
+DltReturnValue multiple_files_buffer_check_size(MultipleFilesRingBuffer *files_buffer)
+{
+ if (files_buffer == NULL) {
+ fprintf(stderr, "multiple files buffer not set\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ struct stat status;
+
+ /* check for existence of buffer files directory */
+ errno = 0;
+ if (stat(files_buffer->directory, &status) == -1) {
+ fprintf(stderr, "Buffer files directory: %s doesn't exist, error=%s\n", files_buffer->directory, strerror(errno));
+ return DLT_RETURN_ERROR;
+ }
+ /* check for accessibility of buffer files directory */
+ else if (access(files_buffer->directory, W_OK) != 0) {
+ fprintf(stderr, "Buffer files directory: %s doesn't have the write access \n", files_buffer->directory);
+ return DLT_RETURN_ERROR;
+ }
+
+ ssize_t total_size = 0;
+ /* check size of complete buffer file */
+ while ((total_size = multiple_files_buffer_get_total_size(files_buffer)) > (files_buffer->maxSize - files_buffer->fileSize)) {
+ /* remove the oldest files as long as new file will not fit in completely into complete multiple files buffer */
+ if (multiple_files_buffer_delete_oldest_file(files_buffer) < 0) return DLT_RETURN_ERROR;
+ }
+
+ return total_size == -1 ? DLT_RETURN_ERROR : DLT_RETURN_OK;
+}
+
+DltReturnValue multiple_files_buffer_open_file_for_append(MultipleFilesRingBuffer *files_buffer) {
+ if (files_buffer == NULL || files_buffer->filenameTimestampBased) return DLT_RETURN_ERROR;
+
+ char newest[NAME_MAX + 1] = {0};
+ char oldest[NAME_MAX + 1] = {0};
+ /* targeting the newest file, ignoring number of files in dir returned */
+
+ if (0 == multiple_files_buffer_storage_dir_info(files_buffer->directory,
+ files_buffer->filenameBase, newest, oldest) ) {
+ // no file for appending found. Create a new one
+ printf("No multiple files for appending found. Create a new one\n");
+ return multiple_files_buffer_create_new_file(files_buffer);
+ }
+
+ char file_path[PATH_MAX + 1];
+ int ret = snprintf(file_path, sizeof(file_path), "%s/%s",
+ files_buffer->directory, newest);
+
+ if ((ret < 0) || (ret >= NAME_MAX)) {
+ fprintf(stderr, "filename cannot be concatenated\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ /* open DLT output file */
+ errno = 0;
+ files_buffer->ohandle = open(file_path, O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IROTH); /* mode: wb */
+
+ return files_buffer->ohandle == -1 ? DLT_RETURN_ERROR : DLT_RETURN_OK;
+}
+
+DltReturnValue multiple_files_buffer_init(MultipleFilesRingBuffer *files_buffer,
+ const char *directory,
+ const int file_size,
+ const int max_size,
+ const bool filename_timestamp_based,
+ const bool append,
+ const char *filename_base,
+ const char *filename_ext)
+{
+ if (files_buffer == NULL) {
+ fprintf(stderr, "multiple files buffer not set\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ /* init parameters */
+ strncpy(files_buffer->directory, directory, NAME_MAX);
+ files_buffer->directory[NAME_MAX] = 0;
+ files_buffer->fileSize = file_size;
+ files_buffer->maxSize = max_size;
+ files_buffer->filenameTimestampBased = filename_timestamp_based;
+ strncpy(files_buffer->filenameBase, filename_base, NAME_MAX);
+ files_buffer->filenameBase[NAME_MAX] = 0;
+ strncpy(files_buffer->filenameExt, filename_ext, NAME_MAX);
+ files_buffer->filenameExt[NAME_MAX] = 0;
+
+ if (DLT_RETURN_ERROR == multiple_files_buffer_check_size(files_buffer)) return DLT_RETURN_ERROR;
+
+ return (!files_buffer->filenameTimestampBased && append)
+ ? multiple_files_buffer_open_file_for_append(files_buffer)
+ : multiple_files_buffer_create_new_file(files_buffer);
+}
+
+void multiple_files_buffer_rotate_file(MultipleFilesRingBuffer *files_buffer, const int size)
+{
+ /* check file size here */
+ if ((lseek(files_buffer->ohandle, 0, SEEK_CUR) + size) < files_buffer->fileSize) return;
+
+ /* close old file */
+ close(files_buffer->ohandle);
+ files_buffer->ohandle = -1;
+
+ /* check complete files size, remove old logs if needed */
+ if (DLT_RETURN_ERROR == multiple_files_buffer_check_size(files_buffer)) return;
+
+ /* create new file */
+ multiple_files_buffer_create_new_file(files_buffer);
+}
+
+DltReturnValue multiple_files_buffer_write_chunk(const MultipleFilesRingBuffer *files_buffer,
+ const unsigned char *data,
+ const int size)
+{
+ if (files_buffer == NULL) {
+ fprintf(stderr, "multiple files buffer not set\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if (data && (files_buffer->ohandle >= 0)) {
+ if (write(files_buffer->ohandle, data, size) != size) {
+ fprintf(stderr, "file write failed!\n");
+ return DLT_RETURN_ERROR;
+ }
+ }
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue multiple_files_buffer_write(MultipleFilesRingBuffer *files_buffer,
+ const unsigned char *data,
+ const int size)
+{
+ if (files_buffer->ohandle < 0) return DLT_RETURN_ERROR;
+
+ multiple_files_buffer_rotate_file(files_buffer, size);
+
+ /* write data into log file */
+ return multiple_files_buffer_write_chunk(files_buffer, data, size);
+}
+
+DltReturnValue multiple_files_buffer_free(const MultipleFilesRingBuffer *files_buffer)
+{
+ if (files_buffer == NULL) {
+ fprintf(stderr, "multiple files buffer not set\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if (files_buffer->ohandle < 0) return DLT_RETURN_ERROR;
+
+ /* close last used log file */
+ close(files_buffer->ohandle);
+
+ return DLT_RETURN_OK;
+}
diff --git a/src/shared/dlt_offline_trace.c b/src/shared/dlt_offline_trace.c
index 2b1e0df..b8b9a85 100644
--- a/src/shared/dlt_offline_trace.c
+++ b/src/shared/dlt_offline_trace.c
@@ -61,393 +61,28 @@
#include <unistd.h>
#include <dirent.h>
#include <syslog.h>
+#include <errno.h>
#include <dlt_offline_trace.h>
-#include "dlt_common.h"
-
-unsigned int dlt_offline_trace_storage_dir_info(char *path, char *file_name, char *newest, char *oldest)
-{
- int i = 0;
- unsigned int num = 0;
- int cnt = 0;
- struct dirent **files = { 0 };
- char *tmp_old = NULL;
- char *tmp_new = NULL;
-
- if ((path == NULL) || (file_name == NULL) || (newest == NULL) || (oldest == NULL)) {
- printf("dlt_offline_trace_storage_dir_info: Invalid parameter(s)");
- return 0;
- }
-
- cnt = scandir(path, &files, NULL, alphasort);
-
- if (cnt < 0)
- return 0;
-
- for (i = 0; i < cnt; i++) {
- int len = 0;
- len = strlen(file_name);
-
- if ((strncmp(files[i]->d_name, file_name, len) == 0) &&
- (files[i]->d_name[len] == DLT_OFFLINETRACE_FILENAME_INDEX_DELI[0])) {
- num++;
-
- if ((tmp_old == NULL) || (strlen(tmp_old) >= strlen(files[i]->d_name))) {
- if (tmp_old == NULL)
- tmp_old = files[i]->d_name;
- /* when file name is smaller, it is older */
- else if (strlen(tmp_old) > strlen(files[i]->d_name))
- tmp_old = files[i]->d_name;
- else /* filename is equal, do a string compare */
- if (strcmp(tmp_old, files[i]->d_name) > 0)
- tmp_old = files[i]->d_name;
- }
-
- if ((tmp_new == NULL) || (strlen(tmp_new) <= strlen(files[i]->d_name))) {
- if (tmp_new == NULL)
- tmp_new = files[i]->d_name;
- /* when file name is longer, it is younger */
- else if (strlen(tmp_new) < strlen(files[i]->d_name))
- tmp_new = files[i]->d_name;
- else if (strcmp(tmp_new, files[i]->d_name) < 0)
- tmp_new = files[i]->d_name;
- }
- }
- }
-
- if (num > 0) {
- if ((tmp_old != NULL) && (strlen(tmp_old) < NAME_MAX)) {
- strncpy(oldest, tmp_old, NAME_MAX);
- oldest[NAME_MAX] = '\0';
- }
-
- if ((tmp_new != NULL) && (strlen(tmp_old) < NAME_MAX)) {
- strncpy(newest, tmp_new, NAME_MAX);
- oldest[NAME_MAX] = '\0';
- }
- }
-
- /* free scandir result */
- for (i = 0; i < cnt; i++)
- free(files[i]);
-
- free(files);
-
- return num;
-}
-
-void dlt_offline_trace_file_name(char *log_file_name, size_t length,
- char *name, unsigned int idx)
-{
- char file_index[11]; /* UINT_MAX = 4294967295 -> 10 digits */
- snprintf(file_index, sizeof(file_index), "%010u", idx);
-
- /* create log file name */
- memset(log_file_name, 0, length * sizeof(char));
- strncat(log_file_name, name, length - strlen(log_file_name) - 1);
- strncat(log_file_name, DLT_OFFLINETRACE_FILENAME_INDEX_DELI,
- length - strlen(log_file_name) - 1);
- strncat(log_file_name, file_index, length - strlen(log_file_name) - 1);
- strncat(log_file_name, DLT_OFFLINETRACE_FILENAME_EXT,
- length - strlen(log_file_name) - 1);
-}
-
-unsigned int dlt_offline_trace_get_idx_of_log_file(char *file)
-{
- const char d[2] = DLT_OFFLINETRACE_FILENAME_INDEX_DELI;
- char *token;
- unsigned int idx = 0;
-
- if (file[0] == '\0')
- return 0;
-
- token = strtok(file, d);
- /* we are interested in 2. token because of log file name */
- token = strtok(NULL, d);
-
- if (token != NULL)
- idx = strtol(token, NULL, 10);
- else
- idx = 0;
-
- return idx;
-}
-
-
-DltReturnValue dlt_offline_trace_create_new_file(DltOfflineTrace *trace)
-{
- time_t t;
- struct tm tmp;
- char file_path[PATH_MAX + 1];
- unsigned int idx = 0;
- int ret = 0;
-
- /* set filename */
- if (trace->filenameTimestampBased) {
- /* timestamp format: "yyyymmdd_hhmmss" */
- char timestamp[16];
- t = time(NULL);
- tzset();
- localtime_r(&t, &tmp);
-
- strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", &tmp);
-
- ret = snprintf(trace->filename, sizeof(trace->filename), "%s%s%s%s",
- DLT_OFFLINETRACE_FILENAME_BASE,
- DLT_OFFLINETRACE_FILENAME_TIMESTAMP_DELI, timestamp,
- DLT_OFFLINETRACE_FILENAME_EXT);
-
- if ((ret < 0) || ((size_t)ret >= (int)sizeof(trace->filename))) {
- printf("dlt_offlinetrace filename cannot be concatenated\n");
- return DLT_RETURN_ERROR;
- }
-
- ret = snprintf(file_path, sizeof(file_path), "%s/%s",
- trace->directory, trace->filename);
-
- if ((ret < 0) || ((size_t)ret >= (int)sizeof(file_path))) {
- printf("dlt_offlinetrace file path cannot be concatenated\n");
- return DLT_RETURN_ERROR;
- }
- }
- else {
- char newest[NAME_MAX + 1] = { 0 };
- char oldest[NAME_MAX + 1] = { 0 };
- /* targeting newest file, ignoring number of files in dir returned */
- dlt_offline_trace_storage_dir_info(trace->directory,
- DLT_OFFLINETRACE_FILENAME_BASE, newest, oldest);
- idx = dlt_offline_trace_get_idx_of_log_file(newest) + 1;
-
- dlt_offline_trace_file_name(trace->filename, sizeof(trace->filename),
- DLT_OFFLINETRACE_FILENAME_BASE, idx);
- ret = snprintf(file_path, sizeof(file_path), "%s/%s",
- trace->directory, trace->filename);
-
- if ((ret < 0) || (ret >= NAME_MAX)) {
- printf("filename cannot be concatenated\n");
- return DLT_RETURN_ERROR;
- }
- }
-
- /* open DLT output file */
- trace->ohandle = open(file_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
- S_IRGRP | S_IROTH); /* mode: wb */
-
- if (trace->ohandle == -1) {
- /* trace file cannot be opened */
- printf("Offline trace file %s cannot be created\n", file_path);
- return DLT_RETURN_ERROR;
- } /* if */
-
- return DLT_RETURN_OK; /* OK */
-}
-
-ssize_t dlt_offline_trace_get_total_size(DltOfflineTrace *trace)
-{
- struct dirent *dp;
- char filename[PATH_MAX + 1];
- ssize_t size = 0;
- struct stat status;
-
- /* go through all dlt files in directory */
- DIR *dir = opendir(trace->directory);
-
- if (!dir)
- return -1;
-
- while ((dp = readdir(dir)) != NULL)
- if (strstr(dp->d_name, DLT_OFFLINETRACE_FILENAME_BASE)) {
- int res = snprintf(filename, sizeof(filename), "%s/%s", trace->directory, dp->d_name);
-
- /* if the total length of the string is greater than the buffer, silently forget it. */
- /* snprintf: a return value of size or more means that the output was truncated */
- /* if an output error is encountered, a negative value is returned. */
- if (((unsigned int)res < sizeof(filename)) && (res > 0)) {
- if (0 == stat(filename, &status))
- size += status.st_size;
- else
- printf("Offline trace file %s cannot be stat-ed", filename);
- }
-
- /*else */
- /*{ */
- /* dlt_log(3, "dlt_offline_trace_get_total_size: long filename ignored"); */
- /*} */
- }
-
- closedir(dir);
-
- /* return size */
- return size;
-}
-
-int dlt_offline_trace_delete_oldest_file(DltOfflineTrace *trace)
-{
- struct dirent *dp;
- char filename[PATH_MAX + 1];
- char filename_oldest[PATH_MAX + 1];
- unsigned long size_oldest = 0;
- struct stat status;
- time_t time_oldest = 0;
-
- filename[0] = 0;
- filename_oldest[0] = 0;
-
- /* go through all dlt files in directory */
- DIR *dir = opendir(trace->directory);
-
- if(!dir)
- return -1;
-
- while ((dp = readdir(dir)) != NULL)
- if (strstr(dp->d_name, DLT_OFFLINETRACE_FILENAME_BASE)) {
- int res = snprintf(filename, sizeof(filename), "%s/%s", trace->directory, dp->d_name);
-
- /* if the total length of the string is greater than the buffer, silently forget it. */
- /* snprintf: a return value of size or more means that the output was truncated */
- /* if an output error is encountered, a negative value is returned. */
- if (((unsigned int)res < sizeof(filename)) && (res > 0)) {
- if (0 == stat(filename, &status)) {
- if ((time_oldest == 0) || (status.st_mtime < time_oldest)) {
- time_oldest = status.st_mtime;
- size_oldest = status.st_size;
- strncpy(filename_oldest, filename, PATH_MAX);
- filename_oldest[PATH_MAX] = 0;
- }
- }
- else {
- printf("Old offline trace file %s cannot be stat-ed", filename);
- }
- }
- }
-
- closedir(dir);
-
- /* delete file */
- if (filename_oldest[0]) {
- if (remove(filename_oldest)) {
- printf("Remove file %s failed!\n", filename_oldest);
- return -1; /* ERROR */
- }
- }
- else {
- printf("No file to be removed!\n");
- return -1; /* ERROR */
- }
-
- /* return size of deleted file*/
- return size_oldest;
-}
-
-DltReturnValue dlt_offline_trace_check_size(DltOfflineTrace *trace)
-{
-
- struct stat status;
-
- /* check for existence of offline trace directory */
- if (stat(trace->directory, &status) == -1) {
- dlt_vlog(LOG_ERR, "Offline trace directory: %s doesn't exist \n", trace->directory);
- return DLT_RETURN_ERROR;
- }
-
- /* check for accesibilty of offline trace directory */
- else if (access(trace->directory, W_OK) != 0)
- {
- dlt_vlog(LOG_ERR, "Offline trace directory: %s doesn't have the write access \n", trace->directory);
- return DLT_RETURN_ERROR;
- }
-
- ssize_t s = 0;
-
- /* check size of complete offline trace */
- while ((s = dlt_offline_trace_get_total_size(trace)) > (trace->maxSize - trace->fileSize))
- /* remove oldest files as long as new file will not fit in completely into complete offline trace */
- if (dlt_offline_trace_delete_oldest_file(trace) < 0)
- return DLT_RETURN_ERROR;
-
- if (s == -1)
- return DLT_RETURN_ERROR;
-
- return DLT_RETURN_OK; /* OK */
-}
-
-DltReturnValue dlt_offline_trace_init(DltOfflineTrace *trace,
- const char *directory,
- int fileSize,
- int maxSize,
- int filenameTimestampBased)
-{
-
- /* init parameters */
- strncpy(trace->directory, directory, NAME_MAX);
- trace->directory[NAME_MAX] = 0;
- trace->fileSize = fileSize;
- trace->maxSize = maxSize;
- trace->filenameTimestampBased = filenameTimestampBased;
- /* check complete offlien trace size, remove old logs if needed */
- dlt_offline_trace_check_size(trace);
-
- return dlt_offline_trace_create_new_file(trace);
-}
-
-DltReturnValue dlt_offline_trace_write(DltOfflineTrace *trace,
- unsigned char *data1,
- int size1,
- unsigned char *data2,
- int size2,
- unsigned char *data3,
- int size3)
+#include <dlt_multiple_files.h>
+
+DltReturnValue dlt_offline_trace_write(MultipleFilesRingBuffer *trace,
+ const unsigned char *data1,
+ const int size1,
+ const unsigned char *data2,
+ const int size2,
+ const unsigned char *data3,
+ const int size3)
{
- if (trace->ohandle < 0)
- return DLT_RETURN_ERROR;
-
- /* check file size here */
- if ((lseek(trace->ohandle, 0, SEEK_CUR) + size1 + size2 + size3) >= trace->fileSize) {
- /* close old file */
- close(trace->ohandle);
- trace->ohandle = -1;
-
- /* check complete offline trace size, remove old logs if needed */
- dlt_offline_trace_check_size(trace);
+ if (trace->ohandle < 0) return DLT_RETURN_ERROR;
- /* create new file */
- dlt_offline_trace_create_new_file(trace);
- }
+ multiple_files_buffer_rotate_file(trace, size1 + size2 + size3);
/* write data into log file */
- if (data1 && (trace->ohandle >= 0)) {
- if (write(trace->ohandle, data1, size1) != size1) {
- printf("Offline trace write failed!\n");
- return DLT_RETURN_ERROR;
- }
- }
-
- if (data2 && (trace->ohandle >= 0)) {
- if (write(trace->ohandle, data2, size2) != size2) {
- printf("Offline trace write failed!\n");
- return DLT_RETURN_ERROR;
- }
- }
-
- if (data3 && (trace->ohandle >= 0)) {
- if (write(trace->ohandle, data3, size3) != size3) {
- printf("Offline trace write failed!\n");
- return DLT_RETURN_ERROR;
- }
- }
-
- return DLT_RETURN_OK; /* OK */
-}
-
-DltReturnValue dlt_offline_trace_free(DltOfflineTrace *trace)
-{
-
- if (trace->ohandle < 0)
- return DLT_RETURN_ERROR;
-
- /* close last used log file */
- close(trace->ohandle);
+ if (multiple_files_buffer_write_chunk(trace, data1, size1) != DLT_RETURN_OK) return DLT_RETURN_ERROR;
+ if (multiple_files_buffer_write_chunk(trace, data2, size2) != DLT_RETURN_OK) return DLT_RETURN_ERROR;
+ if (multiple_files_buffer_write_chunk(trace, data3, size3) != DLT_RETURN_OK) return DLT_RETURN_ERROR;
- return DLT_RETURN_OK; /* OK */
+ return DLT_RETURN_OK;
}