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 \
*/
// 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);
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;
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_;
}
/**
- * @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
#include "socket.h"
#include "dlogutil_line.h"
#include "log_buffer.h"
+#include "writer.h"
#ifdef __cplusplus
extern "C" {
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,
*/
-#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;
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
}
--- /dev/null
+#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;
+}
--- /dev/null
+#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
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);