diff --git a/doc/dlt.conf.5.md b/doc/dlt.conf.5.md index d8253140..690e99ca 100644 --- a/doc/dlt.conf.5.md +++ b/doc/dlt.conf.5.md @@ -246,6 +246,12 @@ Filename timestamp based or index based. 1 = timestamp based, 0 = index based Default: Function is disabled +## OfflineTraceUseUptimeOnly + +Use uptime in DLT storage header and filename instead of real-time + + Default: Function is disabled + # LOCAL CONSOLE OUTPUT OPTIONS ## PrintASCII diff --git a/include/dlt/dlt_common.h b/include/dlt/dlt_common.h index c37a9ce6..00f93536 100644 --- a/include/dlt/dlt_common.h +++ b/include/dlt/dlt_common.h @@ -1299,6 +1299,14 @@ int dlt_receiver_check_and_get(DltReceiver *receiver, * @return negative value if there was an error */ DltReturnValue dlt_set_storageheader(DltStorageHeader *storageheader, const char *ecu); +/** + * Fill the storage header of a DLT message with either the real-time clock or the monotonic clock. + * @param storageheader Pointer to the storage header of a DLT message. + * @param ecu Name of the ECU to be set in the storage header. + * @param useUptime If true, the monotonic clock is used as the timestamp; if false, the real-time clock is used. + * @return negative value if there was an error + */ +DltReturnValue dlt_set_storageheader_with_timestamp_option(DltStorageHeader *storageheader, const char *ecu, bool useUptime); /** * Check if a storage header contains its marker * @param storageheader pointer to storage header of a dlt message diff --git a/include/dlt/dlt_multiple_files.h b/include/dlt/dlt_multiple_files.h index d8d7ed07..91ed80f8 100644 --- a/include/dlt/dlt_multiple_files.h +++ b/include/dlt/dlt_multiple_files.h @@ -51,6 +51,7 @@ typedef struct char filenameBase[NAME_MAX + 1];/**< (String) Prefix of file name */ char filenameExt[NAME_MAX + 1];/**< (String) Extension of file name */ int ohandle; /**< (int) file handle to current output file */ + bool fileNameUptimeBased; /**< (bool) is filename uptime stamp based? false = realtime based (Default: false) */ } MultipleFilesRingBuffer; /** @@ -78,6 +79,33 @@ extern DltReturnValue multiple_files_buffer_init(MultipleFilesRingBuffer *files_ const char *filename_base, const char *filename_ext); +/** + * Initialise the multiple files buffer with an uptime option. + * This function call opens the currently used log file. + * A check of the complete size of the files is done during startup. + * Old files are deleted, if there is not enough space left to create new file. + * This function must be called before using further multiple files functions. + * @param files_buffer pointer to MultipleFilesRingBuffer struct. + * @param directory directory where to store multiple files. + * @param file_size maximum size of one files. + * @param max_size maximum size of complete multiple files in bytes. + * @param filename_timestamp_based filename to be created on timestamp-based or index-based. + * @param append Indicates whether the current log files is used or a new file should be be created + * @param filename_base Base name. + * @param filename_ext File extension. + * @param use_uptime_in_filename Indicates whether filename to be created with realtime- or uptime-stamp. + * @return negative value if there was an error. + */ +extern DltReturnValue multiple_files_buffer_init_with_uptime_option(MultipleFilesRingBuffer *files_buffer, + const char *directory, + int file_size, + int max_size, + bool filename_timestamp_based, + bool append, + const char *filename_base, + const char *filename_ext, + bool use_uptime_in_filename); + /** * Uninitialise the multiple files buffer. * This function call closes currently used log file. diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c index 15ac8630..2a2f5e5d 100644 --- a/src/daemon/dlt-daemon.c +++ b/src/daemon/dlt-daemon.c @@ -622,6 +622,10 @@ int option_file_parser(DltDaemonLocal *daemon_local) daemon_local->flags.offlineTraceFilenameTimestampBased = (bool)atoi(value); /*printf("Option: %s=%s\n",token,value); */ } + else if (strcmp(token, "OfflineTraceUseUptimeOnly") == 0) + { + daemon_local->flags.offlineTraceUseUptimeOnly = (bool)atoi(value); + } else if (strcmp(token, "SendECUSoftwareVersion") == 0) { daemon_local->flags.sendECUSoftwareVersion = atoi(value); @@ -1443,14 +1447,15 @@ 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 (multiple_files_buffer_init(&(daemon_local->offlineTrace), + if (multiple_files_buffer_init_with_uptime_option(&(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_OFFLINETRACE_FILENAME_EXT, + daemon_local->flags.offlineTraceUseUptimeOnly) == -1) { dlt_log(LOG_ERR, "Could not initialize offline trace\n"); return -1; } @@ -2273,7 +2278,7 @@ int dlt_daemon_log_internal(DltDaemon *daemon, DltDaemonLocal *daemon_local, cha /* Set storageheader */ msg.storageheader = (DltStorageHeader *)(msg.headerbuffer); - dlt_set_storageheader(msg.storageheader, daemon->ecuid); + dlt_set_storageheader_with_timestamp_option(msg.storageheader, daemon->ecuid, daemon_local->flags.offlineTraceUseUptimeOnly); /* Set standardheader */ msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); diff --git a/src/daemon/dlt-daemon.h b/src/daemon/dlt-daemon.h index a734802f..cc896ad0 100644 --- a/src/daemon/dlt-daemon.h +++ b/src/daemon/dlt-daemon.h @@ -108,6 +108,7 @@ typedef struct int offlineTraceFileSize; /**< (int) Maximum size in bytes of one trace file (Default: 1000000) */ int offlineTraceMaxSize; /**< (int) Maximum size of all trace files (Default: 4000000) */ bool offlineTraceFilenameTimestampBased; /**< (Boolean) timestamp based or index based (Default: true=Timestamp based) */ + bool offlineTraceUseUptimeOnly; /**< (Boolean) use uptime in storage header and filename instead realtime (Default: false) */ 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) */ diff --git a/src/daemon/dlt.conf b/src/daemon/dlt.conf index c5be1695..c60044ed 100644 --- a/src/daemon/dlt.conf +++ b/src/daemon/dlt.conf @@ -127,6 +127,9 @@ ControlSocketPath = /tmp/dlt-ctrl.sock # Filename timestamp based or index based (Default:1) (timestamp based=1, index based =0) # OfflineTraceFileNameTimestampBased = 1 +# use uptime in DLT storage header and filename instead realtime (Default: 0) +# OfflineTraceUseUptimeOnly = 0 + ######################################################################## # Local console output configuration # ######################################################################## diff --git a/src/daemon/dlt_daemon_client.c b/src/daemon/dlt_daemon_client.c index dda92dec..0db9832d 100644 --- a/src/daemon/dlt_daemon_client.c +++ b/src/daemon/dlt_daemon_client.c @@ -351,8 +351,8 @@ int dlt_daemon_client_send_message_to_all_client(DltDaemon *daemon, } else { ecu_ptr = daemon->ecuid; } - - if (dlt_set_storageheader(daemon_local->msg.storageheader, ecu_ptr)) { + + if (dlt_set_storageheader_with_timestamp_option(daemon_local->msg.storageheader, ecu_ptr, daemon_local->flags.offlineTraceUseUptimeOnly)) { dlt_vlog(LOG_WARNING, "%s: failed to set storage header with header type: 0x%x\n", __func__, daemon_local->msg.standardheader->htyp); @@ -404,8 +404,7 @@ int dlt_daemon_client_send_control_message(int sock, /* prepare storage header */ msg->storageheader = (DltStorageHeader *)msg->headerbuffer; - - if (dlt_set_storageheader(msg->storageheader, daemon->ecuid) == DLT_RETURN_ERROR) + if (dlt_set_storageheader_with_timestamp_option(msg->storageheader, daemon->ecuid, daemon_local->flags.offlineTraceUseUptimeOnly) == DLT_RETURN_ERROR) return DLT_DAEMON_ERROR_UNKNOWN; /* prepare standard header */ @@ -2205,7 +2204,7 @@ void dlt_daemon_control_message_time(int sock, DltDaemon *daemon, DltDaemonLocal /* prepare storage header */ msg.storageheader = (DltStorageHeader *)msg.headerbuffer; - dlt_set_storageheader(msg.storageheader, daemon->ecuid); + dlt_set_storageheader_with_timestamp_option(msg.storageheader, daemon->ecuid, daemon_local->flags.offlineTraceUseUptimeOnly); /* prepare standard header */ msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader)); diff --git a/src/gateway/dlt_gateway.c b/src/gateway/dlt_gateway.c index a0abe985..72375969 100644 --- a/src/gateway/dlt_gateway.c +++ b/src/gateway/dlt_gateway.c @@ -1413,8 +1413,8 @@ DltReturnValue dlt_gateway_process_passive_node_messages(DltDaemon *daemon, } /* prepare storage header */ - if (dlt_set_storageheader(msg.storageheader, - msg.headerextra.ecu) == DLT_RETURN_ERROR) { + if (dlt_set_storageheader_with_timestamp_option(msg.storageheader, + msg.headerextra.ecu, daemon_local->flags.offlineTraceUseUptimeOnly) == DLT_RETURN_ERROR) { dlt_vlog(LOG_ERR, "%s: Can't set storage header\n", __func__); return DLT_RETURN_ERROR; } diff --git a/src/shared/dlt_common.c b/src/shared/dlt_common.c index 4a049efc..f10e4949 100644 --- a/src/shared/dlt_common.c +++ b/src/shared/dlt_common.c @@ -2317,10 +2317,15 @@ int dlt_receiver_check_and_get(DltReceiver *receiver, } DltReturnValue dlt_set_storageheader(DltStorageHeader *storageheader, const char *ecu) +{ + return dlt_set_storageheader_with_timestamp_option(storageheader, ecu, false); +} + +DltReturnValue dlt_set_storageheader_with_timestamp_option(DltStorageHeader *storageheader, const char *ecu, const bool useUptime) { #if !defined(_MSC_VER) - struct timeval tv; + struct timespec ts; #endif if ((storageheader == NULL) || (ecu == NULL)) @@ -2330,7 +2335,10 @@ DltReturnValue dlt_set_storageheader(DltStorageHeader *storageheader, const char #if defined(_MSC_VER) time(&(storageheader->seconds)); #else - gettimeofday(&tv, NULL); + if (useUptime) + clock_gettime(CLOCK_MONOTONIC, &ts); + else + clock_gettime(CLOCK_REALTIME, &ts); #endif /* prepare storage header */ @@ -2345,8 +2353,8 @@ DltReturnValue dlt_set_storageheader(DltStorageHeader *storageheader, const char #if defined(_MSC_VER) storageheader->microseconds = 0; #else - storageheader->seconds = (uint32_t) tv.tv_sec; /* value is long */ - storageheader->microseconds = (int32_t) tv.tv_usec; /* value is long */ + storageheader->seconds = (uint32_t) ts.tv_sec; /* value is long */ + storageheader->microseconds = (int32_t) (ts.tv_nsec / 1000); /* value is long */ #endif return DLT_RETURN_OK; diff --git a/src/shared/dlt_multiple_files.c b/src/shared/dlt_multiple_files.c index 65895569..aabcb7a2 100644 --- a/src/shared/dlt_multiple_files.c +++ b/src/shared/dlt_multiple_files.c @@ -161,9 +161,18 @@ DltReturnValue multiple_files_buffer_create_new_file(MultipleFilesRingBuffer *fi if (files_buffer->filenameTimestampBased) { /* timestamp format: "yyyymmdd_hhmmss" */ char timestamp[16]; - t = time(NULL); - tzset(); - localtime_r(&t, &tmp); + if (files_buffer->fileNameUptimeBased) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + t = ts.tv_sec; + gmtime_r(&t, &tmp); + } + else { + t = time(NULL); + tzset(); + localtime_r(&t, &tmp); + } strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", &tmp); @@ -412,6 +421,19 @@ DltReturnValue multiple_files_buffer_init(MultipleFilesRingBuffer *files_buffer, const bool append, const char *filename_base, const char *filename_ext) +{ + return multiple_files_buffer_init_with_uptime_option(files_buffer, directory, file_size, max_size, filename_timestamp_based, append, filename_base, filename_ext, false); +} + +DltReturnValue multiple_files_buffer_init_with_uptime_option(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, + const bool use_uptime_in_filename) { if (files_buffer == NULL) { fprintf(stderr, "multiple files buffer not set\n"); @@ -428,6 +450,7 @@ DltReturnValue multiple_files_buffer_init(MultipleFilesRingBuffer *files_buffer, files_buffer->filenameBase[NAME_MAX] = 0; strncpy(files_buffer->filenameExt, filename_ext, NAME_MAX); files_buffer->filenameExt[NAME_MAX] = 0; + files_buffer->fileNameUptimeBased = use_uptime_in_filename; if (DLT_RETURN_ERROR == multiple_files_buffer_check_size(files_buffer)) return DLT_RETURN_ERROR;