Commit dd720963 authored by Dimitris Lampridis's avatar Dimitris Lampridis Committed by Dimitris Lampridis

sw: rework logging API to align it with IVI 3.15

parent 9da6cd3b
......@@ -57,11 +57,10 @@ enum {
`define WRTD_ACTION_LOG 'h20
typedef enum uint32_t {
WRTD_LOG_MSG_EV_GENERATED = 0,
WRTD_LOG_MSG_EV_GENERATED = 1,
WRTD_LOG_MSG_EV_CONSUMED,
WRTD_LOG_MSG_EV_DISCARDED,
WRTD_LOG_MSG_EV_NETWORK,
WRTD_LOG_MSG_LINK
WRTD_LOG_MSG_EV_NETWORK
} wrtd_log_msg_type;
typedef enum uint32_t {
......
......@@ -229,11 +229,11 @@ enum wrtd_trtl_actions {
#define WRTD_ACTION_LOG 0x20
enum wrtd_log_msg_type {
WRTD_LOG_MSG_EV_GENERATED,
WRTD_LOG_MSG_EV_CONSUMED,
WRTD_LOG_MSG_EV_DISCARDED,
WRTD_LOG_MSG_EV_NETWORK,
WRTD_LOG_MSG_LINK
WRTD_LOG_MSG_EV_NONE = 0,
WRTD_LOG_MSG_EV_GENERATED = 1,
WRTD_LOG_MSG_EV_CONSUMED = 2,
WRTD_LOG_MSG_EV_DISCARDED = 3,
WRTD_LOG_MSG_EV_NETWORK = 4
};
enum wrtd_log_reason_type {
......@@ -273,8 +273,8 @@ enum wrtd_log_reason_type {
* Log event descriptor
*/
struct wrtd_log_entry {
uint32_t type;
uint32_t reason;
enum wrtd_log_msg_type type;
enum wrtd_log_reason_type reason;
struct wrtd_event event;
struct wrtd_tstamp ts;
};
......
......@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <time.h>
#include "mockturtle/libmockturtle.h"
#include "libwrtd.h"
#include "libwrtd-private.h"
......@@ -702,8 +703,7 @@ enum wrtd_status wrtd_get_alarm_id(struct wrtd_dev *wrtd,
}
enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd,
struct wrtd_log_entry *log,
int poll_timeout)
struct wrtd_log_entry *log)
{
struct trtl_msg msg;
struct polltrtl p[WRTD_MAX_CPUS];
......@@ -721,10 +721,12 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd,
than expected */
errno = 0;
ret = trtl_msg_poll(p, wrtd->nbr_cpus, poll_timeout);
if (ret == 0)
return wrtd_return_error(wrtd, WRTD_ERROR_TIMEOUT,
"wrtd_log_read timeout");
ret = trtl_msg_poll(p, wrtd->nbr_cpus, 0);
if (ret == 0) {
// Nothing to read
log->type = WRTD_LOG_MSG_EV_NONE;
return WRTD_SUCCESS;
}
if (ret < 0)
return wrtd_return_error (wrtd, WRTD_ERROR_UNEXPECTED_RESPONSE,
"poll error(log_read): %s",
......@@ -743,10 +745,164 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd,
return WRTD_SUCCESS;
}
/* Should not happen. */
return wrtd_return_error(wrtd, WRTD_ERROR_TIMEOUT,
return wrtd_return_error(wrtd, WRTD_ERROR_UNEXPECTED_RESPONSE,
"wrtd_log_read timeout");
}
enum wrtd_status wrtd_get_next_event_log_entry(struct wrtd_dev *wrtd,
int32_t log_entry_buffer_size,
char *log_entry)
{
struct wrtd_log_entry log;
enum wrtd_status status;
struct tm *tm;
if(wrtd == NULL){
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Do not retrieve entry from log if buffer_size
is zero. Just report on necessary buffer size.
According to IVI 3.2, section 3.1.2.1 */
if (log_entry_buffer_size == 0)
return WRTD_LOG_ENTRY_SIZE;
status = wrtd_log_read(wrtd, &log);
WRTD_RETURN_IF_ERROR(status);
memset(log_entry, 0, log_entry_buffer_size);
/* Nothing to read */
if (log.type == WRTD_LOG_MSG_EV_NONE)
return WRTD_SUCCESS;
char *sptr = log_entry;
int count;
/* Ignore overflow if buffer_size is negative.
According to IVI 3.2, section 3.1.2.1 */
if (log_entry_buffer_size < 0)
count = WRTD_LOG_ENTRY_SIZE;
else
count = log_entry_buffer_size;
tm = gmtime((const time_t *)&log.ts.seconds);
if (tm == NULL)
return WRTD_ERROR_UNEXPECTED_RESPONSE;
/* Needs 20 characters */
strftime(sptr, count, "%F,%T.", tm);
count -= 20;
if (count < 0)
return WRTD_LOG_ENTRY_SIZE;
sptr += 20;
/* Needs 16 characters */
snprintf(sptr, count, "%03lu.%03lu.%03lu+%03d|",
(log.ts.ns / (1000L * 1000)),
(log.ts.ns / 1000L) % 1000,
log.ts.ns % 1000UL,
log.ts.frac >> (32 - 9));
count -= 16;
if (count < 0)
return WRTD_LOG_ENTRY_SIZE;
sptr += 16;
tm = gmtime((const time_t *)&log.event.ts.seconds);
if (tm == NULL)
return WRTD_ERROR_UNEXPECTED_RESPONSE;
/* Needs 20 characters */
strftime(sptr, count, "%F,%T.", tm);
count -= 20;
if (count < 0)
return WRTD_LOG_ENTRY_SIZE;
sptr += 20;
/* Needs 16 characters */
snprintf(sptr, count, "%03lu.%03lu.%03lu+%03d|",
(log.event.ts.ns / (1000L * 1000)),
(log.event.ts.ns / 1000L) % 1000,
log.event.ts.ns % 1000UL,
log.event.ts.frac >> (32 - 9));
count -= 16;
if (count < 0)
return WRTD_LOG_ENTRY_SIZE;
sptr += 16;
/* Needs 18 characters */
switch(log.type) {
case WRTD_LOG_MSG_EV_GENERATED:
if (log.reason == WRTD_LOG_GENERATED_ALARM)
snprintf(sptr, count, "GENERATED|ALARM ");
else if ((log.reason >= WRTD_LOG_GENERATED_DEVICE_0) &&
(log.reason <= WRTD_LOG_GENERATED_DEVICE_7) &&
(log.reason % 8 == 0))
snprintf(sptr, count, "GENERATED|DEVICE_%d",
(log.reason - 8) / 8);
else
return WRTD_ERROR_UNEXPECTED_RESPONSE;
break;
case WRTD_LOG_MSG_EV_CONSUMED:
if (log.reason == WRTD_LOG_CONSUMED_START)
snprintf(sptr, count, "CONSUMED |START ");
else if (log.reason == WRTD_LOG_CONSUMED_DONE)
snprintf(sptr, count, "CONSUMED |DONE ");
else
return WRTD_ERROR_UNEXPECTED_RESPONSE;
break;
case WRTD_LOG_MSG_EV_DISCARDED:
if (log.reason == WRTD_LOG_DISCARD_NO_SYNC)
snprintf(sptr, count, "DISCARDED|NO SYNC ");
else if (log.reason == WRTD_LOG_DISCARD_HOLDOFF)
snprintf(sptr, count, "DISCARDED|HOLD OFF");
else if (log.reason == WRTD_LOG_DISCARD_TIMEOUT)
snprintf(sptr, count, "DISCARDED|TIME OUT");
else if (log.reason == WRTD_LOG_DISCARD_OVERFLOW)
snprintf(sptr, count, "DISCARDED|OVERFLOW");
else
return WRTD_ERROR_UNEXPECTED_RESPONSE;
break;
case WRTD_LOG_MSG_EV_NETWORK:
if (log.reason == WRTD_LOG_NETWORK_TX)
snprintf(sptr, count, "NETWORK |TX ");
else if (log.reason == WRTD_LOG_NETWORK_RX)
snprintf(sptr, count, "NETWORK |RX ");
else
return WRTD_ERROR_UNEXPECTED_RESPONSE;
break;
default:
return WRTD_ERROR_UNEXPECTED_RESPONSE;
}
/* Last check, therefore also account for null termination */
count -= 19;
if (count < 0)
return WRTD_LOG_ENTRY_SIZE;
return WRTD_SUCCESS;
}
enum wrtd_status wrtd_clear_event_log_entries(struct wrtd_dev *wrtd)
{
int ret, i;
if(wrtd == NULL){
return WRTD_ERROR_NOT_INITIALIZED;
}
for (i = 0; i < wrtd->nbr_cpus; ++i) {
ret = trtl_hmq_flush(wrtd->trtl, i, WRTD_HMQ);
if (ret < 0)
return wrtd_return_error (wrtd, WRTD_ERROR_UNEXPECTED_RESPONSE,
"hmq flush error(clear_log): %s",
trtl_strerror(errno));
}
return WRTD_SUCCESS;
}
enum wrtd_status wrtd_alloc_rules(struct wrtd_dev *wrtd,
struct wrtd_lib_rule **rulesp)
{
......
......@@ -7,6 +7,13 @@
#define WRTD_RETURN_IF_ERROR(status) if(status != WRTD_SUCCESS) return status
/* A complete log entry needs 35+1+35+1+9+1+8=90 + 1 for null termination.
1st field: log tstamp in YYYY-MM-DD,hh:mm:ss.xxx.yyy.zzz+fff format.
2nd field: event tstamp in YYYY-MM-DD,hh:mm:ss.xxx.yyy.zzz+fff format.
3rd field: log type, padded with spaces to 9 characters.
4th field: log reason, padded with spaces to 8 characters. */
#define WRTD_LOG_ENTRY_SIZE 91
/* Add nanoseconds to an existing wrtd timestamp */
static inline void wrtd_ts_add_ns(struct wrtd_tstamp *ts, uint32_t ns)
{
......
......@@ -217,21 +217,11 @@ extern enum wrtd_status wrtd_get_sys_time(struct wrtd_dev *dev,
struct wrtd_tstamp *time);
/**@}*/
extern enum wrtd_status wrtd_clear_event_log_entries(struct wrtd_dev *dev);
extern enum wrtd_status wrtd_get_next_event_log_entry(struct wrtd_dev *wrtd,
int32_t log_entry_buffer_size,
char *log_entry);
/**
* @file libwrtd-log.c
*/
/**
* @defgroup logging
* Set of logging functions
* @{
*/
extern enum wrtd_status wrtd_log_read(struct wrtd_dev *dev,
struct wrtd_log_entry *log,
int poll_timeout);
// Maybe also add non-blocking wrtd_get_next_log_entry()
extern enum wrtd_status wrtd_clear_log(struct wrtd_dev *dev);
/**@}*/
/**
* @file libwrtd-alarm.c
......
......@@ -816,6 +816,12 @@ static enum wrtd_status wrtd_cmd_set_log(struct wrtd_dev *wrtd,
return WRTD_SUCCESS;
}
static enum wrtd_status wrtd_cmd_clear_log(struct wrtd_dev *wrtd,
int argc, char *argv[])
{
return wrtd_clear_event_log_entries(wrtd);
}
static struct wrtd_commands cmds[] = {
{ "dump-all", "", "shows wrtd config",
wrtd_cmd_dump_all },
......@@ -857,6 +863,8 @@ static struct wrtd_commands cmds[] = {
wrtd_cmd_reset_rule_stats },
{ "set-log", "on/off", "enable or disable log",
wrtd_cmd_set_log },
{ "clear-log", "", "clear pending log entries",
wrtd_cmd_clear_log },
#if 0
{ "state", "", "shows input state",
wrtd_cmd_state },
......
......@@ -39,99 +39,24 @@ static void help(void)
static void print_logging (struct wrtd_dev *wrtd, int n_read)
{
struct wrtd_log_entry log;
char log_entry[WRTD_LOG_ENTRY_SIZE];
enum wrtd_status status;
unsigned int i;
for(i = 0; i < n_read || n_read == 0; i++) {
status = wrtd_log_read(wrtd, &log, -1);
if (status != WRTD_SUCCESS) {
fprintf(stderr,
"Error: %s\n", wrtd_get_error_msg(wrtd));
return;
}
if (log.ts.seconds != 0 || log.ts.ns != 0) {
printf("At ");
print_ts(&log.event.ts);
putchar('\n');
}
switch(log.type) {
case WRTD_LOG_MSG_EV_GENERATED:
printf("generated ");
if (log.reason == WRTD_LOG_GENERATED_ALARM)
printf("alrm ");
else if (log.reason >= WRTD_LOG_GENERATED_DEVICE_0
&& log.reason < WRTD_LOG_GENERATED_DEVICE_1)
printf("dev0,ch%u",
log.reason - WRTD_LOG_GENERATED_DEVICE_0);
else if (log.reason >= WRTD_LOG_GENERATED_DEVICE_1
&& log.reason < WRTD_LOG_GENERATED_DEVICE_2)
printf("dev1,ch%u",
log.reason - WRTD_LOG_GENERATED_DEVICE_1);
else
printf("%-8u ", log.reason);
break;
case WRTD_LOG_MSG_EV_CONSUMED:
printf("consumed ");
switch(log.reason) {
case WRTD_LOG_CONSUMED_START:
printf("start ");
break;
case WRTD_LOG_CONSUMED_DONE:
printf("done ");
break;
default:
printf("%-7u ", log.reason);
break;
do {
status = wrtd_get_next_event_log_entry(
wrtd, WRTD_LOG_ENTRY_SIZE, log_entry);
if (status != WRTD_SUCCESS) {
fprintf(stderr,
"Error: %s\n", wrtd_get_error_msg(wrtd));
return;
}
break;
case WRTD_LOG_MSG_EV_DISCARDED:
printf("discarded ");
switch(log.reason) {
case WRTD_LOG_DISCARD_NO_SYNC:
printf("nosync ");
break;
case WRTD_LOG_DISCARD_TIMEOUT:
printf("timeout ");
break;
case WRTD_LOG_DISCARD_OVERFLOW:
printf("ovrflow ");
break;
default:
printf("%-7u ", log.reason);
break;
}
break;
case WRTD_LOG_MSG_EV_NETWORK:
printf("network ");
switch(log.reason) {
case WRTD_LOG_NETWORK_TX:
printf("tx ");
break;
case WRTD_LOG_NETWORK_RX:
printf("rx ");
break;
default:
printf("%-7u ", log.reason);
break;
}
break;
case WRTD_LOG_MSG_LINK:
printf("link ");
break;
default:
printf("?%d", log.type);
break;
}
printf(" id: %-8.*s", WRTD_ID_LEN, log.event.id);
printf(" ev ts: ");
print_ts(&log.event.ts);
printf("\n");
} while (strlen(log_entry) == 0);
printf("%s\n", log_entry);
fflush(stdout);
}
}
}
int main(int argc, char *argv[])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment