From b24a5a890ccd19b0f1b50340c79c5087f08d9447 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 4 Mar 2022 15:56:30 +0100 Subject: [PATCH] ulog: add ringbuffer and log_event notification Signed-off-by: John Crispin --- ucode.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/ucode.c b/ucode.c index cef50e2..9e0373a 100644 --- a/ucode.c +++ b/ucode.c @@ -31,6 +31,17 @@ static const char *exception_types[] = { [EXCEPTION_EXIT] = "Exit" }; +struct log_buffer { + struct list_head list; + int severity; + char entry[]; +}; + +static LIST_HEAD(log_buffer); +static int log_count; +static int log_max = 100; +static uc_value_t *log_event; + static void ucode_handle_exception(uc_vm_t *vm, uc_exception_t *ex) { @@ -287,6 +298,7 @@ static uc_value_t * uc_ulog(uc_vm_t *vm, size_t nargs, int severity) { uc_value_t *res; + char *entry; if (!fmtfn) { fmtfn = (uc_cfunction_t *)ucv_object_get(uc_vm_scope_get(vm), "sprintf", NULL); @@ -300,7 +312,37 @@ uc_ulog(uc_vm_t *vm, size_t nargs, int severity) if (!res) return ucv_int64_new(-1); - ulog(severity, "%s", ucv_string_get(res)); + entry = ucv_string_get(res); + + if (log_max) { + struct log_buffer *log = calloc(1, sizeof(*log) + strlen(entry) + 1); + + strcpy(log->entry, entry); + log->severity = severity; + list_add_tail(&log->list, &log_buffer); + + if (log_event) { + uc_value_t *event = ucv_array_new(vm); + + ucv_array_push(event, ucv_int64_new(severity)); + ucv_array_push(event, ucv_string_new(entry)); + + uc_vm_stack_push(vm, ucv_get(log_event)); + uc_vm_stack_push(vm, ucv_get(event)); + uc_vm_call(vm, false, 1); + } + + if (log_count == log_max) { + struct log_buffer *first = list_first_entry(&log_buffer, struct log_buffer, list); + + list_del(&first->list); + free(first); + } else { + log_count++; + } + } + + ulog(severity, "%s", entry); ucv_put(res); return ucv_int64_new(0); @@ -330,11 +372,27 @@ uc_ulog_err(uc_vm_t *vm, size_t nargs) return uc_ulog(vm, nargs, LOG_ERR); } +static uc_value_t * +uc_ulog_dump(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *log = ucv_array_new(vm); + struct log_buffer *iter; + + list_for_each_entry(iter, &log_buffer, list) { + uc_value_t *entry = ucv_array_new(vm); + ucv_array_push(entry, ucv_int64_new(iter->severity)); + ucv_array_push(entry, ucv_string_new(iter->entry)); + ucv_array_push(log, entry); + } + + return log; +} + static void ucode_init_ulog(ucrun_ctx_t *ucrun) { uc_value_t *ulog = ucv_object_get(ucrun->scope, "ulog", NULL); - uc_value_t *identity, *channels; + uc_value_t *identity, *channels, *logsize; int flags = 0, channel; /* make sure the declartion is complete */ @@ -365,6 +423,18 @@ ucode_init_ulog(ucrun_ctx_t *ucrun) flags |= ULOG_STDIO; } + /* set the internal ring buffer size */ + logsize = ucv_object_get(ulog, "channels", NULL); + if (ucv_type(logsize) == UC_INTEGER && ucv_int64_get(logsize)) + log_max = ucv_int64_get(logsize); + + /* find out if ucrun wants a notification when a new log entry is generated */ + log_event = ucv_object_get(ulog, "event", NULL); + if (ucv_is_callable(log_event)) + ucv_get(log_event); + else + log_event = NULL; + /* open the log */ ucrun->ulog_identity = strdup(ucv_string_get(identity)); ulog_open(flags, LOG_DAEMON, ucrun->ulog_identity); @@ -404,6 +474,7 @@ ucode_init(ucrun_ctx_t *ucrun, int argc, const char **argv, int *rc) uc_function_register(ucrun->scope, "ulog_note", uc_ulog_note); uc_function_register(ucrun->scope, "ulog_warn", uc_ulog_warn); uc_function_register(ucrun->scope, "ulog_err", uc_ulog_err); + uc_function_register(ucrun->scope, "ulog_dump", uc_ulog_dump); /* add commandline parameters */ ARGV = ucv_array_new(&ucrun->vm); -- 2.25.1