Changeset be3ad87 in code for logger.c


Ignore:
Timestamp:
Mar 7, 2014, 2:14:54 PM (11 years ago)
Author:
Mike Belopuhov <mike@…>
Branches:
master
Children:
e13307d
Parents:
460786f
Message:

Rewrite logger_dispatch to use bufferevents to simplify error processing

This also ensures that we're dealing with partial messages correctly and
don't get out of sync with the main process.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • logger.c

    r460786f rbe3ad87  
    3737#include "icbd.h"
    3838
    39 void logger_dispatch(int, short, void *);
     39void logger_ioerr(struct bufferevent *, short, void *);
     40void logger_dispatch(struct bufferevent *, void *);
    4041FILE *logger_open(char *);
    4142void logger_tick(void);
     
    6566logger_init(void)
    6667{
    67         static struct event ev;
     68        struct bufferevent *bev;
    6869        struct passwd *pw;
    6970        int pipes[2];
     
    117118
    118119        /* event for message processing */
    119         event_set(&ev, pipes[1], EV_READ | EV_PERSIST, logger_dispatch, NULL);
    120         if (event_add(&ev, NULL) < 0) {
    121                 syslog(LOG_ERR, "event_add: %m");
    122                 exit (EX_UNAVAILABLE);
     120        if ((bev = bufferevent_new(pipes[1], logger_dispatch, NULL,
     121            logger_ioerr, NULL)) == NULL) {
     122                syslog(LOG_ERR, "bufferevent_new: %m");
     123                exit(EX_UNAVAILABLE);
     124        }
     125        if (bufferevent_enable(bev, EV_READ)) {
     126                syslog(LOG_ERR, "bufferevent_enable: %m");
     127                bufferevent_free(bev);
     128                exit(EX_UNAVAILABLE);
    123129        }
    124130
     
    129135
    130136void
    131 logger_dispatch(int fd, short event, void *arg __attribute__((unused)))
    132 {
    133         char buf[ICB_MSGSIZE];
    134         struct icbd_logentry e;
    135         struct iovec iov[2];
     137logger_ioerr(struct bufferevent *bev __attribute__((__unused__)), short what,
     138    void *arg __attribute__((__unused__)))
     139{
     140        const char *cause = NULL;
     141
     142        if (what & EVBUFFER_TIMEOUT)
     143                cause = "timeout";
     144        else if (what & EVBUFFER_EOF)
     145                cause = "eof";
     146        else if (what & EVBUFFER_ERROR)
     147                cause = what & EVBUFFER_READ ? "read" : "write";
     148        syslog(LOG_ERR, "logger_ioerr: %s", cause ? cause : "unknown");
     149        exit(EX_IOERR);
     150}
     151
     152void
     153logger_dispatch(struct bufferevent *bev, void *arg __attribute__((unused)))
     154{
     155        struct icbd_logentry *e;
     156        static char buf[sizeof *e + ICB_MSGSIZE];
     157        static size_t nread = 0;
    136158        FILE *fp = NULL;
     159        size_t res;
     160        char *m;
    137161        int i;
    138162
    139         if (event != EV_READ)
    140                 return;
    141 
    142         bzero(&e, sizeof e);
    143         iov[0].iov_base = &e;
    144         iov[0].iov_len = sizeof e;
    145 
    146         iov[1].iov_base = buf;
    147         iov[1].iov_len = sizeof buf;
    148 
    149         if (readv(fd, iov, 2) < (ssize_t)sizeof e) {
    150                 syslog(LOG_ERR, "logger read: %m");
    151                 exit(EX_DATAERR);
    152         }
    153 
    154         /* XXX */
    155         if (iov[1].iov_len < e.length) {
    156                 syslog(LOG_ERR, "logger read %lu out of %lu",
    157                     iov[1].iov_len, e.length);
    158         }
    159 
    160         for (i = 0; i < nlogfiles; i++)
    161                 if (strcmp(logfiles[i].group, e.group) == 0)
    162                         fp = logfiles[i].fp;
    163         if (!fp && (fp = logger_open(e.group)) == NULL)
    164                 return;
    165         if (strlen(e.nick) == 0)
    166                 fprintf(fp, "[%s] %s\n", line_ts, buf);
    167         else
    168                 fprintf(fp, "[%s] <%s> %s\n", line_ts, e.nick, buf);
     163        e = (struct icbd_logentry *)buf;
     164        m = buf + sizeof *e;
     165
     166        while (EVBUFFER_LENGTH(EVBUFFER_INPUT(bev)) > 0) {
     167                if (nread == 0) {
     168                        bzero(e, sizeof *e);
     169                        /* read the log entry header */
     170                        res = bufferevent_read(bev, &buf[0], sizeof *e);
     171                        nread += res;
     172                        if (nread < sizeof *e)
     173                                return;
     174                }
     175                /* see if we got the whole header */
     176                if (nread < sizeof *e) {
     177                        /* finish reading */
     178                        res = bufferevent_read(bev, &buf[nread],
     179                            sizeof *e - nread);
     180                        nread += res;
     181                        if (nread < sizeof *e)
     182                                return;
     183                }
     184                /* fetch the message */
     185                res = bufferevent_read(bev, &buf[nread],
     186                    MIN(e->length, ICB_MSGSIZE));
     187                nread += res;
     188#ifdef DEBUG
     189                {
     190                        printf("logger read %lu out of %lu:\n", res, e->length);
     191                        for (i = 0; i < (int)res; i++)
     192                                printf(" %02x", (unsigned char)m[i]);
     193                        printf("\n");
     194                }
     195#endif
     196                if (nread < e->length)
     197                        return;
     198                /* terminate the buffer */
     199                m[MIN(nread - sizeof *e, ICB_MSGSIZE)] = '\0';
     200                /* find the appropriate log file */
     201                for (i = 0; i < nlogfiles; i++)
     202                        if (strcmp(logfiles[i].group, e->group) == 0)
     203                                fp = logfiles[i].fp;
     204                if (!fp && (fp = logger_open(e->group)) == NULL)
     205                        return;
     206                if (strlen(e->nick) == 0)
     207                        fprintf(fp, "[%s] %s\n", line_ts, m);
     208                else
     209                        fprintf(fp, "[%s] <%s> %s\n", line_ts, e->nick, m);
     210                /* get ready for the next message */
     211                nread = 0;
     212        }
    169213}
    170214
Note: See TracChangeset for help on using the changeset viewer.