summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--[-rwxr-xr-x]src/lib/CMakeLists.txt6
-rw-r--r--src/lib/dlt_user.c382
-rw-r--r--src/shared/dlt_queue.c172
-rw-r--r--src/shared/dlt_queue.h142
-rwxr-xr-xsrc/shared/dlt_user_shared.h11
-rw-r--r--src/tests/CMakeLists.txt6
-rw-r--r--src/tests/dlt-test-queue.c94
7 files changed, 670 insertions, 143 deletions
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 0f2913b..bd0e4df 100755..100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -14,10 +14,10 @@
# @licence end@
########q
-set(dlt_LIB_SRCS dlt_user dlt_client dlt_filetransfer ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c)
+set(dlt_LIB_SRCS dlt_user dlt_client dlt_filetransfer ${CMAKE_SOURCE_DIR}/src/shared/dlt_queue.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c)
add_library(dlt ${dlt_LIB_SRCS})
-target_link_libraries(dlt rt m ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(dlt rt ${CMAKE_THREAD_LIBS_INIT})
set_target_properties(dlt PROPERTIES VERSION ${DLT_VERSION} SOVERSION ${DLT_MAJOR_VERSION})
@@ -27,5 +27,3 @@ install(TARGETS dlt
COMPONENT base)
-
-
diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c
index 117e6ae..7c87174 100644
--- a/src/lib/dlt_user.c
+++ b/src/lib/dlt_user.c
@@ -63,7 +63,6 @@
Initials Date Comment
aw 13.01.2010 initial
*/
-
#include <stdlib.h> /* for getenv(), free(), atexit() */
#include <string.h> /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */
#include <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
@@ -83,10 +82,13 @@
#include <sys/uio.h> /* writev() */
+#include <limits.h>
+
#include "dlt_user.h"
#include "dlt_user_shared.h"
#include "dlt_user_shared_cfg.h"
#include "dlt_user_cfg.h"
+#include "dlt_queue.h"
static DltUser dlt_user;
static int dlt_user_initialised = 0;
@@ -97,11 +99,28 @@ static sem_t dlt_mutex;
static pthread_t dlt_receiverthread_handle;
static pthread_attr_t dlt_receiverthread_attr;
+/* Segmented Network Trace */
+#define DLT_MAX_TRACE_SEGMENT_SIZE 1024
+#define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
+#define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFFFFFF
+
+typedef struct {
+ DltContext *handle;
+ uint16_t id;
+ DltNetworkTraceType nw_trace_type;
+ uint16_t header_len;
+ void *header;
+ uint16_t payload_len;
+ void *payload;
+} s_segmented_data;
+
+dlt_queue *dlt_segmented_nwt_queue;
+
/* Function prototypes for internally used functions */
static void dlt_user_receiverthread_function(void *ptr);
static void dlt_user_atexit_handler(void);
static int dlt_user_log_init(DltContext *handle, DltContextData *log);
-static int dlt_user_log_send_log(DltContextData *log, int mtype);
+static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype);
static int dlt_user_log_send_register_application(void);
static int dlt_user_log_send_unregister_application(void);
static int dlt_user_log_send_register_context(DltContextData *log);
@@ -112,6 +131,7 @@ static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
static int dlt_user_log_check_user_message(void);
static void dlt_user_log_reattach_to_daemon(void);
static int dlt_user_log_send_overflow(void);
+static void dlt_user_trace_network_segmented_thread(void *unused);
int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
@@ -223,7 +243,43 @@ int dlt_init(void)
dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
}
- return 0;
+ /* Generate per process name for queue */
+ char queue_name[NAME_MAX];
+ sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
+
+ /* Maximum queue size is 10, limit to size of pointers */
+ struct mq_attr mqatr;
+ mqatr.mq_flags = 0;
+ mqatr.mq_maxmsg = 10;
+ mqatr.mq_msgsize = sizeof(s_segmented_data *);
+ mqatr.mq_curmsgs = 0;
+
+ /* Separate handles for reading and writing */
+ dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
+ if(dlt_user.dlt_segmented_queue_read_handle < 0)
+ {
+ dlt_log(LOG_CRIT, "Can't create message queue read handle!\n");
+ dlt_log(LOG_CRIT, strerror(errno));
+ return -1;
+ }
+
+ dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY);
+ if(dlt_user.dlt_segmented_queue_write_handle < 0)
+ {
+ dlt_log(LOG_CRIT, "Can't open message queue write handle!\n");
+ dlt_log(LOG_CRIT, strerror(errno));
+ return -1;
+ }
+
+ if(pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
+ (void *)dlt_user_trace_network_segmented_thread, NULL))
+ {
+ dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
+ return -1;
+ }
+
+ return 0;
}
int dlt_init_file(const char *name)
@@ -430,6 +486,27 @@ int dlt_free(void)
dlt_user.dlt_ll_ts_num_entries = 0;
}
+ if (dlt_user.dlt_segmented_nwt_handle)
+ {
+ pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
+ }
+
+ char queue_name[NAME_MAX];
+ sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
+
+ if(mq_close(dlt_user.dlt_segmented_queue_write_handle) < 0)
+ {
+ dlt_log(LOG_ERR, "Failed to unlink message queue write handle!\n");
+ dlt_log(LOG_ERR, strerror(errno));
+ }
+
+ if(mq_close(dlt_user.dlt_segmented_queue_read_handle) < 0 ||
+ mq_unlink(queue_name))
+ {
+ dlt_log(LOG_ERR, "Failed to unlink message queue read handle!\n");
+ dlt_log(LOG_ERR, strerror(errno));
+ }
+
dlt_user_initialised = 0;
return 0;
@@ -1085,7 +1162,7 @@ int dlt_user_log_write_finish(DltContextData *log)
return -1;
}
- return dlt_user_log_send_log(log, DLT_TYPE_LOG);
+ return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
}
int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
@@ -1744,16 +1821,7 @@ int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
/**
* NW Trace related
*/
-#define MAX_TRACE_SEGMENT_SIZE 1024
-typedef struct {
- DltContext handle;
- DltNetworkTraceType nw_trace_type;
- uint16_t header_len;
- void *header;
- uint16_t payload_len;
- void *payload;
-} s_segmented_data;
int check_buffer()
{
@@ -1771,18 +1839,15 @@ int check_buffer()
* Send the start of a segment chain.
* Returns -1 on failure
*/
-int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len)
+int dlt_user_trace_network_segmented_start(uint16_t *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len)
{
DltContextData log;
struct timeval tv;
- if (dlt_user_initialised==0)
+ if (handle==NULL)
{
- if (dlt_init()<0)
- {
- return -1;
- }
+ return -1;
}
if (dlt_user_log_init(handle, &log)==-1)
@@ -1790,12 +1855,6 @@ int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle,
return -1;
}
- if (handle==0)
- {
- return -1;
- }
-
-
DLT_SEM_LOCK();
if (dlt_user.dlt_ll_ts==0)
@@ -1834,21 +1893,27 @@ int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle,
}
/* Write size of payload */
- if(dlt_user_log_write_uint(&log, payload_len))
+ if(dlt_user_log_write_uint(&log, payload_len) < 0)
{
return -1;
}
/* Write expected segment count */
- uint16_t segment_count = floor(payload_len/MAX_TRACE_SEGMENT_SIZE)+1;
+ uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
- if(dlt_user_log_write_uint(&log, segment_count))
+ /* If segments align perfectly with segment size, avoid sending empty segment */
+ if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
+ {
+ segment_count--;
+ }
+
+ if(dlt_user_log_write_uint(&log, segment_count) < 0)
{
return -1;
}
/* Write length of one segment */
- if(dlt_user_log_write_uint(&log, MAX_TRACE_SEGMENT_SIZE))
+ if(dlt_user_log_write_uint(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
{
return -1;
}
@@ -1863,42 +1928,26 @@ int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle,
return 0;
}
-int dlt_user_trace_network_segmented_segment(int id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
+int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
{
- int max_wait = 20;
- usleep(1000); // Yield, to give other threads time
while(check_buffer() < 0)
{
usleep(1000*50); // Wait 50ms
- if(max_wait-- < 0)
- {
- // Waited one second for buffer to flush, return error.
- return -1;
- }
dlt_user_log_resend_buffer();
}
- DltContextData log;
-
- if (dlt_user_initialised==0)
+ if (handle==NULL)
{
- if (dlt_init()<0)
- {
- return -1;
- }
+ return -1;
}
+ DltContextData log;
+
if (dlt_user_log_init(handle, &log)==-1)
{
return -1;
}
- if (handle==0)
- {
- return -1;
- }
-
-
DLT_SEM_LOCK();
if (dlt_user.dlt_ll_ts==0)
@@ -1928,7 +1977,7 @@ int dlt_user_trace_network_segmented_segment(int id, DltContext *handle, DltNetw
}
/* Write segment sequence number */
- if(dlt_user_log_write_uint(&log, sequence))
+ if(dlt_user_log_write_uint(&log, sequence) < 0)
{
return -1;
}
@@ -1946,19 +1995,19 @@ int dlt_user_trace_network_segmented_segment(int id, DltContext *handle, DltNetw
{
DLT_SEM_FREE();
}
+
+ /* Allow other threads to log between chunks */
+ pthread_yield();
return 0;
}
-int dlt_user_trace_network_segmented_end(int id, DltContext *handle, DltNetworkTraceType nw_trace_type)
+int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
{
DltContextData log;
- if (dlt_user_initialised==0)
+ if (handle==0)
{
- if (dlt_init()<0)
- {
- return -1;
- }
+ return -1;
}
if (dlt_user_log_init(handle, &log)==-1)
@@ -1966,10 +2015,6 @@ int dlt_user_trace_network_segmented_end(int id, DltContext *handle, DltNetworkT
return -1;
}
- if (handle==0)
- {
- return -1;
- }
DLT_SEM_LOCK();
@@ -2010,67 +2055,142 @@ int dlt_user_trace_network_segmented_end(int id, DltContext *handle, DltNetworkT
return 0;
}
-void dlt_user_trace_network_segmented_thread(s_segmented_data *data)
+void dlt_user_trace_network_segmented_thread(void *unused)
{
- unsigned int id;
- /* Send initial message */
- if(dlt_user_trace_network_segmented_start(&id, &(data->handle), data->nw_trace_type, data->header_len, data->header, data->payload_len) < 0)
- {
- // TODO: Report error
- return;
- }
+ /* Unused on purpose. */
+ (void) unused;
- /* Send segments */
- uint16_t offset = 0;
- uint16_t sequence = 0;
- void *ptr;
+ s_segmented_data *data;
- do
+ while(1)
{
- uint16_t len = data->payload_len - offset;
- if(len > MAX_TRACE_SEGMENT_SIZE)
+ ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
+ sizeof(s_segmented_data * ), NULL);
+ if(read != sizeof(s_segmented_data *))
{
- len = MAX_TRACE_SEGMENT_SIZE;
+ dlt_log(LOG_ERR, "NWTSegmented: Error while reading queue.\n");
+ dlt_log(LOG_ERR, strerror(errno));
+ continue;
}
- ptr = data->payload + offset;
- if(dlt_user_trace_network_segmented_segment(id, &(data->handle), data->nw_trace_type, sequence++, len, ptr) < 0)
+
+ /* Indicator just to try to flush the buffer */
+ if(data == (s_segmented_data *)DLT_DELAYED_RESEND_INDICATOR_PATTERN)
{
- // TODO: Report error
- return;
+ dlt_user_log_resend_buffer();
+ continue;
}
- offset += MAX_TRACE_SEGMENT_SIZE;
- }while(offset < data->payload_len);
- dlt_user_trace_network_segmented_end(id, &(data->handle), data->nw_trace_type);
+ /* Segment the data and send the chunks */
+ void *ptr = NULL;
+ uint16_t offset = 0;
+ uint16_t sequence = 0;
+ do
+ {
+ uint16_t len = 0;
+ if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
+ {
+ len = data->payload_len - offset;
+ }
+ else
+ {
+ len = DLT_MAX_TRACE_SEGMENT_SIZE;
+ }
+ /* If payload size aligns perfectly with segment size, avoid sendind empty segment */
+ if(len == 0)
+ {
+ break;
+ }
- // Allocated outside of thread, free here.
- free(data->header);
- free(data->payload);
- free(data);
+ ptr = data->payload + offset;
+ DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
+ if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
+ {
+ dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
+ break; // Inner loop
+ }
+ offset += len;
+ }while(ptr < data->payload + data->payload_len);
+
+ /* Send the end message */
+ DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
+ if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
+ {
+ dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
+ }
+
+ /* Free resources */
+ free(data->header);
+ free(data->payload);
+ free(data);
+ }
}
-void dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
+int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
{
+ /* Send as normal trace if possible */
+ if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
+ return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
+ }
+
+ /* Allocate Memory */
s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
+ if(thread_data == NULL)
+ {
+ return -1;
+ }
+ thread_data->header = malloc(header_len);
+ if(thread_data->header == NULL)
+ {
+ free(thread_data);
+ return -1;
+ }
+ thread_data->payload = malloc(payload_len);
+ if(thread_data->payload == NULL)
+ {
+ free(thread_data->header);
+ free(thread_data);
+ return -1;
+ }
/* Copy data */
- memcpy(&(thread_data->handle), handle, sizeof(DltContext));
+ thread_data->handle = handle;
thread_data->nw_trace_type = nw_trace_type;
thread_data->header_len = header_len;
- thread_data->header = malloc(header_len);
memcpy(thread_data->header, header, header_len);
thread_data->payload_len = payload_len;
- thread_data->payload = malloc(payload_len);
memcpy(thread_data->payload, payload, payload_len);
- /* Begin background thread */
- pthread_t thread;
- pthread_create(&thread, NULL, (void *)dlt_user_trace_network_segmented_thread, thread_data);
+ /* Send start message */
+ DltReturnValue err = dlt_user_trace_network_segmented_start(&(thread_data->id),
+ thread_data->handle, thread_data->nw_trace_type,
+ thread_data->header_len, thread_data->header,
+ thread_data->payload_len);
+ if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
+ {
+ dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
+ free(thread_data->header);
+ free(thread_data->payload);
+ free(thread_data);
+ return -1;
+ }
+
+ /* Add to queue */
+ if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
+ (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
+ {
+ free(thread_data->header);
+ free(thread_data->payload);
+ free(thread_data);
+ dlt_log(LOG_ERR, "NWTSegmented: Could not write into queue.\n");
+ dlt_log(LOG_ERR, strerror(errno));
+ return -1;
+ }
+ return 0;
}
int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
{
- return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 0);
+ return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
}
int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate)
@@ -2461,37 +2581,37 @@ int dlt_user_log_init(DltContext *handle, DltContextData *log)
return 0;
}
-int dlt_user_log_send_log(DltContextData *log, int mtype)
+DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
{
DltMessage msg;
DltUserHeader userheader;
int32_t len;
- DltReturnValue ret = 0;
+ DltReturnValue ret = DLT_RETURN_OK;
if (log==0)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (log->handle==0)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (dlt_user.appID[0]=='\0')
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (log->handle->contextID[0]=='\0')
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
{
- return -1;
+ return DLT_RETURN_ERROR;
}
/* also for Trace messages */
@@ -2501,19 +2621,19 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
#endif
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (dlt_message_init(&msg,0)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
@@ -2545,7 +2665,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
if (dlt_message_set_extraparameters(&msg,0)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
/* Fill out extended header, if extended header should be provided */
@@ -2569,7 +2689,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
default:
{
/* This case should not occur */
- return -1;
+ return DLT_RETURN_ERROR;
break;
}
}
@@ -2596,7 +2716,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
if (len>UINT16_MAX)
{
dlt_log(LOG_CRIT,"Huge message discarded!\n");
- return -1;
+ return DLT_RETURN_ERROR;
}
msg.standardheader->len = DLT_HTOBE_16(len);
@@ -2609,7 +2729,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
{
if (dlt_user_print_msg(&msg, log)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
}
}
@@ -2618,7 +2738,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
{
/* log to file */
ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
- return ((ret==DLT_RETURN_OK)?0:-1);
+ return ret;
}
else
{
@@ -2634,10 +2754,10 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
}
/* try to resent old data first */
- ret = 0;
+ ret = DLT_RETURN_OK;
if(dlt_user.dlt_log_handle!=-1)
ret = dlt_user_log_resend_buffer();
- if(ret==0)
+ if(ret==DLT_RETURN_OK)
{
/* resend ok or nothing to resent */
#ifdef DLT_SHM_ENABLE
@@ -2681,18 +2801,28 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
log->buffer, log->size)==-1)
{
dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
+ ret = DLT_RETURN_BUFFER_FULL;
}
DLT_SEM_FREE();
+
+ /* Ask segmented thread to try emptying the buffer soon. */
+ void *indic = (void *)DLT_DELAYED_RESEND_INDICATOR_PATTERN;
+ mq_send(dlt_user.dlt_segmented_queue_read_handle, (char *)&indic, sizeof(void *), 1);
}
switch (ret)
{
+ case DLT_RETURN_BUFFER_FULL:
+ {
+ /* Buffer full */
+ return DLT_RETURN_BUFFER_FULL;
+ }
case DLT_RETURN_PIPE_FULL:
{
/* data could not be written */
dlt_user.overflow = 1;
- return -1;
+ return DLT_RETURN_PIPE_FULL;
}
case DLT_RETURN_PIPE_ERROR:
{
@@ -2710,26 +2840,26 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
dlt_user_print_msg(&msg, log);
}
- return -1;
+ return DLT_RETURN_PIPE_ERROR;
}
case DLT_RETURN_ERROR:
{
/* other error condition */
- return -1;
+ return DLT_RETURN_ERROR;
}
case DLT_RETURN_OK:
{
- return 0;
+ return DLT_RETURN_OK;
}
default:
{
/* This case should never occur. */
- return -1;
+ return DLT_RETURN_ERROR;
}
}
}
- return 0;
+ return DLT_RETURN_OK;
}
int dlt_user_log_send_register_application(void)
@@ -3307,20 +3437,6 @@ int dlt_user_log_resend_buffer(void)
if (ret==DLT_RETURN_OK)
{
dlt_buffer_remove(&(dlt_user.startup_buffer));
- /*
- DLT_SEM_LOCK();
- if (dlt_buffer_push(&(dlt_user.startup_buffer), buf, size)==-1)
- {
- dlt_log(LOG_ERR,"Error pushing back message to history buffer. Message discarded.\n");
- }
- DLT_SEM_FREE();
-
- // In case of: data could not be written, set overflow flag
- if (ret==DLT_RETURN_PIPE_FULL)
- {
- dlt_user.overflow = 1;
- }
- */
}
else
{
diff --git a/src/shared/dlt_queue.c b/src/shared/dlt_queue.c
new file mode 100644
index 0000000..b9b4855
--- /dev/null
+++ b/src/shared/dlt_queue.c
@@ -0,0 +1,172 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2012 BMW AG
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Lassi Marttala <lassi.lm.marttala@partner.bmw.de> BMW 2012
+ *
+ * \file dlt_queue.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt_queue.h **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Lassi Marttala <lassi.lm.marttala@partner.bmw.de> **
+** **
+** PURPOSE : Linked list based dynamic queue **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: no **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** lm Lassi Marttala Eureka GmbH **
+*******************************************************************************/
+#include <stdlib.h>
+#include <semaphore.h>
+
+#include "dlt_queue.h"
+
+// Thread safety
+static sem_t dlt_queue_mutex;
+#define DLT_QUEUE_SEM_LOCK() { sem_wait(&dlt_queue_mutex); }
+#define DLT_QUEUE_SEM_FREE() { sem_post(&dlt_queue_mutex); }
+
+dlt_queue_item *dlt_queue_create_item()
+{
+ dlt_queue_item *item = malloc(sizeof(dlt_queue_item));
+ item->item = NULL;
+ item->item_size = 0;
+ item->next_item = NULL;
+ return item;
+}
+
+void dlt_queue_free_item(dlt_queue_item *item)
+{
+ if(item != NULL)
+ {
+ free(item);
+ item = NULL;
+ }
+}
+
+dlt_queue *dlt_queue_create()
+{
+ static int init_done = 0;
+ if(!init_done)
+ {
+ init_done = 1;
+ sem_init(&dlt_queue_mutex, 0, 1);
+ }
+ return (dlt_queue *)malloc(sizeof(dlt_queue));
+}
+
+void dlt_queue_free(dlt_queue *queue)
+{
+ if(queue != NULL)
+ {
+ free(queue);
+ queue = NULL;
+ }
+}
+
+void dlt_queue_push(dlt_queue_item *item, dlt_queue *queue)
+{
+ DLT_QUEUE_SEM_LOCK()
+ item->next_item = NULL;
+ // Empty queue
+ if(dlt_queue_is_empty(queue))
+ {
+ queue->head = item;
+ queue->tail = item;
+ }
+ // Exactly one item
+ else if(queue->head == queue->tail)
+ {
+ queue->head->next_item = (struct dlt_queue_item *)item;
+ queue->tail = item;
+ }
+ // Default case
+ else
+ {
+ queue->tail->next_item = (struct dlt_queue_item *)item;
+ queue->tail = item;
+ }
+ DLT_QUEUE_SEM_FREE()
+}
+
+dlt_queue_item *dlt_queue_pop(dlt_queue *queue)
+{
+ DLT_QUEUE_SEM_LOCK()
+ dlt_queue_item *retval = NULL;
+ // Empty queue
+ if(dlt_queue_is_empty(queue))
+ {
+ retval = NULL;
+ }
+ // Exactly one item
+ else if(queue->head == queue->tail)
+ {
+ retval = queue->head;
+ retval->next_item = NULL;
+ queue->head = NULL;
+ queue->tail = NULL;
+ }
+ // Default case
+ else
+ {
+ retval = queue->head;
+ queue->head = (dlt_queue_item *)retval->next_item;
+ retval->next_item = NULL;
+ }
+ DLT_QUEUE_SEM_FREE()
+ return retval;
+}
+
+int dlt_queue_is_empty(dlt_queue *queue)
+{
+ if(queue->head == NULL && queue->tail == NULL)
+ return 1;
+ return 0;
+}
+
+int dlt_queue_item_count(dlt_queue *queue)
+{
+ DLT_QUEUE_SEM_LOCK()
+ int retval = 0;
+ dlt_queue_item *ptr = queue->head;
+ while(ptr != NULL)
+ {
+ ptr = (dlt_queue_item *) ptr->next_item;
+ retval++;
+ }
+ DLT_QUEUE_SEM_FREE()
+ return retval;
+}
diff --git a/src/shared/dlt_queue.h b/src/shared/dlt_queue.h
new file mode 100644
index 0000000..40eda03
--- /dev/null
+++ b/src/shared/dlt_queue.h
@@ -0,0 +1,142 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2012 BMW AG
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Lassi Marttala <lassi.lm.marttala@partner.bmw.de> BMW 2012
+ *
+ * \file dlt_common_cfg.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt_queue.h **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Lassi Marttala <lassi.lm.marttala@partner.bmw.de> **
+** **
+** PURPOSE : Linked list based dynamic queue **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: no **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** lm Lassi Marttala Eureka GmbH **
+*******************************************************************************/
+#ifndef __DLT_QUEUE_H_
+#define __DLT_QUEUE_H_
+#include <stdint.h>
+
+/**
+ * \brief One item in the linked list
+ */
+typedef struct {
+ void *item;
+ uint16_t item_size;
+ struct dlt_queue_item *next_item;
+}dlt_queue_item;
+
+/**
+ * \brief Linked list of items
+ */
+typedef struct {
+ dlt_queue_item *head;
+ dlt_queue_item *tail;
+} dlt_queue;
+
+/**
+ * \brief Create new empty queue item
+ * Allocates a new item and returns a pointer to it
+ * @return Pointer to the new item
+ */
+dlt_queue_item *dlt_queue_create_item();
+
+/**
+ * \brief Free an queue item
+ * Frees the memory of the queue item
+ * @param item Pointer to the item to be freed
+ */
+void dlt_queue_free_item(dlt_queue_item *item);
+
+/**
+ * \brief Create a new empty queue
+ * Queue is created with no items in it.
+ * User is responsible for calling dlt_queue_free after
+ * the queue is not needed anymore.
+ * @return New allocated queue
+ */
+dlt_queue *dlt_queue_create();
+
+/**
+ * \brief Delete a queue
+ * Free the memory of the queue structure.
+ * Queued items are NOT freed. User must first pop all the items
+ * to remove the from queue and fere their memory themself.
+ * @param queue the queue to be freed
+ */
+void dlt_queue_free(dlt_queue *queue);
+
+/**
+ * \brief Push an item to the end of the queue
+ * Add a new item to the queue. It is now the new tail item.
+ * Queue does not take ownership of the item. User still must
+ * handle the freeing of the memory.
+ * @param item New item to add to the queue
+ * @param queue Queue to add the item to.
+ */
+void dlt_queue_push(dlt_queue_item *item, dlt_queue *queue);
+
+/**
+ * \brief Pop an item from the head of the queue
+ * Remove an item from the head of the queue and return it.
+ * @param queue Queue to pop from
+ * @return Pointer to the popped item
+ */
+dlt_queue_item *dlt_queue_pop(dlt_queue *queue);
+
+/**
+ * \brief Checks if the queue is empty
+ * Checks if the head and and tail are null pointers
+ * and returns the result.
+ * @param queue Queue to check
+ * @return 1 if queue is empty, 0 if not.
+ */
+int dlt_queue_is_empty(dlt_queue *queue);
+
+/**
+ * \brief Counts the items in the queue
+ * Walks the item chain and reports the number of items in
+ * the queue. If you only need to know if there are items
+ * or not, please use dlt_queue_is_empty, which is cheaper
+ * than counting the items.
+ * @param queue Queue to check
+ * @return number of items.
+ */
+int dlt_queue_item_count(dlt_queue *queue);
+#endif
diff --git a/src/shared/dlt_user_shared.h b/src/shared/dlt_user_shared.h
index 251a12e..203763a 100755
--- a/src/shared/dlt_user_shared.h
+++ b/src/shared/dlt_user_shared.h
@@ -75,11 +75,12 @@
* This are the return values for the functions dlt_user_log_out2() and dlt_user_log_out3()
*/
typedef enum
-{
- DLT_RETURN_PIPE_FULL = -3,
- DLT_RETURN_PIPE_ERROR = -2,
- DLT_RETURN_ERROR = -1,
- DLT_RETURN_OK = 0
+{
+ DLT_RETURN_BUFFER_FULL = -4,
+ DLT_RETURN_PIPE_FULL = -3,
+ DLT_RETURN_PIPE_ERROR = -2,
+ DLT_RETURN_ERROR = -1,
+ DLT_RETURN_OK = 0
} DltReturnValue;
/**
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 3d5ab91..e91ab58 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -13,6 +13,10 @@
#
# @licence end@
########
+set(dlt_test_queue_SRCS dlt-test-queue)
+add_executable(dlt-test-queue ${dlt_test_queue_SRCS})
+target_link_libraries(dlt-test-queue dlt)
+set_target_properties(dlt-test-queue PROPERTIES LINKER_LANGUAGE C)
set(dlt_test_multi_process_SRCS dlt-test-multi-process)
add_executable(dlt-test-multi-process ${dlt_test_multi_process_SRCS})
@@ -54,7 +58,7 @@ add_executable(dlt-test-filetransfer ${dlt_test_filetransfer_SRCS})
target_link_libraries(dlt-test-filetransfer dlt)
set_target_properties(dlt-test-filetransfer PROPERTIES LINKER_LANGUAGE C)
-install(TARGETS dlt-test-multi-process dlt-test-multi-process-client dlt-test-user dlt-test-client dlt-test-stress-user dlt-test-stress-client dlt-test-stress dlt-test-filetransfer
+install(TARGETS dlt-test-queue dlt-test-multi-process dlt-test-multi-process-client dlt-test-user dlt-test-client dlt-test-stress-user dlt-test-stress-client dlt-test-stress dlt-test-filetransfer
RUNTIME DESTINATION bin
COMPONENT base)
diff --git a/src/tests/dlt-test-queue.c b/src/tests/dlt-test-queue.c
new file mode 100644
index 0000000..774ea8f
--- /dev/null
+++ b/src/tests/dlt-test-queue.c
@@ -0,0 +1,94 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2012 BMW AG
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Lassi Marttala <lassi.lm.marttala@partner.bmw.de> BMW 2012
+ *
+ * \file dlt-test-queue.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt_queue.h **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Lassi Marttala <lassi.lm.marttala@partner.bmw.de> **
+** **
+** PURPOSE : Test for queue implementation **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: no **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** lm Lassi Marttala Eureka GmbH **
+*******************************************************************************/
+
+#include "dlt_queue.h"
+#include <stdio.h>
+#include <string.h>
+
+int main(void)
+{
+ char *item_content = "item_content\n";
+ int item_len = strlen(item_content) + 1;
+ dlt_queue *queue = dlt_queue_create();
+ printf("#1\tdlt_queue_is_empty returns\t%d\n", dlt_queue_is_empty(queue));
+
+ dlt_queue_item *first = dlt_queue_create_item();
+ first->item = item_content;
+ first->item_size = item_len;
+ dlt_queue_push(first, queue);
+
+ printf("#2\tdlt_queue_is_empty returns\t%d\n", dlt_queue_is_empty(queue));
+ printf("#3\tdlt_queue_item_count returns\t%d\n", dlt_queue_item_count(queue));
+
+ dlt_queue_item *tret = dlt_queue_pop(queue);
+ printf("#4\tItem content after pop:\t%d:%s", tret->item_size, (char *)tret->item);
+ dlt_queue_free_item(tret);
+
+ int i=0;
+ for(i=0;i<5;i++)
+ {
+ dlt_queue_item *newitem = dlt_queue_create_item();
+ newitem->item = item_content;
+ newitem->item_size = i;
+ dlt_queue_push(newitem, queue);
+ }
+ printf("#5\tdlt_queue_item_count returns\t%d\n", dlt_queue_item_count(queue));
+ while(!dlt_queue_is_empty(queue))
+ {
+ dlt_queue_item *olditem = dlt_queue_pop(queue);
+ printf("#6\tItem size (item number):%d\n", olditem->item_size);
+ dlt_queue_free_item(olditem);
+ }
+ printf("#7\tdlt_queue_is_empty returns\t%d\n", dlt_queue_is_empty(queue));
+ printf("#8\tdlt_queue_item_count returns\t%d\n", dlt_queue_item_count(queue));
+ return 0;
+}