From 72f56da6b6fca986a82f4239b003e15d582e4a46 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Wed, 8 Jun 2016 16:35:08 +0200
Subject: [PATCH] add a filter to loggers

events are accepted by the logger if the filter accepts them
the filter is optional (no filter means to accept all events)
---
 common/utils/T/tracer/Makefile             |  15 ++-
 common/utils/T/tracer/filter/Makefile      |  13 +++
 common/utils/T/tracer/filter/filter.c      | 109 +++++++++++++++++++++
 common/utils/T/tracer/filter/filter.h      |  14 +++
 common/utils/T/tracer/logger/framelog.c    |   4 +
 common/utils/T/tracer/logger/logger.c      |   6 ++
 common/utils/T/tracer/logger/logger.h      |   1 +
 common/utils/T/tracer/logger/logger_defs.h |   2 +
 common/utils/T/tracer/logger/textlog.c     |   4 +
 common/utils/T/tracer/logger/ticklog.c     |   4 +
 common/utils/T/tracer/logger/timelog.c     |   4 +
 common/utils/T/tracer/logger/ttilog.c      |   4 +
 12 files changed, 176 insertions(+), 4 deletions(-)
 create mode 100644 common/utils/T/tracer/filter/Makefile
 create mode 100644 common/utils/T/tracer/filter/filter.c
 create mode 100644 common/utils/T/tracer/filter/filter.h

diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile
index e9d9b99da7..bf0f72710c 100644
--- a/common/utils/T/tracer/Makefile
+++ b/common/utils/T/tracer/Makefile
@@ -8,18 +8,21 @@ LIBS=-lX11 -lm -lpng -lXft
 all: textlog enb vcd
 
 textlog: utils.o textlog.o database.o event.o handler.o config.o \
-         event_selector.o view/view.a gui/gui.a logger/logger.a
+         event_selector.o view/view.a gui/gui.a logger/logger.a \
+         filter/filter.a
 	$(CC) $(CFLAGS) -o textlog $^ $(LIBS)
 
 enb: utils.o enb.o database.o event.o handler.o config.o \
-         event_selector.o view/view.a gui/gui.a logger/logger.a
+         event_selector.o view/view.a gui/gui.a logger/logger.a \
+         filter/filter.a
 	$(CC) $(CFLAGS) -o enb $^ $(LIBS)
 
 vcd: utils.o vcd.o database.o event.o handler.o config.o \
-         event_selector.o view/view.a gui/gui.a logger/logger.a
+         event_selector.o view/view.a gui/gui.a logger/logger.a \
+         filter/filter.a
 	$(CC) $(CFLAGS) -o vcd $^ $(LIBS)
 
-.PHONY: all gui/gui.a view/view.a logger/logger.a
+.PHONY: all gui/gui.a view/view.a logger/logger.a filter/filter.a
 
 gui/gui.a:
 	cd gui && make
@@ -30,6 +33,9 @@ view/view.a:
 logger/logger.a:
 	cd logger && make
 
+filter/filter.a:
+	cd filter && make
+
 %.o: %.c
 	$(CC) $(CFLAGS) -c -o $@ $<
 
@@ -38,3 +44,4 @@ clean:
 	cd gui && make clean
 	cd view && make clean
 	cd logger && make clean
+	cd filter && make clean
diff --git a/common/utils/T/tracer/filter/Makefile b/common/utils/T/tracer/filter/Makefile
new file mode 100644
index 0000000000..fb1427ca6a
--- /dev/null
+++ b/common/utils/T/tracer/filter/Makefile
@@ -0,0 +1,13 @@
+CC=gcc
+CFLAGS=-Wall -g -pthread -I..
+
+OBJS=filter.o
+
+filter.a: $(OBJS)
+	ar cr filter.a $(OBJS)
+
+%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+	rm -f *.a *.o
diff --git a/common/utils/T/tracer/filter/filter.c b/common/utils/T/tracer/filter/filter.c
new file mode 100644
index 0000000000..9c1e96a611
--- /dev/null
+++ b/common/utils/T/tracer/filter/filter.c
@@ -0,0 +1,109 @@
+#include "filter.h"
+#include "event.h"
+#include "database.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct filter {
+  union {
+    struct { struct filter *a, *b; } eq;
+    int v;
+    struct { int event_type; int arg_index; } evarg;
+  } v;
+
+  int (*eval)(struct filter *this, event e);
+};
+
+/****************************************************************************/
+/*                     evaluation functions                                 */
+/****************************************************************************/
+
+int eval_eq(struct filter *f, event e)
+{
+  int a = f->v.eq.a->eval(f->v.eq.a, e);
+  int b = f->v.eq.b->eval(f->v.eq.b, e);
+  return a == b;
+}
+
+int eval_int(struct filter *f, event e)
+{
+  return f->v.v;
+}
+
+int eval_evarg(struct filter *f, event e)
+{
+  if (e.type != f->v.evarg.event_type) {
+    printf("%s:%d:%s: bad event type\n", __FILE__, __LINE__, __FUNCTION__);
+    abort();
+  }
+  if (e.e[f->v.evarg.arg_index].type != EVENT_INT) {
+    printf("%s:%d:%s: bad event argtype; has to be 'int'\n",
+        __FILE__, __LINE__, __FUNCTION__);
+    abort();
+  }
+  return e.e[f->v.evarg.arg_index].i;
+}
+
+/****************************************************************************/
+/*                     filter construction functions                        */
+/****************************************************************************/
+
+filter *filter_eq(filter *a, filter *b)
+{
+  struct filter *ret = calloc(1, sizeof(struct filter));
+  if (ret == NULL) abort();
+  ret->eval = eval_eq;
+  ret->v.eq.a = a;
+  ret->v.eq.b = b;
+  return ret;
+}
+
+filter *filter_int(int v)
+{
+  struct filter *ret = calloc(1, sizeof(struct filter));
+  if (ret == NULL) abort();
+  ret->eval = eval_int;
+  ret->v.v = v;
+  return ret;
+}
+
+filter *filter_evarg(void *database, char *event_name, char *varname)
+{
+  struct filter *ret;
+  int event_id;
+  database_event_format f;
+  int i;
+
+  ret = calloc(1, sizeof(struct filter)); if (ret == NULL) abort();
+
+  event_id = event_id_from_name(database, event_name);
+  f = get_format(database, event_id);
+
+  ret->eval = eval_evarg;
+  ret->v.evarg.event_type = event_id;
+  ret->v.evarg.arg_index = -1;
+
+  for (i = 0; i < f.count; i++) {
+    if (strcmp(f.name[i], varname) != 0) continue;
+    ret->v.evarg.arg_index = i;
+    break;
+  }
+  if (ret->v.evarg.arg_index == -1) {
+    printf("%s:%d:%s: event '%s' has no argument '%s'\n",
+        __FILE__, __LINE__, __FUNCTION__, event_name, varname);
+    abort();
+  }
+
+  return ret;
+}
+
+/****************************************************************************/
+/*                     eval function                                        */
+/****************************************************************************/
+
+int filter_eval(filter *_f, event e)
+{
+  struct filter *f = _f;
+  return f->eval(f, e);
+}
diff --git a/common/utils/T/tracer/filter/filter.h b/common/utils/T/tracer/filter/filter.h
new file mode 100644
index 0000000000..b47b755dbc
--- /dev/null
+++ b/common/utils/T/tracer/filter/filter.h
@@ -0,0 +1,14 @@
+#ifndef _FILTER_H_
+#define _FILTER_H_
+
+#include "event.h"
+
+typedef void filter;
+
+filter *filter_eq(filter *a, filter *b);
+filter *filter_int(int v);
+filter *filter_evarg(void *database, char *event_name, char *varname);
+
+int filter_eval(filter *f, event e);
+
+#endif /* _FILTER_H_ */
diff --git a/common/utils/T/tracer/logger/framelog.c b/common/utils/T/tracer/logger/framelog.c
index 0889f2b80c..057960c382 100644
--- a/common/utils/T/tracer/logger/framelog.c
+++ b/common/utils/T/tracer/logger/framelog.c
@@ -2,6 +2,7 @@
 #include "logger_defs.h"
 #include "handler.h"
 #include "database.h"
+#include "filter/filter.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -31,6 +32,9 @@ static void _event(void *p, event e)
   int bsize;
   int nsamples;
 
+  if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
+    return;
+
   subframe = e.e[l->subframe_arg].i;
   buffer = e.e[l->buffer_arg].b;
   bsize = e.e[l->buffer_arg].bsize;
diff --git a/common/utils/T/tracer/logger/logger.c b/common/utils/T/tracer/logger/logger.c
index c27c612f82..ab6fb8bc62 100644
--- a/common/utils/T/tracer/logger/logger.c
+++ b/common/utils/T/tracer/logger/logger.c
@@ -9,3 +9,9 @@ void logger_add_view(logger *_l, view *v)
   l->v = realloc(l->v, l->vsize * sizeof(view *)); if (l->v == NULL) abort();
   l->v[l->vsize-1] = v;
 }
+
+void logger_set_filter(logger *_l, void *filter)
+{
+  struct logger *l = _l;
+  l->filter = filter;
+}
diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h
index 2c26f8dcb2..e3e4b97aa5 100644
--- a/common/utils/T/tracer/logger/logger.h
+++ b/common/utils/T/tracer/logger/logger.h
@@ -19,5 +19,6 @@ void framelog_set_skip(logger *_this, int skip_delay);
 #include "view/view.h"
 
 void logger_add_view(logger *l, view *v);
+void logger_set_filter(logger *l, void *filter);
 
 #endif /* _LOGGER_H_ */
diff --git a/common/utils/T/tracer/logger/logger_defs.h b/common/utils/T/tracer/logger/logger_defs.h
index e4279157ec..8e8d6a2d3e 100644
--- a/common/utils/T/tracer/logger/logger_defs.h
+++ b/common/utils/T/tracer/logger/logger_defs.h
@@ -9,6 +9,8 @@ struct logger {
   /* list of views */
   view **v;
   int vsize;
+  /* filter - NULL if no filter set */
+  void *filter;
 };
 
 #endif /* _LOGGER_DEFS_H_ */
diff --git a/common/utils/T/tracer/logger/textlog.c b/common/utils/T/tracer/logger/textlog.c
index a9503b9510..e80af7813e 100644
--- a/common/utils/T/tracer/logger/textlog.c
+++ b/common/utils/T/tracer/logger/textlog.c
@@ -4,6 +4,7 @@
 #include "database.h"
 #include "view/view.h"
 #include "utils.h"
+#include "filter/filter.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -42,6 +43,9 @@ static void _event(void *p, event e)
   char tt[64];
 #endif
 
+  if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
+    return;
+
   l->o.osize = 0;
 
 #ifdef T_SEND_TIME
diff --git a/common/utils/T/tracer/logger/ticklog.c b/common/utils/T/tracer/logger/ticklog.c
index b2462aabb6..7a3bc45338 100644
--- a/common/utils/T/tracer/logger/ticklog.c
+++ b/common/utils/T/tracer/logger/ticklog.c
@@ -3,6 +3,7 @@
 #include "event.h"
 #include "database.h"
 #include "handler.h"
+#include "filter/filter.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -21,6 +22,9 @@ static void _event(void *p, event e)
   int frame;
   int subframe;
 
+  if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
+    return;
+
   frame = e.e[l->frame_arg].i;
   subframe = e.e[l->subframe_arg].i;
 
diff --git a/common/utils/T/tracer/logger/timelog.c b/common/utils/T/tracer/logger/timelog.c
index 5dadad8c27..b474c8200d 100644
--- a/common/utils/T/tracer/logger/timelog.c
+++ b/common/utils/T/tracer/logger/timelog.c
@@ -3,6 +3,7 @@
 #include "event.h"
 #include "database.h"
 #include "handler.h"
+#include "filter/filter.h"
 #include <stdlib.h>
 #include <string.h>
 
@@ -15,6 +16,9 @@ static void _event(void *p, event e)
   struct timelog *l = p;
   int i;
 
+  if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
+    return;
+
   for (i = 0; i < l->common.vsize; i++)
     l->common.v[i]->append(l->common.v[i], e.sending_time);
 }
diff --git a/common/utils/T/tracer/logger/ttilog.c b/common/utils/T/tracer/logger/ttilog.c
index 172d0eeb2d..29e22fbf10 100644
--- a/common/utils/T/tracer/logger/ttilog.c
+++ b/common/utils/T/tracer/logger/ttilog.c
@@ -3,6 +3,7 @@
 #include "event.h"
 #include "database.h"
 #include "handler.h"
+#include "filter/filter.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -25,6 +26,9 @@ static void _event(void *p, event e)
   int subframe;
   float value;
 
+  if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
+    return;
+
   frame = e.e[l->frame_arg].i;
   subframe = e.e[l->subframe_arg].i;
   switch (e.e[l->data_arg].type) {
-- 
GitLab