From 9abf935040bd368c4b3c1828a79691d200fd45a9 Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Thu, 31 Oct 2013 21:22:45 +0200 Subject: [PATCH] Convert data reading into event based system As of preparing for the future, convert the data reading into an even based system. The main loop has got the loop that holds the state of the logging process. All other modules then register itself into the event system where they get called back whenever data gets feed in into their file descriptors. Signed-off-by: Timo Kokkonen --- Makefile | 2 +- data.c | 171 ++++++++++++++++++++++++++++--------------------------- data.h | 2 +- event.c | 98 +++++++++++++++++++++++++++++++ event.h | 15 +++++ main.c | 8 ++- utils.h | 10 ++++ 7 files changed, 220 insertions(+), 86 deletions(-) create mode 100644 event.c create mode 100644 event.h diff --git a/Makefile b/Makefile index f770686..68d2e64 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC=gcc LD=ld CFLAGS=-Wall -O2 -g -fPIC -LOG-PLOTTER_OBJS = baud.o main.o options.o trace.o data.o config.o +LOG-PLOTTER_OBJS = baud.o main.o options.o trace.o data.o config.o event.o ALL_OBJS = $(LOG-PLOTTER_OBJS) ALL_DEBS = $(patsubst %.o,.%.o.d,$(ALL_OBJS)) diff --git a/data.c b/data.c index fa37072..81a8345 100644 --- a/data.c +++ b/data.c @@ -11,8 +11,18 @@ #include "data.h" #include "trace.h" +#include "event.h" #include "utils.h" - +#include "event.h" + +struct dataparser_struct { + struct eventhandler_entry evhandler; + int infd; + int outfd; + int offset; + time_t start_time; + char buf[256]; +}; static int separate_entries(char *buf, char *entries[], int max_entries) { @@ -238,107 +248,102 @@ static int read_log_line(int infd, char *buf, size_t bufsize, int *offset) return 0; } -int read_data(int infd, int outfd) +static int read_data(struct eventhandler_entry *h) { - struct epoll_event ev; - time_t start_time = 0, cur_time; - int epoll_fd; + struct dataparser_struct *dt; + time_t cur_time; int ret; - char buf[256]; - int offset = 0; + struct charger_data data; + char str[320]; + int len; - epoll_fd = epoll_create(1); - if (epoll_fd < 0) { - pr_err("Failed to create epoll socket: %m\n"); - return -1; - } + dt = container_of(h, struct dataparser_struct, evhandler); - ev.events = EPOLLIN; - ev.data.fd = infd; - if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, infd, &ev) == -1) { - pr_err("epoll_ctl: %m\n"); - return 1; - } + ret = read_log_line(dt->infd, dt->buf, sizeof(dt->buf), &dt->offset); + pr_debug("Line now %d: %s\n", dt->offset, dt->buf); + if (ret <= 0) + return ret; - while (1) { - struct charger_data data; - char str[320]; - int len; + if (ret == 0) + pr_err("%s %s: EOF\n", __FILE__, __func__); - ret = epoll_wait(epoll_fd, &ev, 1, -1); - if (ret == 0) - continue; - - if (ret < 0) { - pr_err("epoll: %m\n"); - return -1; - } + if (strlen(dt->buf) < 5) { + pr_debug("discarding truncated log entry\n"); + dt->offset = 0; + return 0; + } - ret = read_log_line(infd, buf, sizeof(buf), &offset); - if (ret < 0) - return ret; + if (!dt->start_time) + dt->start_time = time(NULL); - if (ret == 0) - continue; + cur_time = time(NULL); - if (strlen(buf) < 5) { - pr_debug("discarding truncated log entry\n"); - offset = 0; - continue; - } + parse_logline(dt->buf, &data); - if (!start_time) - start_time = time(NULL); + /* Fill in possibly missing timestamp */ + if (isnan(data.timestamp) || data.timestamp == 0) + data.timestamp = cur_time - dt->start_time; - cur_time = time(NULL); + print_status_line(&data); - parse_logline(buf, &data); + dump_data(&data); - /* Fill in possibly missing timestamp */ - if (isnan(data.timestamp) || data.timestamp == 0); - data.timestamp = cur_time - start_time; + if (!dt->outfd) + return 0; - print_status_line(&data); + len = snprintf(str, sizeof(str), + "%d;%d;%.1f;" + "%.3f;%.3f;%.3f;" + "%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;" + "%.f;%.1f;%.1f\n", /* mAh, and temp */ + data.channel, + data.state, + data.timestamp, - dump_data(&data); + data.input_voltage, + data.charging_voltage, + data.charging_current, - if (!outfd) - continue; + data.cell_voltage[0], + data.cell_voltage[1], + data.cell_voltage[2], + data.cell_voltage[3], + data.cell_voltage[4], + data.cell_voltage[5], + data.cell_voltage[6], + data.cell_voltage[7], + data.cell_voltage[8], + data.cell_voltage[9], + data.int_temp, + data.ext_temp, + data.total_charge); - len = snprintf(str, sizeof(str), - "%d;%d;%.1f;" - "%.3f;%.3f;%.3f;" - "%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;" - "%.f;%.1f;%.1f\n", /* mAh, and temp */ - data.channel, - data.state, - data.timestamp, - - data.input_voltage, - data.charging_voltage, - data.charging_current, - - data.cell_voltage[0], - data.cell_voltage[1], - data.cell_voltage[2], - data.cell_voltage[3], - data.cell_voltage[4], - data.cell_voltage[5], - data.cell_voltage[6], - data.cell_voltage[7], - data.cell_voltage[8], - data.cell_voltage[9], - data.int_temp, - data.ext_temp, - data.total_charge); - - ret = write(outfd, str, len); - if (ret < 0) { - pr_err("write: %m\n"); - break; - } + ret = write(dt->outfd, str, len); + if (ret < 0) { + pr_err("write: %m\n"); + return -1;; } return 0; } +static struct dataparser_struct dataparser = { + .evhandler.name = "OpenLog Parser", + .evhandler.events = EPOLLIN, + .evhandler.handle_event = read_data, +}; + +int init_data_parser(int infd, int outfd) +{ + int ret; + + dataparser.evhandler.fd = infd; + dataparser.infd = infd; + dataparser.outfd = outfd; + + ret = register_event_handler(&dataparser.evhandler); + if (ret < 0) + return 1; + + return 0; +} diff --git a/data.h b/data.h index 459ee66..90934a1 100644 --- a/data.h +++ b/data.h @@ -17,6 +17,6 @@ struct charger_data { double ext_temp; }; -int read_data(int infd, int outfd); +int init_data_parser(int infd, int outfd); #endif diff --git a/event.c b/event.c new file mode 100644 index 0000000..b3cbaf2 --- /dev/null +++ b/event.c @@ -0,0 +1,98 @@ +#include +#include + +#include "event.h" +#include "trace.h" + +static int epoll_fd = -1; + +static int init_event_handler(void) +{ + epoll_fd = epoll_create(1); + if (epoll_fd < 0) { + pr_err("Failed to create epoll socket: %m\n"); + return -1; + } + + return 0; +} + +int register_event_handler(struct eventhandler_entry *handler) +{ + struct epoll_event ev; + int ret = 0; + + if (epoll_fd < 0) + ret = init_event_handler(); + + if (ret < 0) + return ret; + + if (handler->fd < 0) { + pr_err("Invalid file descriptor of %d for handler %s\n", + handler->fd, handler->name); + return -1; + } + + if (!handler->handle_event) { + pr_err("Handler %s missing callback function\n", handler->name); + return -1; + } + + pr_debug("Registering handler for \"%s\", fd=%d\n", + handler->name, handler->fd); + + ev.data.fd = handler->fd; + ev.data.ptr = handler; + ev.events = handler->events; + ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, handler->fd, &ev); + if (ret) { + pr_err("Failed to add epoll_fd: %m\n"); + return -1; + } + + return 0; +} + +int poll_events(int timeout_ms) +{ + struct epoll_event event; + struct eventhandler_entry *handler; + int ret; + + ret = epoll_wait(epoll_fd, &event, 1, timeout_ms); + + if (ret == -1) { + if (errno != EINTR) { + pr_err("epoll_wait: %m\n"); + return -1; + } + + /* + * If epoll_wait() was interrupted, better start + * everything again from the beginning + */ + return 0; + } + + if (ret == 0) { + pr_info("Timed out\n"); + goto out; + } + + handler = event.data.ptr; + + if (!handler || !handler->handle_event) { + pr_err("Corrupted event handler for fd %d\n", + event.data.fd); + goto out; + } + + pr_debug("Running handler %s to handle events from fd %d\n", + handler->name, handler->fd); + handler->handle_event(handler); + +out: + return ret; +} + diff --git a/event.h b/event.h new file mode 100644 index 0000000..91d0705 --- /dev/null +++ b/event.h @@ -0,0 +1,15 @@ +#ifndef _EVENT_H +#define _EVENT_H + +struct eventhandler_entry { + char *name; + int fd; + int events; + int (*handle_event)(struct eventhandler_entry *h); +}; + +int inint_event_handler(void); +int register_event_handler(struct eventhandler_entry *h); +int poll_events(int timeout_ms); + +#endif diff --git a/main.c b/main.c index 05e3390..1057d09 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include "baud.h" #include "trace.h" #include "data.h" +#include "event.h" int main(int argc, char *argv[]) { @@ -49,7 +50,12 @@ int main(int argc, char *argv[]) } } - read_data(fd, out_fd); + + init_data_parser(fd, out_fd); + + while (1) { + poll_events(10000); + } out: close(fd); diff --git a/utils.h b/utils.h index 8b5152e..102dc65 100644 --- a/utils.h +++ b/utils.h @@ -3,4 +3,14 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#ifndef offsetof +#define offsetof(type, member) __builtin_offsetof (type, member) +#endif + +#define container_of(ptr, type, member) \ + ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) ); \ + }) + #endif -- 2.44.0