Add counters to the context. This counters allow to keep a state for the filter of...
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Mon, 13 Oct 2008 19:36:35 +0000 (21:36 +0200)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Mon, 13 Oct 2008 19:36:35 +0000 (21:36 +0200)
Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
postlicyd/filter.c
postlicyd/filter.h
postlicyd/main-postlicyd.c

index d145f42..14bfc9b 100644 (file)
@@ -50,6 +50,8 @@ static filter_async_handler_t       async_handler = NULL;
 static const filter_hook_t default_hook = {
     .type      = 0,
     .value     = (char*)"DUNNO",
+    .counter   = -1,
+    .cost      = 0,
     .postfix   = true,
     .async     = false,
     .filter_id = 0
@@ -58,6 +60,8 @@ static const filter_hook_t default_hook = {
 static const filter_hook_t async_hook = {
     .type      = 0,
     .value     = NULL,
+    .counter   = -1,
+    .cost      = 0,
     .postfix   = false,
     .async     = true,
     .filter_id = 0
@@ -288,6 +292,35 @@ bool filter_add_hook(filter_t *filter, const char *name, int name_len,
         return false;
     }
     hook.async   = false;
+
+    /* Value format is (counter:id:incr)?(postfix:reply|filter_name)
+     */
+    if (strncmp(value, "counter:", 8) == 0) {
+        char *end = NULL;
+        value += 8;
+        hook.counter = strtol(value, &end, 10);
+        if (end == value || *end != ':') {
+              err("hook %s, cannot read counter id", htokens[hook.type]);
+              return false;
+        } else if (hook.counter < 0 || hook.counter >= MAX_COUNTERS) {
+            err("hook %s, invalid counter id %d", htokens[hook.type], hook.counter);
+            return false;
+        }
+        value = end + 1;
+        hook.cost = strtol(value, &end, 10);
+        if (end == value || *end != ':') {
+            err("hook %s, cannot read counter increment", htokens[hook.type]);
+            return false;
+        } else if (hook.cost < 0) {
+            err("hook %s, invalid counter increment value %d", htokens[hook.type],
+                hook.cost);
+            return false;
+        }
+        value = end + 1;
+    } else {
+        hook.counter = -1;
+        hook.cost    = 0;
+    }
     hook.postfix = (strncmp(value, "postfix:", 8) == 0);
     if (hook.postfix && query_format(NULL, 0, value + 8, NULL) == -1) {
         err("invalid formatted text \"%s\"", value + 8);
@@ -319,6 +352,12 @@ void filter_context_wipe(filter_context_t *context)
     }
 }
 
+void filter_context_clean(filter_context_t *context)
+{
+    p_clear(&context->counters, 1);
+    context->instance[0] = '\0';
+}
+
 void filter_post_async_result(filter_context_t *context, filter_result_t result)
 {
     const filter_t *filter = context->current_filter;
index dcbaecb..c2c7a4f 100644 (file)
@@ -52,9 +52,13 @@ typedef struct filter_hook_t {
     filter_result_t type;
     char *value;
 
+    int counter;
+    int cost;
+
     unsigned postfix:1;
     unsigned async:1;
     int filter_id;
+
 } filter_hook_t;
 ARRAY(filter_hook_t)
 
@@ -82,13 +86,24 @@ typedef struct filter_t {
 } filter_t;
 ARRAY(filter_t)
 
+#define MAX_COUNTERS (64)
+
 /** Context of the query. To be filled with data to use when
  * performing asynchronous filtering.
  */
 typedef struct filter_context_t {
+    /* filter context
+     */
     const filter_t *current_filter;
     void *contexts[FTK_count];
 
+    /* message context
+     */
+    char instance[64];
+    uint32_t counters[MAX_COUNTERS];
+
+    /* connection context
+     */
     void *data;
 } filter_context_t;
 
@@ -273,6 +288,9 @@ void filter_context_prepare(filter_context_t *context, void* qctx);
 __attribute__((nonnull))
 void filter_context_wipe(filter_context_t *context);
 
+__attribute__((nonnull))
+void filter_context_clean(filter_context_t *context);
+
 __attribute__((nonnull))
 void filter_post_async_result(filter_context_t *context, filter_result_t result);
 
index fa31a1e..bf68941 100644 (file)
@@ -110,6 +110,17 @@ static void policy_answer(server_t *pcy, const char *message)
 
 static const filter_t *next_filter(server_t *pcy, const filter_t *filter,
                                    const query_t *query, const filter_hook_t *hook, bool *ok) {
+    if (hook != NULL) {
+        query_context_t *context = pcy->data;
+        if (hook->counter >= 0 && hook->counter < MAX_COUNTERS && hook->cost > 0) {
+            context->context.counters[hook->counter] += hook->cost;
+            debug("request client=%s, from=<%s>, to=<%s>: added %d to counter %d (now %u)",
+                  query->client_name,
+                  query->sender == NULL ? "undefined" : query->sender,
+                  query->recipient == NULL ? "undefined" : query->recipient,
+                  hook->cost, hook->counter, context->context.counters[hook->counter]);
+        }
+    }
     if (hook == NULL) {
         warn("request client=%s, from=<%s>, to=<%s>: aborted",
              query->client_name,
@@ -205,6 +216,10 @@ static int policy_run(server_t *pcy, void* vconfig)
     if (!query_parse(pcy->data, pcy->ibuf.data))
         return -1;
     query->eoq = eoq + strlen("\n\n");
+    if (query->instance == NULL || strcmp(context->context.instance, query->instance) != 0) {
+        filter_context_clean(&context->context);
+        m_strcat(context->context.instance, 64, query->instance);
+    }
     epoll_modify(pcy->fd, 0, pcy);
     return policy_process(pcy, mconfig) ? 0 : -1;
 }