Split various writer related stuff to a separate file 34/242134/2
authorMateusz Majewski <m.majewski2@samsung.com>
Mon, 24 Aug 2020 10:31:35 +0000 (12:31 +0200)
committerMichal Bloch <m.bloch@partner.samsung.com>
Mon, 24 Aug 2020 10:34:08 +0000 (10:34 +0000)
Change-Id: I973e057119535f7a57a16c469900a6480eab5c8c

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

index eaba195..9c47857 100644 (file)
@@ -135,6 +135,7 @@ dlog_logger_SOURCES = \
        src/logger/reader_logger.c \
        src/logger/reader_pipe.c \
        src/logger/socket.c \
+       src/logger/writer.c \
        src/shared/backend_androidlogger.c \
        src/shared/ptrs_list.c \
        src/shared/logcommon.c \
index 2895d92..04ae764 100644 (file)
@@ -34,9 +34,6 @@
  */
 
 // function prototypes
-int service_writer_kmsg(struct logger* server, struct writer* wr, struct epoll_event* event);
-int service_writer_syslog(struct logger* server, struct writer* wr, struct epoll_event* event);
-void dispatch_event_writer(struct logger *server, struct epoll_event *event, void *userdata);
 static void logger_free(struct logger* l);
 static int initialize_epoll_size(struct epoll_event **events, unsigned *size);
 
@@ -155,101 +152,6 @@ int reset_self_privileges()
        return 0;
 }
 
-/**
- * @brief Create a writer
- * @details Create a writer structure
- * @param[out] writer The newly-allocated writer
- * @param[in] fd The FD writer initially belongs to
- * @param[in] log_buffer The logging buffer
- * @param[in] service_writer callback function for handling new data on writer descriptor FD
- * @return 0 on success, -ENOMEM when out of memory
- */
-int writer_create(struct writer **writer, int fd, struct log_buffer *log_buffer,
-                                                service_writer_t service_writer, service_socket_t service_socket)
-{
-       struct writer *w = (struct writer *)calloc(1, sizeof(struct writer));
-       if (!w)
-               return -ENOMEM;
-
-       init_fd_entity(&w->fd_entity, dispatch_event_writer, w);
-       set_read_fd_entity(&w->fd_entity, fd);
-       w->buf_ptr = log_buffer;
-       w->readed = 0;
-       w->service_writer = service_writer;
-       w->service_socket = service_socket;
-
-       *writer = w;
-       return 0;
-}
-
-/**
- * @brief Dummy function placeholder that should not be called at all
- * @details Use this function as a service socket callback for writers that handle other resources than sockets
- *          This function is temporary and only for testing purposes
- * @param[in] server Unused
- * @param[in] wr Unused
- * @param[in] msg Unused
- * @return Will not return - just raises SIGABRT signal
- *
- * @todo Remove this function after unification of evant handling functionality of writers
- */
-int service_socket_dummy(struct logger *server, struct writer *wr, struct dlog_control_msg *msg) // LCOV_EXCL_START
-{
-       (void) msg;
-       (void) wr;
-       (void) server;
-       assert(0 && "This function should not be called");
-       return -1;
-} // LCOV_EXCL_STOP
-
-/**
- * @brief Create kmsg writer
- * @details Create the structure responsible for handling writing data from /dev/kmsg to given logging buffer
- * @param[out] writer The newly-allocated writer
- * @param[in] log_buffer The logging buffer
- * @return 0 on success, -errno on failure
- */
-int create_kmsg_writer(struct writer ** writer, struct log_buffer *log_buffer)
-{
-       int fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
-       if (fd < 0)
-               return -errno;
-
-       int ret = writer_create(writer, fd, log_buffer, service_writer_kmsg, service_socket_dummy);
-       if (ret != 0) {
-               close(fd);
-       }
-       return ret;
-}
-
-/**
- * @brief Create syslog writer
- * @details Create the structure responsible for handling writing data from syslog to given logging buffer
- * @param[out] writer The newly-allocated writer
- * @param[in] log_buffer The logging buffer
- * @return 0 on success, -errno on failure
- */
-int create_syslog_writer(struct writer ** writer, struct log_buffer *log_buffer)
-{
-       int fd = dev_log_sock_get();
-       if (fd < 0)
-               fd = dev_log_sock_create();
-       if (fd < 0)
-               return -errno;
-
-       int err = fd_set_flags(fd, O_NONBLOCK);
-       if (err < 0) {
-               close(fd);
-               return err;
-       }
-
-       int ret = writer_create(writer, fd, log_buffer, service_writer_syslog, service_socket_dummy);
-       if (ret != 0) {
-               close(fd);
-       }
-       return ret;
-}
-
 static bool cond_reader_pipe_free(void *ptr, void *user_data)
 {
        struct reader_pipe *reader = (struct reader_pipe *)ptr;
@@ -357,36 +259,6 @@ void check_if_fd_limit_reached(struct logger *server, int err)
                printf("ERROR: not enough memory either, please check platform settings as the daemon is seriously resource-starved!\n");
 }
 
-/**
- * @brief Writer close FD
- * @details Close a writer's connections
- * @param[in] server The logger server
- * @param[in] wr The writer whose connections to close
- */
-void writer_close_fd(struct logger* server, struct writer* wr)
-{
-       assert(wr);
-       remove_fd_entity(&server->epoll_common, &wr->fd_entity);
-
-       /* Note: the following can fail, since the entity may not be in the epoll.
-        * However, the kernel knows best whether it has to delete the entity or not,
-        * so we should just let it act on its knowledge. */
-       remove_fd_entity(&server->epoll_socket, &wr->fd_entity);
-
-       close(wr->fd_entity.fd);
-}
-
-/**
- * @brief Free writer
- * @details Deallocate a writer
- * @param[in] w The writer to deallocate
- */
-static void writer_free(struct writer *w, struct logger *logger)
-{
-       writer_close_fd(logger, w);
-       free(w);
-}
-
 void reader_notify_losing_log(const dlogutil_entry_s *le, void *reader_)
 {
        struct reader_pipe *reader = (struct reader_pipe *) reader_;
@@ -1023,27 +895,6 @@ static void logger_free(struct logger *l)
 }
 
 /**
- * @brief Dispatch writer event
- * @details Receives and handles an event
- * @param[in] server The logger server
- * @param[in] event The received event
- */
-void dispatch_event_writer(struct logger *server, struct epoll_event *event, void *userdata)
-{
-       assert(server);
-       assert(event);
-       struct writer *writer = (struct writer*) userdata;
-       assert(writer);
-
-       assert(writer->service_writer);
-       int r = writer->service_writer(server, writer, event);
-       if (r) {
-               list_remove(&server->writers, writer);
-               writer_free(writer, server);
-       }
-}
-
-/**
  * @brief Handle interrupting/terminating signals
  * @details Clears global flag to stop main loop
  * @param[in] signo signal number
index 482a802..11bdd58 100644 (file)
@@ -37,6 +37,7 @@
 #include "socket.h"
 #include "dlogutil_line.h"
 #include "log_buffer.h"
+#include "writer.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -94,19 +95,6 @@ extern struct backend_data {
        struct reader_logger *logger_readers[LOG_ID_MAX];
 } g_backend;
 
-struct logger;
-struct writer;
-
-/**
- * @brief Service a writer
- * @details Specific handler that event is delegated to, according to writers type
- * @param[in] server The logger server
- * @param[in] wr The writer to handle the request
- * @param[in] event The relevant event on file descriptor
- * @return 0 on success, else -errno
- */
-typedef int (*service_writer_t)(struct logger* server, struct writer* wr, struct epoll_event* event);
-
 
 /* Writers and readers can be a bit confusing in what they refer to.
  * Something that does write() calls is usually actually a reader,
@@ -138,17 +126,6 @@ typedef int (*service_writer_t)(struct logger* server, struct writer* wr, struct
  */
 
 
-#define LARGEST_STRUCT(a, b) (sizeof(struct a) > sizeof(struct b) ? sizeof(struct a) : sizeof(struct b))
-struct writer {
-       struct fd_entity   fd_entity;
-       struct log_buffer* buf_ptr;
-       unsigned           readed;
-       service_writer_t   service_writer;
-       service_socket_t   service_socket;
-       char               buffer[LOG_MAX_PAYLOAD_SIZE + LARGEST_STRUCT(android_logger_entry, pipe_logger_entry)];
-};
-#undef LARGEST_STRUCT
-
 struct logger {
        struct epoll_metadata epoll_common;
        struct epoll_metadata epoll_socket;
@@ -184,13 +161,12 @@ struct logger_config_data {
 void remove_reader_fd_entities(struct logger *server, struct reader *reader);
 void reader_deinit_common(struct reader *reader);
 void check_if_fd_limit_reached(struct logger *server, int err);
-int writer_create(struct writer **writer, int fd, struct log_buffer *log_buffer,
-                                                service_writer_t service_writer, service_socket_t service_socket);
+int service_writer_kmsg(struct logger* server, struct writer* wr, struct epoll_event* event);
 int service_writer_socket(struct logger* server, struct writer* wr, struct epoll_event* event);
+int service_writer_syslog(struct logger* server, struct writer* wr, struct epoll_event* event);
 void logger_add_writer(struct logger* l, struct writer* wr);
 int create_fifo_fds(struct logger *server, int fifo_id, int *write_fd, int *read_fd, bool dump);
 int add_reader_pipe(struct logger *server, struct reader_pipe *reader);
-void writer_close_fd(struct logger* server, struct writer* wr);
 
 #ifdef __cplusplus
 }
diff --git a/src/logger/writer.c b/src/logger/writer.c
new file mode 100644 (file)
index 0000000..9ad8942
--- /dev/null
@@ -0,0 +1,148 @@
+#include "writer.h"
+#include "logger_internal.h"
+
+/**
+ * @brief Dummy function placeholder that should not be called at all
+ * @details Use this function as a service socket callback for writers that handle other resources than sockets
+ *          This function is temporary and only for testing purposes
+ * @param[in] server Unused
+ * @param[in] wr Unused
+ * @param[in] msg Unused
+ * @return Will not return - just raises SIGABRT signal
+ *
+ * @todo Remove this function after unification of evant handling functionality of writers
+ */
+int service_socket_dummy(struct logger *server, struct writer *wr, struct dlog_control_msg *msg) // LCOV_EXCL_START
+{
+       (void) msg;
+       (void) wr;
+       (void) server;
+       assert(0 && "This function should not be called");
+       return -1;
+} // LCOV_EXCL_STOP
+
+/**
+ * @brief Writer close FD
+ * @details Close a writer's connections
+ * @param[in] server The logger server
+ * @param[in] wr The writer whose connections to close
+ */
+void writer_close_fd(struct logger* server, struct writer* wr)
+{
+       assert(wr);
+       remove_fd_entity(&server->epoll_common, &wr->fd_entity);
+
+       /* Note: the following can fail, since the entity may not be in the epoll.
+        * However, the kernel knows best whether it has to delete the entity or not,
+        * so we should just let it act on its knowledge. */
+       remove_fd_entity(&server->epoll_socket, &wr->fd_entity);
+
+       close(wr->fd_entity.fd);
+}
+
+/**
+ * @brief Free writer
+ * @details Deallocate a writer
+ * @param[in] w The writer to deallocate
+ */
+void writer_free(struct writer *w, struct logger *logger)
+{
+       writer_close_fd(logger, w);
+       free(w);
+}
+
+/**
+ * @brief Dispatch writer event
+ * @details Receives and handles an event
+ * @param[in] server The logger server
+ * @param[in] event The received event
+ */
+void dispatch_event_writer(struct logger *server, struct epoll_event *event, void *userdata)
+{
+       assert(server);
+       assert(event);
+       struct writer *writer = (struct writer*) userdata;
+       assert(writer);
+
+       assert(writer->service_writer);
+       int r = writer->service_writer(server, writer, event);
+       if (r) {
+               list_remove(&server->writers, writer);
+               writer_free(writer, server);
+       }
+}
+
+/**
+ * @brief Create a writer
+ * @details Create a writer structure
+ * @param[out] writer The newly-allocated writer
+ * @param[in] fd The FD writer initially belongs to
+ * @param[in] log_buffer The logging buffer
+ * @param[in] service_writer callback function for handling new data on writer descriptor FD
+ * @return 0 on success, -ENOMEM when out of memory
+ */
+int writer_create(struct writer **writer, int fd, struct log_buffer *log_buffer,
+                                                service_writer_t service_writer, service_socket_t service_socket)
+{
+       struct writer *w = (struct writer *)calloc(1, sizeof(struct writer));
+       if (!w)
+               return -ENOMEM;
+
+       init_fd_entity(&w->fd_entity, dispatch_event_writer, w);
+       set_read_fd_entity(&w->fd_entity, fd);
+       w->buf_ptr = log_buffer;
+       w->readed = 0;
+       w->service_writer = service_writer;
+       w->service_socket = service_socket;
+
+       *writer = w;
+       return 0;
+}
+
+/**
+ * @brief Create kmsg writer
+ * @details Create the structure responsible for handling writing data from /dev/kmsg to given logging buffer
+ * @param[out] writer The newly-allocated writer
+ * @param[in] log_buffer The logging buffer
+ * @return 0 on success, -errno on failure
+ */
+int create_kmsg_writer(struct writer ** writer, struct log_buffer *log_buffer)
+{
+       int fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
+       if (fd < 0)
+               return -errno;
+
+       int ret = writer_create(writer, fd, log_buffer, service_writer_kmsg, service_socket_dummy);
+       if (ret != 0) {
+               close(fd);
+       }
+       return ret;
+}
+
+/**
+ * @brief Create syslog writer
+ * @details Create the structure responsible for handling writing data from syslog to given logging buffer
+ * @param[out] writer The newly-allocated writer
+ * @param[in] log_buffer The logging buffer
+ * @return 0 on success, -errno on failure
+ */
+int create_syslog_writer(struct writer ** writer, struct log_buffer *log_buffer)
+{
+       int fd = dev_log_sock_get();
+       if (fd < 0)
+               fd = dev_log_sock_create();
+       if (fd < 0)
+               return -errno;
+
+       int err = fd_set_flags(fd, O_NONBLOCK);
+       if (err < 0) {
+               close(fd);
+               return err;
+       }
+
+       int ret = writer_create(writer, fd, log_buffer, service_writer_syslog, service_socket_dummy);
+       if (ret != 0) {
+               close(fd);
+       }
+       return ret;
+}
diff --git a/src/logger/writer.h b/src/logger/writer.h
new file mode 100644 (file)
index 0000000..3e41447
--- /dev/null
@@ -0,0 +1,34 @@
+#pragma once
+#include "socket.h"
+
+/**
+ * @brief Service a writer
+ * @details Specific handler that event is delegated to, according to writers type
+ * @param[in] server The logger server
+ * @param[in] wr The writer to handle the request
+ * @param[in] event The relevant event on file descriptor
+ * @return 0 on success, else -errno
+ */
+typedef int (*service_writer_t)(struct logger* server, struct writer* wr, struct epoll_event* event);
+
+#define LARGEST_STRUCT(a, b) (sizeof(struct a) > sizeof(struct b) ? sizeof(struct a) : sizeof(struct b))
+struct writer {
+       struct fd_entity   fd_entity;
+       struct log_buffer* buf_ptr;
+       unsigned           readed;
+       service_writer_t   service_writer;
+       service_socket_t   service_socket;
+       char               buffer[LOG_MAX_PAYLOAD_SIZE + LARGEST_STRUCT(android_logger_entry, pipe_logger_entry)];
+};
+#undef LARGEST_STRUCT
+
+int writer_create(struct writer **writer, int fd, struct log_buffer *log_buffer,
+                                                service_writer_t service_writer, service_socket_t service_socket);
+int create_kmsg_writer(struct writer ** writer, struct log_buffer *log_buffer);
+int create_syslog_writer(struct writer ** writer, struct log_buffer *log_buffer);
+void writer_close_fd(struct logger* server, struct writer* wr);
+void writer_free(struct writer *w, struct logger *logger);
+
+#ifdef UNIT_TEST
+void dispatch_event_writer(struct logger *server, struct epoll_event *event, void *userdata);
+#endif
index 34c9992..146b0e4 100644 (file)
@@ -17,8 +17,6 @@ int listen_fd_create(const char *path, int permissions);
 int systemd_sock_get(const char *path, int type);
 int dev_log_sock_get();
 int dev_log_sock_create();
-int writer_create(struct writer **writer, int fd, struct log_buffer *log_buffer, service_writer_t service_writer, service_socket_t service_socket);
-void dispatch_event_writer(struct logger *server, struct epoll_event *event, void *userdata);
 int create_kmsg_writer(struct writer **writer, struct log_buffer *log_buffer);
 int service_writer_kmsg(struct logger *server, struct writer *wr, struct epoll_event *event);
 int create_syslog_writer(struct writer **writer, struct log_buffer *log_buffer);