Move various reader_logger relate things to a separate file 01/242001/1
authorMateusz Majewski <m.majewski2@samsung.com>
Fri, 21 Aug 2020 09:07:01 +0000 (11:07 +0200)
committerMateusz Majewski <m.majewski2@samsung.com>
Fri, 21 Aug 2020 09:07:01 +0000 (11:07 +0200)
Change-Id: I80de86306dc906da8890554320c09d4ff746606b

Makefile.am
src/logger/logger.c
src/logger/logger_internal.h
src/logger/reader_logger.c [new file with mode: 0644]
src/logger/reader_logger.h [new file with mode: 0644]

index 7887832..292008f 100644 (file)
@@ -130,6 +130,7 @@ dlog_logger_SOURCES = \
        src/logger/qos.c \
        src/logger/qos_distributions.c \
        src/logger/reader_common.c \
+       src/logger/reader_logger.c \
        src/logger/reader_pipe.c \
        src/shared/backend_androidlogger.c \
        src/shared/ptrs_list.c \
index 410623c..b3eec70 100644 (file)
@@ -42,8 +42,6 @@ static int service_writer_handle_req_ctrl(struct logger *server, struct writer *
 static int service_writer_handle_req_pipe(struct logger *server, struct writer *wr, struct dlog_control_msg *msg);
 void dispatch_event_writer(struct logger *server, struct epoll_event *event, void *userdata);
 void dispatch_event_sock(struct logger *server, struct epoll_event *event, void *userdata);
-static void dispatch_event_reader_logger(struct logger *server, struct epoll_event *event, void *userdata);
-static void reader_logger_free(struct reader_logger *reader);
 static void logger_free(struct logger* l);
 int socket_initialize(struct sock_data *sock, struct log_buffer *buffer, service_socket_t service_socket, struct socket_config_data *data);
 static int initialize_epoll_size(struct epoll_event **events, unsigned *size);
@@ -51,13 +49,6 @@ static int initialize_epoll_size(struct epoll_event **events, unsigned *size);
 /** global state when logger is not interrupted by any handled signals */
 static volatile sig_atomic_t g_logger_run = 1;
 
-static struct {
-       bool use_logger_by_default;
-       char logger_devices[LOG_ID_MAX][MAX_CONF_VAL_LEN];
-       int logger_device_throttling[LOG_ID_MAX];
-       struct reader_logger *logger_readers[LOG_ID_MAX];
-} g_backend = {};
-
 static const int DEFAULT_EPOLL_TIME_MS = 1000;
 
 static const int DEFAULT_LAZY_POLLING_TOTAL_MS = 0;
@@ -66,6 +57,8 @@ static const int DEFAULT_LAZY_POLLING_SLEEP_MS = 1000;
 static const int S_TO_MS = 1000;
 static const int MS_TO_NS = 1000000;
 
+struct backend_data g_backend = {};
+
 /**
  * @brief Parse permissions
  * @details Parse a string representation of permissions to the internal integral one
@@ -562,133 +555,6 @@ static void writer_free(struct writer *w, struct logger *logger)
        free(w);
 }
 
-static void subreader_logger_metrics_apply_log(const struct subreader_logger *srl, const struct dlogutil_entry *due)
-{
-       assert(srl);
-       assert(due);
-
-       struct subreader_logger_metrics *const srlm = (struct subreader_logger_metrics *) srl->sub_userdata;
-       assert(srlm);
-
-       qos_add_log(srlm->qos, due);
-}
-
-static void subreader_logger_metrics_free(void *userdata)
-{
-       // nothing to do; we're just a wrapper over a weak (shared) pointer
-}
-
-static void subreader_logger_file_apply_log(const struct subreader_logger *srl, const struct dlogutil_entry *due)
-{
-       assert(srl);
-       assert(due);
-
-       struct subreader_logger_file *const srlf = (struct subreader_logger_file *) srl->sub_userdata;
-       assert(srlf);
-
-       logfile_write_with_rotation(due, &srlf->file, DLOGUTIL_SORT_SENT_REAL);
-}
-
-static void subreader_logger_file_free(void *userdata)
-{
-       struct subreader_logger_file *const srlf = (struct subreader_logger_file *) userdata;
-       assert(srlf);
-
-       logfile_free(&srlf->file);
-}
-
-static void subreader_logger_free(void *sub, void *userdata)
-{
-       struct subreader_logger *const srl = (struct subreader_logger *) sub;
-       assert(srl);
-       assert(userdata == NULL);
-
-       srl->sub_destroy(srl->sub_userdata);
-       if (srl->filter)
-               log_filter_free(srl->filter);
-       free(srl->sub_userdata);
-}
-
-static void subreader_logger_apply_log(void *sub, void *userdata)
-{
-       struct subreader_logger *const srl = (struct subreader_logger *) sub;
-       assert(srl);
-
-       const struct dlogutil_entry *const due = (const struct dlogutil_entry *) userdata;
-       assert(due);
-
-       if (!log_should_print_line(srl->filter, due))
-               return;
-
-       srl->sub_apply_log(srl, due);
-}
-
-static void reader_logger_free(struct reader_logger *reader)
-{
-       if (!reader)
-               return;
-
-       reader_deinit_common(&reader->common);
-       list_clear_custom(&reader->subs, NULL, subreader_logger_free);
-       free(reader);
-}
-
-void reader_logger_cleanup(struct reader_logger *const *ptr)
-{
-       assert(ptr);
-       reader_logger_free(*ptr);
-}
-
-/**
- * @brief Service reader file
- * @details Handles readers reading directly from file
- * @param[in] reader The reader to service
- * @param[in] time Timestamps
- * @return 0 on success, else an errno value
- * @return 1 if the reader is to be removed, 0 if kept, -errno on error
- */
-int service_reader_logger(struct reader_logger* reader, struct now_t time)
-{
-       assert(reader);
-
-       struct dlogutil_entry_with_msg entry;
-       static char buffer[sizeof entry + 1];
-       buffer[sizeof buffer - 1] = '\0';
-
-       /* The devices for the Android Logger only return one log per read().
-        * So using an 'if' here would be wasteful and, more importantly, too slow in the case where other logs come in.
-        * However, with an unlimited loop, if there are extreme amounts of logs incoming,
-        * the loop handles them slower than they come so the program stays in the loop
-        * for a very long time, starving all other log sources. Using a limited loop
-        * makes sure that the daemon works efficiently in the usual case while preventing
-        * starvation under heavy load. */
-       int max_loop_iterations = g_backend.logger_device_throttling[reader->buf_id];
-       while (max_loop_iterations--) {
-               int r = TEMP_FAILURE_RETRY(read(reader->common.fd_entity_source.fd, buffer, sizeof buffer - 1));
-               if (r == 0)
-                       break;
-               else if (r == -1) {
-                       if (errno == EAGAIN) // no data left in the buffer
-                               break;
-                       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);
-
-                       list_foreach(reader->subs, &entry.header, subreader_logger_apply_log);
-               }
-       }
-
-       return 0;
-}
-
 void reader_notify_losing_log(const dlogutil_entry_s *le, void *reader_)
 {
        struct reader_pipe *reader = (struct reader_pipe *) reader_;
@@ -794,103 +660,6 @@ failure:
        return ret;
 }
 
-static struct reader_logger *reader_logger_alloc()
-{
-       struct reader_logger *const ret = calloc(1, sizeof *ret);
-       if (!ret)
-               return NULL;
-
-       ret->buf_id = LOG_ID_INVALID;
-
-       return ret;
-}
-
-static int reader_logger_add_subreader_file(struct reader_logger *reader, dlogutil_filter_options_s *filter, struct log_file *file)
-{
-       assert(reader);
-       assert(filter);
-
-       struct subreader_logger *const srl = malloc(sizeof *srl);
-       struct subreader_logger_file *const srlf = malloc(sizeof *srlf);
-       if (!srl || !srlf) {
-               free(srl);
-               free(srlf);
-               return -ENOMEM;
-       }
-
-       logfile_move(&srlf->file, file);
-
-       srl->sub_userdata = srlf;
-       srl->sub_destroy = subreader_logger_file_free;
-       srl->sub_apply_log = subreader_logger_file_apply_log;
-       srl->filter = log_filter_move(filter);
-
-       list_add(&reader->subs, srl);
-
-       return 0;
-}
-
-static int reader_logger_add_subreader_metrics(struct reader_logger *reader, struct qos_module *qos)
-{
-       assert(reader);
-       assert(qos);
-
-       struct subreader_logger *const srl = malloc(sizeof *srl);
-       struct subreader_logger_metrics *const srlm = malloc(sizeof *srlm);
-       dlogutil_filter_options_s *const filter = log_filter_new();
-       if (!srl || !srlm || !filter || dlogutil_filter_options_set_filterspec(filter, "*:V")) {
-               free(srl);
-               free(srlm);
-               log_filter_free(filter);
-               return -ENOMEM;
-       }
-
-       srlm->qos = qos;
-
-       srl->sub_userdata = srlm;
-       srl->sub_destroy = subreader_logger_metrics_free;
-       srl->sub_apply_log = subreader_logger_metrics_apply_log;
-       srl->filter = filter;
-
-       list_add(&reader->subs, srl);
-
-       return 0;
-}
-
-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);
-       assert(buf_id < LOG_ID_MAX);
-       assert(is_core_buffer(buf_id));
-       assert(server);
-
-       __attribute__((cleanup(reader_logger_cleanup))) struct reader_logger *ret = reader_logger_alloc();
-       if (!ret)
-               return -ENOMEM;
-
-       assert(buf_id >= 0 && (unsigned) buf_id < NELEMS(g_backend.logger_devices));
-       char const *config_list = g_backend.logger_devices[buf_id];
-       if (strlen(config_list) == 0)
-               return -ENOENT;
-       ret->buf_id = buf_id;
-
-       int read_fd = -1;
-       int r = logger_open_buffer(buf_id, config_list, O_RDONLY | O_NONBLOCK, &read_fd);
-       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);
-
-       *reader = ret;
-       ret = NULL;
-       return 0;
-}
-
 static int create_fifo_fds(struct logger *server, int fifo_id, int *write_fd, int *read_fd, bool dump)
 {
        assert(write_fd);
@@ -1642,26 +1411,6 @@ static bool cond_service_reader_logger(void *ptr, void *user_data)
        return false;
 }
 
-static void dispatch_event_reader_logger(struct logger *server, struct epoll_event *event, void *userdata)
-{
-       struct reader_logger *const rl = (struct reader_logger *) userdata;
-       assert(rl);
-
-       if (event->events & (EPOLLHUP | EPOLLERR)) {
-               remove_reader_fd_entities(server, &rl->common);
-               list_remove(&server->readers_logger, rl);
-               reader_logger_free(rl);
-               return;
-       }
-
-       int r = service_reader_logger(rl, server->time);
-       if (r != 0) {
-               /* TODO: There is no reason not to free the reader in full. However, when I do so, some tests start to
-                * fail without any reasonable reason. You are welcome to *try* to figure out why does this happen. */
-               remove_reader_fd_entities(server, &rl->common);
-       }
-}
-
 /**
  * @brief Service syslog
  * @details Read from the syslog socket
index 5555f5f..6df7103 100644 (file)
@@ -32,6 +32,7 @@
 #include "qos.h"
 #include "fd_entity.h"
 #include "reader_common.h"
+#include "reader_logger.h"
 #include "reader_pipe.h"
 
 #ifdef __cplusplus
@@ -83,6 +84,13 @@ enum {
        LOGGER_DEVICE_THROTTLING_DEFAULT = 100,
 };
 
+extern struct backend_data {
+       bool use_logger_by_default;
+       char logger_devices[LOG_ID_MAX][MAX_CONF_VAL_LEN];
+       int logger_device_throttling[LOG_ID_MAX];
+       struct reader_logger *logger_readers[LOG_ID_MAX];
+} g_backend;
+
 struct logger;
 struct writer;
 
@@ -148,28 +156,6 @@ struct writer {
 };
 #undef LARGEST_STRUCT
 
-struct subreader_logger_file {
-       struct log_file file;
-};
-
-struct subreader_logger_metrics {
-       struct qos_module *qos;
-};
-
-struct subreader_logger {
-       void (*sub_apply_log)(const struct subreader_logger *srl, const struct dlogutil_entry *due);
-       void (*sub_destroy)(void *sub_userdata);
-       void *sub_userdata;
-       dlogutil_filter_options_s *filter;
-};
-
-struct reader_logger {
-       list_head subs;
-       log_id_t buf_id;
-       int skip_count;
-       struct reader common;
-};
-
 struct sock_data {
        struct fd_entity   fd_entity;
        struct log_buffer* buf_ptr;
diff --git a/src/logger/reader_logger.c b/src/logger/reader_logger.c
new file mode 100644 (file)
index 0000000..1f4fb52
--- /dev/null
@@ -0,0 +1,246 @@
+#include "reader_logger.h"
+#include "logger_internal.h"
+
+static void subreader_logger_metrics_apply_log(const struct subreader_logger *srl, const struct dlogutil_entry *due)
+{
+       assert(srl);
+       assert(due);
+
+       struct subreader_logger_metrics *const srlm = (struct subreader_logger_metrics *) srl->sub_userdata;
+       assert(srlm);
+
+       qos_add_log(srlm->qos, due);
+}
+
+static void subreader_logger_metrics_free(void *userdata)
+{
+       // nothing to do; we're just a wrapper over a weak (shared) pointer
+}
+
+static void subreader_logger_file_apply_log(const struct subreader_logger *srl, const struct dlogutil_entry *due)
+{
+       assert(srl);
+       assert(due);
+
+       struct subreader_logger_file *const srlf = (struct subreader_logger_file *) srl->sub_userdata;
+       assert(srlf);
+
+       logfile_write_with_rotation(due, &srlf->file, DLOGUTIL_SORT_SENT_REAL);
+}
+
+static void subreader_logger_file_free(void *userdata)
+{
+       struct subreader_logger_file *const srlf = (struct subreader_logger_file *) userdata;
+       assert(srlf);
+
+       logfile_free(&srlf->file);
+}
+
+static void subreader_logger_free(void *sub, void *userdata)
+{
+       struct subreader_logger *const srl = (struct subreader_logger *) sub;
+       assert(srl);
+       assert(userdata == NULL);
+
+       srl->sub_destroy(srl->sub_userdata);
+       if (srl->filter)
+               log_filter_free(srl->filter);
+       free(srl->sub_userdata);
+}
+
+static void subreader_logger_apply_log(void *sub, void *userdata)
+{
+       struct subreader_logger *const srl = (struct subreader_logger *) sub;
+       assert(srl);
+
+       const struct dlogutil_entry *const due = (const struct dlogutil_entry *) userdata;
+       assert(due);
+
+       if (!log_should_print_line(srl->filter, due))
+               return;
+
+       srl->sub_apply_log(srl, due);
+}
+void reader_logger_free(struct reader_logger *reader)
+{
+       if (!reader)
+               return;
+
+       reader_deinit_common(&reader->common);
+       list_clear_custom(&reader->subs, NULL, subreader_logger_free);
+       free(reader);
+}
+
+void reader_logger_cleanup(struct reader_logger *const *ptr)
+{
+       assert(ptr);
+       reader_logger_free(*ptr);
+}
+
+/**
+ * @brief Service reader file
+ * @details Handles readers reading directly from file
+ * @param[in] reader The reader to service
+ * @param[in] time Timestamps
+ * @return 0 on success, else an errno value
+ * @return 1 if the reader is to be removed, 0 if kept, -errno on error
+ */
+int service_reader_logger(struct reader_logger* reader, struct now_t time)
+{
+       assert(reader);
+
+       struct dlogutil_entry_with_msg entry;
+       static char buffer[sizeof entry + 1];
+       buffer[sizeof buffer - 1] = '\0';
+
+       /* The devices for the Android Logger only return one log per read().
+        * So using an 'if' here would be wasteful and, more importantly, too slow in the case where other logs come in.
+        * However, with an unlimited loop, if there are extreme amounts of logs incoming,
+        * the loop handles them slower than they come so the program stays in the loop
+        * for a very long time, starving all other log sources. Using a limited loop
+        * makes sure that the daemon works efficiently in the usual case while preventing
+        * starvation under heavy load. */
+       int max_loop_iterations = g_backend.logger_device_throttling[reader->buf_id];
+       while (max_loop_iterations--) {
+               int r = TEMP_FAILURE_RETRY(read(reader->common.fd_entity_source.fd, buffer, sizeof buffer - 1));
+               if (r == 0)
+                       break;
+               else if (r == -1) {
+                       if (errno == EAGAIN) // no data left in the buffer
+                               break;
+                       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);
+
+                       list_foreach(reader->subs, &entry.header, subreader_logger_apply_log);
+               }
+       }
+
+       return 0;
+}
+
+static struct reader_logger *reader_logger_alloc()
+{
+       struct reader_logger *const ret = calloc(1, sizeof *ret);
+       if (!ret)
+               return NULL;
+
+       ret->buf_id = LOG_ID_INVALID;
+
+       return ret;
+}
+
+int reader_logger_add_subreader_file(struct reader_logger *reader, dlogutil_filter_options_s *filter, struct log_file *file)
+{
+       assert(reader);
+       assert(filter);
+
+       struct subreader_logger *const srl = malloc(sizeof *srl);
+       struct subreader_logger_file *const srlf = malloc(sizeof *srlf);
+       if (!srl || !srlf) {
+               free(srl);
+               free(srlf);
+               return -ENOMEM;
+       }
+
+       logfile_move(&srlf->file, file);
+
+       srl->sub_userdata = srlf;
+       srl->sub_destroy = subreader_logger_file_free;
+       srl->sub_apply_log = subreader_logger_file_apply_log;
+       srl->filter = log_filter_move(filter);
+
+       list_add(&reader->subs, srl);
+
+       return 0;
+}
+
+int reader_logger_add_subreader_metrics(struct reader_logger *reader, struct qos_module *qos)
+{
+       assert(reader);
+       assert(qos);
+
+       struct subreader_logger *const srl = malloc(sizeof *srl);
+       struct subreader_logger_metrics *const srlm = malloc(sizeof *srlm);
+       dlogutil_filter_options_s *const filter = log_filter_new();
+       if (!srl || !srlm || !filter || dlogutil_filter_options_set_filterspec(filter, "*:V")) {
+               free(srl);
+               free(srlm);
+               log_filter_free(filter);
+               return -ENOMEM;
+       }
+
+       srlm->qos = qos;
+
+       srl->sub_userdata = srlm;
+       srl->sub_destroy = subreader_logger_metrics_free;
+       srl->sub_apply_log = subreader_logger_metrics_apply_log;
+       srl->filter = filter;
+
+       list_add(&reader->subs, srl);
+
+       return 0;
+}
+
+static void dispatch_event_reader_logger(struct logger *server, struct epoll_event *event, void *userdata)
+{
+       struct reader_logger *const rl = (struct reader_logger *) userdata;
+       assert(rl);
+
+       if (event->events & (EPOLLHUP | EPOLLERR)) {
+               remove_reader_fd_entities(server, &rl->common);
+               list_remove(&server->readers_logger, rl);
+               reader_logger_free(rl);
+               return;
+       }
+
+       int r = service_reader_logger(rl, server->time);
+       if (r != 0) {
+               /* TODO: There is no reason not to free the reader in full. However, when I do so, some tests start to
+                * fail without any reasonable reason. You are welcome to *try* to figure out why does this happen. */
+               remove_reader_fd_entities(server, &rl->common);
+       }
+}
+
+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);
+       assert(buf_id < LOG_ID_MAX);
+       assert(is_core_buffer(buf_id));
+       assert(server);
+
+       __attribute__((cleanup(reader_logger_cleanup))) struct reader_logger *ret = reader_logger_alloc();
+       if (!ret)
+               return -ENOMEM;
+
+       assert(buf_id >= 0 && (unsigned) buf_id < NELEMS(g_backend.logger_devices));
+       char const *config_list = g_backend.logger_devices[buf_id];
+       if (strlen(config_list) == 0)
+               return -ENOENT;
+       ret->buf_id = buf_id;
+
+       int read_fd = -1;
+       int r = logger_open_buffer(buf_id, config_list, O_RDONLY | O_NONBLOCK, &read_fd);
+       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);
+
+       *reader = ret;
+       ret = NULL;
+       return 0;
+}
+
diff --git a/src/logger/reader_logger.h b/src/logger/reader_logger.h
new file mode 100644 (file)
index 0000000..ea7ef4a
--- /dev/null
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <log_file.h>
+#include <queued_entry_timestamp.h>
+#include "reader_common.h"
+
+struct subreader_logger_file {
+       struct log_file file;
+};
+
+struct subreader_logger_metrics {
+       struct qos_module *qos;
+};
+
+struct subreader_logger {
+       void (*sub_apply_log)(const struct subreader_logger *srl, const struct dlogutil_entry *due);
+       void (*sub_destroy)(void *sub_userdata);
+       void *sub_userdata;
+       dlogutil_filter_options_s *filter;
+};
+
+struct reader_logger {
+       list_head subs;
+       log_id_t buf_id;
+       int skip_count;
+       struct reader common;
+};
+
+int reader_logger_init(struct reader_logger **reader, log_id_t buf_id, struct logger *server, bool skip);
+int service_reader_logger(struct reader_logger* reader, struct now_t time);
+int reader_logger_add_subreader_file(struct reader_logger *reader, dlogutil_filter_options_s *filter, struct log_file *file);
+int reader_logger_add_subreader_metrics(struct reader_logger *reader, struct qos_module *qos);
+void reader_logger_free(struct reader_logger *reader);
+void reader_logger_cleanup(struct reader_logger *const *ptr);