mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-23 14:07:42 +00:00
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 <xinwu.liu@intel.com> Reviewed-by: Zhang Yanmin <yanmin.zhang@intel.com> Reviewed-by: Liu Chuansheng <chuansheng.liu@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Reviewed-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com> Acked-by: Eddie Dong <Eddie.dong@intel.com>
This commit is contained in:
parent
384c195faa
commit
2cea6129eb
@ -19,8 +19,267 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "fsutils.h"
|
||||||
|
#include "load_conf.h"
|
||||||
#include "history.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;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@
|
|||||||
#ifndef __HISTORY_H__
|
#ifndef __HISTORY_H__
|
||||||
#define __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_infoerror(char *type);
|
||||||
|
void hist_raise_uptime(char *lastuptime);
|
||||||
|
void hist_raise_event(char *event, char *type, char *log, char *lastuptime,
|
||||||
|
char *key);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user