return;
}
- r = reader->service_reader(reader, now);
+ r = reader->ops->service(reader, now);
if (r > 0) {
reader_free(reader);
return;
return ret;
}
-void reader_common_init(struct reader_common *reader, struct logger *server)
+void reader_common_init(struct reader_common *reader, struct logger *server, const struct reader_ops *ops)
{
reader->server = server;
+ reader->ops = ops;
reader->thread = 0;
init_fd_entity(&reader->fd_entity_sink , NULL, NULL);
init_fd_entity(&reader->fd_entity_source, NULL, NULL);
if (r < 0)
goto reader_free;
- r = reader->service_reader(reader, now);
+ r = reader->ops->service(reader, now);
if (r != 0) {
/* This can happen for example if a pipe gets clogged,
* and is not necessarily a reason to remove the reader. */
int reader_run(struct reader_common *const reader)
{
pthread_t thread;
- int r = pthread_create(&thread, NULL, reader->thread_func, reader);
+ int r = pthread_create(&thread, NULL, reader->ops->thread_func, reader);
if (r < 0)
return r;
reader_flush(reader, (struct timespec){0, 0}, 0);
- reader->free_reader(reader);
+ reader->ops->destroy(reader);
reader_deinit_common(reader);
free(reader);
* └────────┘ └────────┘
*/
+struct reader_common;
+struct reader_ops {
+ int (*service) (struct reader_common *reader, struct now_t time);
+ void (*destroy) (struct reader_common *reader);
+ void *(*thread_func) (void *userdata);
+};
+
struct reader_common {
struct fd_entity fd_entity_sink;
struct fd_entity fd_entity_source;
struct logger *server;
-
+ const struct reader_ops *ops;
pthread_t thread; // note, pthread id, not the same as OS tid!
- void *(*thread_func)(void *userdata);
-
list_head subs;
- int (*service_reader) (struct reader_common *_reader, struct now_t time);
- void (*free_reader) (struct reader_common *reader);
};
struct subreader_common {
void reader_free(struct reader_common *reader);
void reader_free_ptr(void *reader);
void reader_add_sub(struct reader_common *reader, void *sub);
-void reader_common_init(struct reader_common *reader, struct logger *server);
+void reader_common_init(struct reader_common *reader, struct logger *server, const struct reader_ops *ops);
int reader_apply_log_to_subs(struct reader_common *reader, const struct dlogutil_entry *de);
void dispatch_event_reader(struct logger *server, struct epoll_event *event, void *userdata);
int reader_run(struct reader_common *const reader);
return 0;
}
+static const struct reader_ops logger_ops = (struct reader_ops) {
+ .service = service_reader_logger,
+ .destroy = free_reader_logger,
+ .thread_func = reader_logger_thread,
+};
+
static struct reader_logger *reader_logger_alloc(struct logger *server)
{
struct reader_logger *const ret = calloc(1, sizeof *ret);
/* The reader nominally belongs to the server,
* but is mostly handled by its own thread. */
- reader_common_init(&ret->common, server);
+ reader_common_init(&ret->common, server, &logger_ops);
ret->device_fd = -1;
ret->buf_id = LOG_ID_INVALID;
- ret->common.thread_func = reader_logger_thread;
- ret->common.service_reader = service_reader_logger;
- ret->common.free_reader = free_reader_logger;
return ret;
}
if (r < 0)
return;
- r = reader->common.service_reader(&reader->common, now);
+ r = reader->common.ops->service(&reader->common, now);
if (r > 0)
return;
static int print_out_logs(struct reader_common *_reader, struct now_t _time);
+static const struct reader_ops memory_ops = (struct reader_ops) {
+ .service = print_out_logs,
+ .destroy = reader_memory_free,
+};
+
static struct reader_memory *reader_memory_alloc(struct logger *server, bool monitor, bool is_dumping)
{
struct reader_memory *ret = calloc(1, sizeof(*ret));
if (!ret)
return NULL;
- reader_common_init(&ret->common, server);
-
- ret->common.free_reader = reader_memory_free;
+ reader_common_init(&ret->common, server, &memory_ops);
ret->uncompressed_chunk = malloc(COMPRESSION_CHUNK_SIZE);
if (!ret->uncompressed_chunk) {
ret->uncompressed_chunk_size = 0;
ret->uncompressed_chunk_index = 0;
- ret->common.service_reader = print_out_logs;
ret->monitor = monitor;
ret->is_dumping = is_dumping;
ret->log_compressed_storage_reader_ptr = NULL;
reader_pipe_print_out_single_log(reader, (dlogutil_entry_s *)le);
}
+static const struct reader_ops pipe_ops = (struct reader_ops) {
+ .service = print_out_logs,
+ .destroy = reader_pipe_free,
+};
+
static struct reader_pipe *reader_pipe_alloc(struct logger *server, bool monitor, bool is_dumping)
{
struct reader_pipe *ret = calloc(1, sizeof(*ret));
if (!ret)
return NULL;
- reader_common_init(&ret->common, server);
-
- ret->common.free_reader = reader_pipe_free;
- ret->common.service_reader = print_out_logs;
+ reader_common_init(&ret->common, server, &pipe_ops);
for (log_id_t i = 0; i < NELEMS(ret->log_storage_reader_ptrs); ++i)
ret->log_storage_reader_ptrs[i] = NULL;
sock.fd_entity.fd = 0;
socket_close(&sock);
+ struct reader_ops test_ops = {
+ .destroy = reader_free_empty,
+ };
+
struct reader_pipe *reader = calloc(1, sizeof(*reader));
assert(reader);
- reader_common_init(&reader->common, &logger);
- reader->common.free_reader = reader_free_empty;
+ reader_common_init(&reader->common, &logger, &test_ops);
reader_free(&reader->common);
assert(last_free == reader);