From: Mateusz Majewski Date: Mon, 24 Aug 2020 10:31:35 +0000 (+0200) Subject: Split various writer related stuff to a separate file X-Git-Tag: accepted/tizen/unified/20200908.060805~29 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cf22798842919c54fcd58fac05a186dbc6725a47;p=platform%2Fcore%2Fsystem%2Fdlog.git Split various writer related stuff to a separate file Change-Id: I973e057119535f7a57a16c469900a6480eab5c8c --- diff --git a/Makefile.am b/Makefile.am index eaba195..9c47857 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/src/logger/logger.c b/src/logger/logger.c index 2895d92..04ae764 100644 --- a/src/logger/logger.c +++ b/src/logger/logger.c @@ -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 diff --git a/src/logger/logger_internal.h b/src/logger/logger_internal.h index 482a802..11bdd58 100644 --- a/src/logger/logger_internal.h +++ b/src/logger/logger_internal.h @@ -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 index 0000000..9ad8942 --- /dev/null +++ b/src/logger/writer.c @@ -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 index 0000000..3e41447 --- /dev/null +++ b/src/logger/writer.h @@ -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 diff --git a/src/tests/logger.c b/src/tests/logger.c index 34c9992..146b0e4 100644 --- a/src/tests/logger.c +++ b/src/tests/logger.c @@ -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);