From 76bc7078e6cf7da6becbf28c48c8532268c9acc9 Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Wed, 12 Aug 2020 14:20:06 +0200 Subject: [PATCH] Only write missed AL logs on the first service start The AL backend is based on the kernel devices, which may be written to at any time. dlog_logger used to read the whole contents of the device on its start, which is the reasonable thing to do (we don't want to miss any logs) but bad for various reasons (for example, the same logs are written to the persistent logs file many times when the service is restarted). This patch makes it so that the device is only read in its entirety on the first start of the service after reboot; on every other start, all the logs existing in the device at the moment of the service start are skipped. Change-Id: I1eefd62191d66201ca74919d32b27aecbb1f621b --- configs/25-logger.conf | 5 +++++ configs/dlog-logger.conf.cpu | 2 ++ src/logger/logger.c | 31 +++++++++++++++++++++++++++++-- src/logger/logger_internal.h | 2 ++ tests/dlog_cpu.in | 3 +++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/configs/25-logger.conf b/configs/25-logger.conf index e2fb556..379e252 100644 --- a/configs/25-logger.conf +++ b/configs/25-logger.conf @@ -37,3 +37,8 @@ logger_dev_throttling=100 # total time to keep the daemon in the lazy mode permanently. Defaults to 0. lazy_polling_total_ms=-1 lazy_polling_sleep_ms=100 + +# File which will be used to check if the DLog daemon is run for the first time since last system restart. +# Note that this file must be in a directory that is not preserved across restarts! +# If empty or unset, the file won't be created and every run will be treated as first. +first_time_file_path=/run/dlog/first_time diff --git a/configs/dlog-logger.conf.cpu b/configs/dlog-logger.conf.cpu index f264e55..b4b696b 100644 --- a/configs/dlog-logger.conf.cpu +++ b/configs/dlog-logger.conf.cpu @@ -42,3 +42,5 @@ dynamic_config_path=/tmp/dlog-filters/ handle_kmsg=0 handle_syslog=0 + +first_time_file_path=/run/dlog/first_time diff --git a/src/logger/logger.c b/src/logger/logger.c index b856915..d0961a4 100644 --- a/src/logger/logger.c +++ b/src/logger/logger.c @@ -1058,6 +1058,11 @@ int service_reader_logger(struct reader_logger* reader, struct now_t time) else return -errno; } else { + if (reader->skip_count > 0) { + reader->skip_count -= r; + continue; + } + buffer[r] = '\0'; parse_androidlogger_message((struct android_logger_entry *) buffer, &entry.header, r); add_recv_timestamp(&entry.header, time); @@ -1304,7 +1309,7 @@ static int reader_pipe_init_with_writer(struct reader_pipe **reader, struct writ return 0; } -static int reader_logger_init(struct reader_logger **reader, log_id_t buf_id, struct logger *server) +static int reader_logger_init(struct reader_logger **reader, log_id_t buf_id, struct logger *server, bool skip) { assert(reader); assert(buf_id > LOG_ID_INVALID); @@ -1327,6 +1332,8 @@ static int reader_logger_init(struct reader_logger **reader, log_id_t buf_id, st if (r <= 0) return r; + ret->skip_count = skip ? logger_get_log_len(read_fd) : 0; + init_fd_entity(&ret->common.fd_entity_sink, dispatch_event_reader_logger, ret); init_fd_entity(&ret->common.fd_entity_source, dispatch_event_reader_logger, ret); set_read_fd_entity(&ret->common.fd_entity_source, read_fd); @@ -2284,12 +2291,29 @@ static int logger_create(struct logger_config_data *data, struct logger *l) l->qos.file_path = data->qos_file_path; data->qos_file_path = NULL; + // Check if the daemon is being launched for the first time since reboot + bool first_time; + if (data->first_time_file_path) { + int fd = open(data->first_time_file_path, O_CREAT | O_EXCL | O_RDONLY, 0644); + if (fd == -1) { + if (errno == EEXIST) + first_time = false; + else + return -errno; + } else { + first_time = true; + close(fd); + } + } else + // If no path, assume first time + first_time = true; + if (g_backend.use_logger_by_default) for (log_id_t id = 0; id < LOG_ID_MAX; ++id) { if (!is_core_buffer(id)) continue; - int r = reader_logger_init(g_backend.logger_readers + id, id, l); + int r = reader_logger_init(g_backend.logger_readers + id, id, l, !first_time); if (r < 0) return r; if (!g_backend.logger_readers[id]) @@ -2730,6 +2754,8 @@ int prepare_config_data(struct logger_config_data *data) if (!strcmp(qos_method, qos_methods[i].name)) qos_distribution_func = qos_methods[i].func; + const char *const first_time_file_path = log_config_get(&conf, "first_time_file_path"); + data->first_time_file_path = first_time_file_path ? strdup(first_time_file_path) : NULL; memset(data->is_buffer_enabled, 0, sizeof(data->is_buffer_enabled)); if (!strcmp(backend, "pipe")) { @@ -2782,6 +2808,7 @@ static void free_config_data(struct logger_config_data *data) list_remove_if(&data->logfile_configs, NULL, cond_string_free); free(data->dynamic_config_dir); free(data->qos_file_path); + free(data->first_time_file_path); } /** diff --git a/src/logger/logger_internal.h b/src/logger/logger_internal.h index 52b40fd..0e41d30 100644 --- a/src/logger/logger_internal.h +++ b/src/logger/logger_internal.h @@ -198,6 +198,7 @@ struct subreader_logger { struct reader_logger { list_head subs; log_id_t buf_id; + int skip_count; struct reader common; }; @@ -270,6 +271,7 @@ struct logger_config_data { int qos_limit_duration; int qos_threshold; int qos_threshold_reapply; + char *first_time_file_path; }; #ifdef __cplusplus diff --git a/tests/dlog_cpu.in b/tests/dlog_cpu.in index 0e9fdfc..9ba18c0 100644 --- a/tests/dlog_cpu.in +++ b/tests/dlog_cpu.in @@ -13,6 +13,9 @@ if [ "$1" = "pipe" ]; then type="pipe" elif [ "$1" = "logger" ]; then type="logger" + + # Make sure the newly launched daemon ignores old logs + touch /run/dlog/first_time else echo "usage: $0 pipe|logger" exit 1 -- 2.7.4