diff --git a/src/logmsg.c b/src/logmsg.c index fb11a46..97139f8 100644 --- a/src/logmsg.c +++ b/src/logmsg.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "private.h" @@ -201,4 +202,89 @@ igloo_objecthandler_t * igloo_logmsg_formarter(igloo_ro_t backend, const char return objecthandler; } -igloo_filter_t * igloo_logmsg_filter(igloo_loglevel_t level_min, igloo_loglevel_t level_max, igloo_logmsg_opt_t options_required, igloo_logmsg_opt_t options_absent, const struct timespec * ts_min, const struct timespec * ts_max, const char *cat, const char *name, igloo_ro_t associated); +typedef struct { + igloo_loglevel_t level_min; + igloo_loglevel_t level_max; + igloo_logmsg_opt_t options_required; + igloo_logmsg_opt_t options_absent; + struct timespec ts_min; + struct timespec ts_max; + char *cat; +} igloo_logmsg_filter_mask_t; + +static inline int __gt_timespec(struct timespec *a, struct timespec *b) +{ + return a->tv_sec > b->tv_sec || (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec); +} + +static igloo_filter_result_t __test(igloo_INTERFACE_BASIC_ARGS, igloo_ro_t object) +{ + igloo_logmsg_t *msg = igloo_RO_TO_TYPE(object, igloo_logmsg_t); + igloo_logmsg_filter_mask_t *mask = *backend_userdata; + + if (!msg) + return igloo_FILTER_RESULT_DROP; + + if (msg->level < mask->level_min || msg->level > mask->level_max) + return igloo_FILTER_RESULT_DROP; + + if ((msg->options & mask->options_required) != mask->options_required || (msg->options & mask->options_absent)) + return igloo_FILTER_RESULT_DROP; + + if (__gt_timespec(&(mask->ts_min), &(msg->ts)) || __gt_timespec(&(msg->ts), &(mask->ts_max))) + return igloo_FILTER_RESULT_DROP; + + if (mask->cat) { + if (!msg->cat) + return igloo_FILTER_RESULT_DROP; + + if (strcmp(msg->cat, mask->cat) != 0) + return igloo_FILTER_RESULT_DROP; + } + + return igloo_FILTER_RESULT_PASS; +} + +static const igloo_filter_ifdesc_t igloo_logmsg_filter_ifdesc = { + igloo_INTERFACE_DESCRIPTION_BASE(igloo_filter_ifdesc_t), + .test = __test +}; + +igloo_filter_t * igloo_logmsg_filter(igloo_loglevel_t level_min, igloo_loglevel_t level_max, igloo_logmsg_opt_t options_required, igloo_logmsg_opt_t options_absent, const struct timespec * ts_min, const struct timespec * ts_max, const char *cat, const char *name, igloo_ro_t associated) +{ + igloo_filter_t *filter; + igloo_logmsg_filter_mask_t *mask = calloc(1, sizeof(*mask)); + + if (!mask) + return NULL; + + mask->level_min = level_min; + mask->level_max = level_max; + mask->options_required = options_required; + mask->options_absent = options_absent; + + /* No else needed, as {0, 0} is already in the past. */ + if (ts_min) + mask->ts_min = *ts_min; + + if (ts_max) { + mask->ts_max = *ts_max; + } else { + /* BEFORE YEAR 2038 IMPORTANT REWRITE: Update date. */ + mask->ts_max.tv_sec = 2145916800; /* this is 2038-01-01 */ + } + + if (cat) { + mask->cat = strdup(cat); + if (!mask->cat) { + free(mask); + return NULL; + } + } + + filter = igloo_filter_new(&igloo_logmsg_filter_ifdesc, igloo_RO_NULL, mask, name, associated); + if (!filter) { + free(mask); + } + return filter; +}