diff options
-rw-r--r-- | doc/dlt_for_developers.md | 70 | ||||
-rw-r--r-- | include/dlt/dlt_user.h.in | 34 | ||||
-rw-r--r-- | src/lib/dlt_user.c | 122 |
3 files changed, 195 insertions, 31 deletions
diff --git a/doc/dlt_for_developers.md b/doc/dlt_for_developers.md index 09e2b87..d664ab8 100644 --- a/doc/dlt_for_developers.md +++ b/doc/dlt_for_developers.md @@ -262,7 +262,7 @@ DLT\_LOG\_INFO | Informational, providing high level understanding DLT\_LOG\_DEBUG | Detailed debug information for programmers DLT\_LOG\_VERBOSE | Verbose debug information for programmers -Please be aware the the default Log Level is set to INFO; this means message +Please be aware the default Log Level is set to INFO; this means message which are logged in INFO, WARN, ERROR and FATAL will logged. Hint: The default Log Level can be changed by setting an environment variable (see DLT Library - runtime configuration). @@ -734,6 +734,74 @@ if (dlt_user_log_write_start(&ctx, &ctxdata, DLT_LOG_INFO) > 0) { } ``` +#### Send log message with given buffer + +DLT applications can prepare a log message buffer by themselves instead +of calling logging parameters. There are two benefits; the applications +can reduce API calls to DLT library as much as possible so that the +APIs won't block the application's sequence, and dynamic allocation can +be avoided in DLT library during runtime. + +The applications should prepare following values in order to use this +functionality: + +- *char buffer[DLT_USER_BUF_MAX_SIZE]*: Buffer which contains one log message payload +- *size_t size*: Buffer size +- *int32_t args_num*: Number of arguments + +One argument in the buffer consists of following: +| Length(byte) | Description | +|----------------|--------------| +| 4 | Type Info | +| x | Data Payload | + +DLT Applications need to simulate what are done in logging parameters to +store data to the buffer (type info given to the buffer, etc.), +otherwise the behavior is undefined. + +Also important note here is that the functionality works properly only +with these function combination: + +- *Start logging*: dlt\_user\_log\_write\_start\_w\_given\_buffer +- *Finish logging*: dlt\_user\_log\_write\_finish\_w\_given\_buffer + +Since the function does not allocate memory dynamically, it could lead +to segmentation fault or memory leak with different APIs. It is mandatory +to check if dlt_user_is_logLevel_enabled is returning DLT_RETURN_TRUE before +calling dlt_user_log_write_start_w_given_buffer (see below code example). + +##### Macro + +No macro interface is available as of now. + +##### Function + +``` +/* Example: Prepare one log message with uint16 */ +char buffer[DLT_USER_BUF_MAX_SIZE] = {0}; +size_t size = 0; +int32_t args_num = 0; + +uint32_t type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT; +memcpy(buffer + size, &(type_info), sizeof(uint32_t)); +size += sizeof(uint32_t); + +uint16_t data = 1234; +memcpy(buffer + size, &data, sizeof(uint16_t)); +size += sizeof(uint16_t); + +args_num++; + +/* Give the buffer to DLT library */ +if (dlt_user_is_logLevel_enabled(&ctx,DLT_LOG_INFO) == DLT_RETURN_TRUE) +{ + if (dlt_user_log_write_start_w_given_buffer(&ctx, &ctxdata, DLT_LOG_INFO, buffersize, args_num) > 0) + { + dlt_user_log_write_finish_w_given_buffer(&ctxdata); + } +} +``` + #### Attributes In verbose mode, log message arguments can contain attributes. A "name" attribute diff --git a/include/dlt/dlt_user.h.in b/include/dlt/dlt_user.h.in index 30eb234..7a2d35e 100644 --- a/include/dlt/dlt_user.h.in +++ b/include/dlt/dlt_user.h.in @@ -298,6 +298,30 @@ DltReturnValue dlt_user_log_write_start_id(DltContext *handle, uint32_t messageid); /** + * Initialize the generation of a DLT log message with given buffer from DLT application. + * This can be considered as replacement of dlt_user_log_write_start/dlt_user_log_write_start_id + * and other data functions like dlt_user_log_write_string. The fourth, fifth, and sixth arguments + * shall be prepared by DLT application; this function is only responsible for checking log + * level and setting the given values to context data. This function has to be called first, + * when an application is ready to send a new log message with given buffer. This function only + * works with combination of dlt_user_log_write_finish_w_given_buffer and the function must only be + * called, when return value is bigger than zero. The function only supports verbose mode as of now. + * @param handle pointer to an object containing information about one special logging context + * @param log pointer to an object containing information about logging context data + * @param loglevel this is the current log level of the log message to be sent + * @param buffer data with log message + * @param size buffer size + * @param args_num number of arguments in buffer + * @return Value from DltReturnValue enum, DLT_RETURN_TRUE if log level is matching + */ +DltReturnValue dlt_user_log_write_start_w_given_buffer(DltContext *handle, + DltContextData *log, + DltLogLevelType loglevel, + char *buffer, + size_t size, + int32_t args_num); + +/** * Finishing the generation of a DLT log message and sending it to the DLT daemon. * This function has to be called after writing all the log attributes of a log message. * @param log pointer to an object containing information about logging context data @@ -306,6 +330,16 @@ DltReturnValue dlt_user_log_write_start_id(DltContext *handle, DltReturnValue dlt_user_log_write_finish(DltContextData *log); /** + * Finishing the generation of a DLT log message and sending it to the DLT daemon without + * freeing log buffer. This function only works with combination of + * dlt_user_log_write_start_w_given_buffer. This function has to be called after writing all + * the log attributes of a log message. + * @param log pointer to an object containing information about logging context data + * @return Value from DltReturnValue enum + */ +DltReturnValue dlt_user_log_write_finish_w_given_buffer(DltContextData *log); + +/** * Write a boolean parameter into a DLT log message. * dlt_user_log_write_start has to be called before adding any attributes to the log message. * Finish sending log message by calling dlt_user_log_write_finish. diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c index d2ef613..d29a7a0 100644 --- a/src/lib/dlt_user.c +++ b/src/lib/dlt_user.c @@ -1719,6 +1719,26 @@ int dlt_set_resend_timeout_atexit(uint32_t timeout_in_milliseconds) /* ********************************************************************************************* */ +DltReturnValue dlt_user_log_write_start_init(DltContext *handle, + DltContextData *log, + DltLogLevelType loglevel, + bool is_verbose) +{ + DLT_LOG_FATAL_RESET_TRAP(loglevel); + + /* initialize values */ + if ((dlt_user_log_init(handle, log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL)) + return DLT_RETURN_ERROR; + + log->args_num = 0; + log->log_level = loglevel; + log->size = 0; + log->use_timestamp = DLT_AUTO_TIMESTAMP; + log->verbose_mode = is_verbose; + + return DLT_RETURN_TRUE; +} + static DltReturnValue dlt_user_log_write_start_internal(DltContext *handle, DltContextData *log, DltLogLevelType loglevel, @@ -1744,8 +1764,7 @@ DltReturnValue dlt_user_log_write_start_internal(DltContext *handle, uint32_t messageid, bool is_verbose) { - DLT_LOG_FATAL_RESET_TRAP(loglevel); - DltReturnValue ret = DLT_RETURN_OK; + int ret = DLT_RETURN_TRUE; /* check nullpointer */ if ((handle == NULL) || (log == NULL)) @@ -1758,47 +1777,78 @@ DltReturnValue dlt_user_log_write_start_internal(DltContext *handle, /* check log levels */ ret = dlt_user_is_logLevel_enabled(handle, loglevel); - if (ret == DLT_RETURN_WRONG_PARAMETER) + if (ret == DLT_RETURN_WRONG_PARAMETER) { return DLT_RETURN_WRONG_PARAMETER; - else if (ret == DLT_RETURN_LOGGING_DISABLED) + } else if (ret == DLT_RETURN_LOGGING_DISABLED) { + log->handle = NULL; return DLT_RETURN_OK; + } - /* initialize values */ - if ((dlt_user_log_init(handle, log) < DLT_RETURN_OK) || (dlt_user.dlt_ll_ts == NULL)) - return DLT_RETURN_ERROR; + ret = dlt_user_log_write_start_init(handle, log, loglevel, is_verbose); + if (ret == DLT_RETURN_TRUE) { + /* initialize values */ + if (log->buffer == NULL) { + log->buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); - /* initialize values */ - if (log->buffer == NULL) { - log->buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); + if (log->buffer == NULL) { + dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); + return DLT_RETURN_ERROR; + } + } - if (log->buffer == NULL) { - dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); - return DLT_RETURN_ERROR; + /* In non-verbose mode, insert message id */ + if (!is_verbose_mode(dlt_user.verbose_mode, log)) { + if ((sizeof(uint32_t)) > dlt_user.log_buf_len) { + return DLT_RETURN_USER_BUFFER_FULL; + } + + /* Write message id */ + memcpy(log->buffer, &(messageid), sizeof(uint32_t)); + log->size = sizeof(uint32_t); + + /* as the message id is part of each message in non-verbose mode, + * it doesn't increment the argument counter in extended header (if used) */ } } - log->args_num = 0; - log->log_level = loglevel; - log->size = 0; - log->use_timestamp = DLT_AUTO_TIMESTAMP; - log->verbose_mode = is_verbose; + return ret; +} - /* In non-verbose mode, insert message id */ - if (!is_verbose_mode(dlt_user.verbose_mode, log)) { - if ((sizeof(uint32_t)) > dlt_user.log_buf_len) - return DLT_RETURN_USER_BUFFER_FULL; +DltReturnValue dlt_user_log_write_start_w_given_buffer(DltContext *handle, + DltContextData *log, + DltLogLevelType loglevel, + char *buffer, + size_t size, + int32_t args_num) +{ + int ret = DLT_RETURN_TRUE; - /* Write message id */ - memcpy(log->buffer, &(messageid), sizeof(uint32_t)); - log->size = sizeof(uint32_t); + /* check nullpointer */ + if ((handle == NULL) || (log == NULL) || (buffer == NULL)) + return DLT_RETURN_WRONG_PARAMETER; - /* as the message id is part of each message in non-verbose mode, - * it doesn't increment the argument counter in extended header (if used) */ - } + /* discard unexpected parameters */ + if ((size <= 0) || (size > dlt_user.log_buf_len) || (args_num <= 0)) + return DLT_RETURN_WRONG_PARAMETER; - return DLT_RETURN_TRUE; -} + /* forbid dlt usage in child after fork */ + if (g_dlt_is_child) + return DLT_RETURN_ERROR; + + /* discard non-verbose mode */ + if (dlt_user.verbose_mode == 0) + return DLT_RETURN_ERROR; + + ret = dlt_user_log_write_start_init(handle, log, loglevel, true); + if (ret == DLT_RETURN_TRUE) { + log->buffer = (unsigned char *)buffer; + log->size = size; + log->args_num = args_num; + } + return ret; + } + DltReturnValue dlt_user_log_write_finish(DltContextData *log) { int ret = DLT_RETURN_ERROR; @@ -1813,6 +1863,18 @@ DltReturnValue dlt_user_log_write_finish(DltContextData *log) return ret; } +DltReturnValue dlt_user_log_write_finish_w_given_buffer(DltContextData *log) +{ + int ret = DLT_RETURN_ERROR; + + if (log == NULL) + return DLT_RETURN_WRONG_PARAMETER; + + ret = dlt_user_log_send_log(log, DLT_TYPE_LOG); + + return ret; +} + static DltReturnValue dlt_user_log_write_raw_internal(DltContextData *log, const void *data, uint16_t length, DltFormatType type, const char *name, bool with_var_info) { /* check nullpointer */ |