From 2cea6129eb16eb189913a5558bb1f23e303af776 Mon Sep 17 00:00:00 2001 From: Liu Xinwu Date: Wed, 9 May 2018 18:21:01 +0800 Subject: [PATCH] tools: acrn-crashlog: interfaces to control history_event in acrnprobe "history_event" is the file to manage all evebts collected by acrnprobe. This patch provides the operation APIs for this file in a fixed format. Signed-off-by: Liu Xinwu Reviewed-by: Zhang Yanmin Reviewed-by: Liu Chuansheng Reviewed-by: Zhao Yakui Reviewed-by: Geoffroy Van Cutsem Acked-by: Eddie Dong --- tools/acrn-crashlog/acrnprobe/history.c | 261 +++++++++++++++++- .../acrn-crashlog/acrnprobe/include/history.h | 8 + 2 files changed, 268 insertions(+), 1 deletion(-) diff --git a/tools/acrn-crashlog/acrnprobe/history.c b/tools/acrn-crashlog/acrnprobe/history.c index 2c5a03b50..30514e575 100644 --- a/tools/acrn-crashlog/acrnprobe/history.c +++ b/tools/acrn-crashlog/acrnprobe/history.c @@ -19,8 +19,267 @@ * limitations under the License. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "fsutils.h" +#include "load_conf.h" #include "history.h" +#include "log_sys.h" +#include "probeutils.h" -void hist_raise_infoerror(char *type __attribute__((unused))) +#define HISTORY_FIRST_LINE_FMT \ + "#V1.0 CURRENTUPTIME %-24s\n" +#define HISTORY_BLANK_LINE2 \ + "#EVENT ID DATE TYPE\n" + +struct history_entry { + char *event; + char *type; + char *log; + const char *lastuptime; /* for uptime */ + char *key; + char *eventtime; +}; + +char *history_file; +static int current_lines; + +static void entry_to_history_line(struct history_entry *entry, + char newline[MAXLINESIZE]) { + newline[0] = 0; + if (entry->log != NULL) { + char *ptr; + char tmp[MAXLINESIZE]; + + strncpy(tmp, entry->log, MAXLINESIZE); + tmp[MAXLINESIZE-1] = 0; + ptr = strrchr(tmp, '/'); + if (ptr && ptr[1] == 0) + ptr[0] = 0; + snprintf(newline, MAXLINESIZE, "%-8s%-22s%-20s%s %s\n", + entry->event, entry->key, entry->eventtime, + entry->type, tmp); + } else if (entry->type != NULL && entry->type[0]) { + if (entry->lastuptime != NULL) { + snprintf(newline, MAXLINESIZE, + "%-8s%-22s%-20s%-16s %s\n", + entry->event, entry->key, + entry->eventtime, entry->type, + entry->lastuptime); + } else { + snprintf(newline, MAXLINESIZE, + "%-8s%-22s%-20s%-16s\n", + entry->event, entry->key, entry->eventtime, + entry->type); + } + } else { + snprintf(newline, MAXLINESIZE, "%-8s%-22s%-20s%s\n", + entry->event, entry->key, entry->eventtime, + entry->lastuptime); + } +} + +static void backup_history(void) +{ + int ret; + char *des; + + ret = asprintf(&des, "%s.bak", history_file); + if (ret < 0) { + LOGE("compute string failed, out of memory\n"); + return; + } + + ret = do_mv(history_file, des); + if (ret < 0) { + LOGE("backup %s failed, error (%s)\n", history_file, + strerror(errno)); + goto free; + } + + ret = prepare_history(); + if (ret < 0) { + LOGE("Prepare new history_file failed, exit\n"); + exit(EXIT_FAILURE); + } + +free: + free(des); +} + +void hist_raise_event(char *event, char *type, char *log, char *lastuptime, + char *key) +{ + char line[MAXLINESIZE]; + char eventtime[32]; + struct sender_t *crashlog; + int maxlines; + int ret; + struct history_entry entry = { + .event = event, + .type = type, + .log = log, + .lastuptime = lastuptime, + .key = key + }; + + /* here means user have configured the crashlog sender */ + crashlog = get_sender_by_name("crashlog"); + maxlines = atoi(crashlog->maxlines); + if (++current_lines >= maxlines) { + LOGW("lines of (%s) meet quota %d, backup... Pls clean!\n", + history_file, maxlines); + backup_history(); + } + + get_current_time_long(eventtime); + entry.eventtime = eventtime; + + entry_to_history_line(&entry, line); + ret = append_file(history_file, line); + if (ret < 0) { + LOGE("append (%s) failed, error (%s)\n", history_file, + strerror(errno)); + return; + } +} + +void hist_raise_uptime(char *lastuptime) +{ + char boot_time[24]; + char firstline[MAXLINESIZE]; + int hours; + int ret; + char *key; + static int loop_uptime_event = 1; + struct sender_t *crashlog; + struct uptime_t *uptime; + static int uptime_hours; + + /* user have configured the crashlog sender */ + crashlog = get_sender_by_name("crashlog"); + uptime = crashlog->uptime; + uptime_hours = atoi(uptime->eventhours); + + if (lastuptime) + hist_raise_event(uptime->name, NULL, NULL, lastuptime, + "00000000000000000000"); + else { + ret = get_uptime_string(boot_time, &hours); + if (ret < 0) { + LOGE("cannot get uptime - %s\n", strerror(-ret)); + return; + } + + sprintf(firstline, HISTORY_FIRST_LINE_FMT, boot_time); + replace_file_head(history_file, firstline); + + if (hours / uptime_hours >= loop_uptime_event) { + loop_uptime_event = (hours / uptime_hours) + 1; + + key = generate_event_id(uptime->name, ""); + if (key == NULL) { + LOGE("generate event id failed, error (%s)\n", + strerror(errno)); + return; + } + + hist_raise_event(uptime->name, NULL, NULL, + boot_time, key); + free(key); + } + } +} + +void hist_raise_infoerror(char *type) +{ + char *key; + + key = generate_event_id("ERROR", type); + if (key == NULL) { + LOGE("generate event id failed, error (%s)\n", + strerror(errno)); + return; + } + + hist_raise_event("ERROR", type, NULL, NULL, key); + free(key); +} + +static int get_time_firstline(char *buffer) +{ + char firstline[MAXLINESIZE]; + int ret; + char *fmt = "%*[^ ]%*[ ]%*[^ ]%*[ ]%[^ ]%*c"; + + memset(firstline, 0, MAXLINESIZE); + ret = file_read_string(history_file, firstline, MAXLINESIZE); + if (ret <= 0) { + LOGW("file_read_string failed, %d %s\n", ret, strerror(-ret)); + return -1; + } + + if (!strstr(firstline, "#V1.0 ")) + return -1; + + ret = sscanf(firstline, fmt, buffer); + if (ret != 1) { + LOGE("get last time failed, %d %s\n", ret, firstline); + return -1; + } + return 0; +} + +int prepare_history(void) +{ + int ret; + struct sender_t *crashlog; + char linebuf[MAXLINESIZE] = {0}; + + crashlog = get_sender_by_name("crashlog"); + if (!crashlog) + return 0; + + if (!history_file) { + ret = asprintf(&history_file, "%s/%s", crashlog->outdir, + HISTORY_NAME); + if (ret < 0) { + LOGE("compute string failed, out of memory\n"); + return -ENOMEM; + } + } + + ret = get_time_firstline(linebuf); + if (ret == 0) { + current_lines = count_lines_in_file(history_file); + hist_raise_uptime(linebuf); + } else { + /* new history */ + LOGW("new history\n"); + sprintf(linebuf, HISTORY_FIRST_LINE_FMT, "0000:00:00"); + ret = overwrite_file(history_file, linebuf); + if (ret < 0) { + LOGE("Write (%s, %s) failed, error (%s)\n", + history_file, linebuf, + strerror(errno)); + return ret; + } + ret = append_file(history_file, HISTORY_BLANK_LINE2); + if (ret < 0) { + LOGE("Write (%s, %s) failed, error (%s)\n", + history_file, HISTORY_BLANK_LINE2, + strerror(errno)); + return ret; + } + current_lines = count_lines_in_file(history_file); + } + + return 0; } diff --git a/tools/acrn-crashlog/acrnprobe/include/history.h b/tools/acrn-crashlog/acrnprobe/include/history.h index 2bda650a6..4e175f354 100644 --- a/tools/acrn-crashlog/acrnprobe/include/history.h +++ b/tools/acrn-crashlog/acrnprobe/include/history.h @@ -22,6 +22,14 @@ #ifndef __HISTORY_H__ #define __HISTORY_H__ +#define HISTORY_NAME "history_event" + +extern char *history_file; + +int prepare_history(void); void hist_raise_infoerror(char *type); +void hist_raise_uptime(char *lastuptime); +void hist_raise_event(char *event, char *type, char *log, char *lastuptime, + char *key); #endif