]> source.dussan.org Git - rspamd.git/commitdiff
* Implement composite symbols
authorcebka@cebka-laptop <cebka@cebka-laptop>
Tue, 14 Oct 2008 15:10:21 +0000 (19:10 +0400)
committercebka@cebka-laptop <cebka@cebka-laptop>
Tue, 14 Oct 2008 15:10:21 +0000 (19:10 +0400)
cfg_file.h
cfg_file.l
cfg_file.y
cfg_utils.c
filter.c
filter.h
main.h
protocol.c

index 21c8b26fac3da5a747c4e3c8f0f8c8635fea9fca..9632a70e7c0291fdd099e5793a6fe67fa59657f6 100644 (file)
@@ -47,6 +47,7 @@
                fprintf (stderr, fmt, ##__VA_ARGS__); \
                fprintf (stderr, "\n")
 
+struct expression;
 
 enum { VAL_UNDEF=0, VAL_TRUE, VAL_FALSE };
 
@@ -119,6 +120,7 @@ struct config_file {
        GHashTable* metrics;
        GHashTable* factors;
        GHashTable* c_modules;
+       GHashTable* composite_symbols;
 };
 
 int add_memcached_server (struct config_file *cf, char *str);
@@ -132,6 +134,7 @@ char parse_flag (const char *str);
 char* substitute_variable (struct config_file *cfg, char *str, u_char recursive);
 void post_load_config (struct config_file *cfg);
 struct rspamd_regexp* parse_regexp (memory_pool_t *pool, char *line);
+struct expression* parse_expression (memory_pool_t *pool, char *line);
 
 int yylex (void);
 int yyparse (void);
index 3cb8441bdc92f7ce8d0d75952edf1f9fb208e407..198f657921d916c7c2c0948db7caa28b580f99d4 100644 (file)
@@ -24,6 +24,7 @@ extern struct config_file *cfg;
 ^[ \t]*#.*                                             /* ignore comments */;
 .include                                               BEGIN(incl);
 .module                                                        BEGIN(module);
+composites                                             return COMPOSITES;
 tempdir                                                        return TEMPDIR;
 pidfile                                                        return PIDFILE;
 workers                                                        return WORKERS;
index ae901964be36241513e7cf2f6af132999e516819..c5badb43754609ea5c00c089aa7e05fb1748be21 100644 (file)
@@ -17,6 +17,7 @@
 #include <glib.h>
 
 #include "cfg_file.h"
+#include "main.h"
 
 #define YYDEBUG 1
 
@@ -48,7 +49,7 @@ struct metric *cur_metric = NULL;
 %token  MEMCACHED WORKERS REQUIRE MODULE
 %token  MODULE_OPT PARAM VARIABLE
 %token  HEADER_FILTERS MIME_FILTERS MESSAGE_FILTERS URL_FILTERS FACTORS METRIC NAME
-%token  REQUIRED_SCORE FUNCTION FRACT
+%token  REQUIRED_SCORE FUNCTION FRACT COMPOSITES
 
 %type  <string>        STRING
 %type  <string>        VARIABLE
@@ -85,6 +86,7 @@ command       :
        | variable
        | factors
        | metric
+       | composites
        ;
 
 tempdir :
@@ -351,6 +353,25 @@ requirecmd:
        }
        ;
 
+composites:
+       COMPOSITES OBRACE compositesbody EBRACE
+       ;
+
+compositesbody:
+       compositescmd SEMICOLON
+       | compositesbody compositescmd SEMICOLON
+       ;
+
+compositescmd:
+       QUOTEDSTRING EQSIGN QUOTEDSTRING {
+               struct expression *expr;
+               if ((expr = parse_expression (cfg->cfg_pool, $3)) == NULL) {
+                       yyerror ("yyparse: cannot parse composite expression: %s", $3);
+                       YYERROR;
+               }
+               g_hash_table_insert (cfg->composite_symbols, $1, expr);
+       }
+       ;
 module_opt:
        MODULE_OPT OBRACE moduleoptbody EBRACE {
                g_hash_table_insert (cfg->modules_opts, $1, cur_module_opt);
index 8630a096352a4f32c7580a53ac1a65fde6d60591..ae0dce5e39991d46377676abcd3c87d4f19c5b9c 100644 (file)
@@ -134,6 +134,7 @@ init_defaults (struct config_file *cfg)
        cfg->metrics = g_hash_table_new (g_str_hash, g_str_equal);
        cfg->factors = g_hash_table_new (g_str_hash, g_str_equal);
        cfg->c_modules = g_hash_table_new (g_str_hash, g_str_equal);
+       cfg->composite_symbols = g_hash_table_new (g_str_hash, g_str_equal);
 
        LIST_INIT (&cfg->perl_modules);
 }
@@ -151,6 +152,8 @@ free_config (struct config_file *cfg)
        g_hash_table_unref (cfg->factors);
        g_hash_table_remove_all (cfg->c_modules);
        g_hash_table_unref (cfg->c_modules);
+       g_hash_table_remove_all (cfg->composite_symbols);
+       g_hash_table_unref (cfg->composite_symbols);
        memory_pool_delete (cfg->cfg_pool);
 }
 
index a69a9efa907ef459dba3b513ea0f516db73d14a7..d1edbb93005e7ef1fca202e73187290f8e3ce5e2 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -12,7 +12,6 @@
 void
 insert_result (struct worker_task *task, const char *metric_name, const char *symbol, u_char flag)
 {
-       struct filter_result *result;
        struct metric *metric;
        struct metric_result *metric_res;
 
@@ -21,20 +20,18 @@ insert_result (struct worker_task *task, const char *metric_name, const char *sy
                return;
        }
 
-       result = memory_pool_alloc (task->task_pool, sizeof (struct filter_result));
-       result->symbol = symbol;
-       result->flag = flag;
        metric_res = g_hash_table_lookup (task->results, metric_name);
 
        if (metric_res == NULL) {
                /* Create new metric chain */
                metric_res = memory_pool_alloc (task->task_pool, sizeof (struct metric_result));
-               LIST_INIT (&metric_res->results);
+               metric_res->symbols = g_hash_table_new (g_str_hash, g_str_equal);
+               memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_hash_table_destroy, metric_res->symbols);
                metric_res->metric = metric;
                g_hash_table_insert (task->results, (gpointer)metric_name, metric_res);
        }
        
-       LIST_INSERT_HEAD (&metric_res->results, result, next);
+       g_hash_table_insert (metric_res->symbols, (gpointer)symbol, GSIZE_TO_POINTER (flag));
 }
 
 /*
@@ -44,28 +41,31 @@ double
 factor_consolidation_func (struct worker_task *task, const char *metric_name)
 {
        struct metric_result *metric_res;
-       struct filter_result *result;
        double *factor;
        double res = 0.;
+       GList *symbols = NULL, *cur;
 
        metric_res = g_hash_table_lookup (task->results, metric_name);
        if (metric_res == NULL) {
                return res;
        }
-
-       LIST_FOREACH (result, &metric_res->results, next) {
-               if (result->flag) {
-                       factor = g_hash_table_lookup (task->worker->srv->cfg->factors, result->symbol);
-                       if (factor == NULL) {
-                               /* Default multiplier is 1 */
-                               res ++;
-                       }
-                       else {
-                               res += *factor;
-                       }
+       
+       symbols = g_hash_table_get_keys (metric_res->symbols);
+       cur = g_list_first (symbols);
+       while (cur) {
+               factor = g_hash_table_lookup (task->worker->srv->cfg->factors, cur->data);
+               if (factor == NULL) {
+                       /* Default multiplier is 1 */
+                       res ++;
                }
+               else {
+                       res += *factor;
+               }
+               cur = g_list_next (cur);
        }
 
+       g_list_free (symbols);
+
        return res;
 }
 
@@ -240,3 +240,97 @@ process_filters (struct worker_task *task)
        g_hash_table_foreach (task->results, metric_process_callback, task);
        return 1;
 }
+
+struct composites_data {
+       struct worker_task *task;
+       struct metric_result *metric_res;
+};
+
+static void
+composites_foreach_callback (gpointer key, gpointer value, void *data)
+{
+       struct composites_data *cd = (struct composites_data *)data;
+       struct expression *expr = (struct expression *)value;
+       GQueue *stack;
+       GList *symbols = NULL, *s;
+       gsize cur, op1, op2;
+       
+       stack = g_queue_new ();
+
+       while (expr) {
+               if (expr->type == EXPR_OPERAND) {
+                       /* Find corresponding symbol */
+                       if (g_hash_table_lookup (cd->metric_res->symbols, expr->content.operand) == NULL) {
+                               cur = 0;
+                       }
+                       else {
+                               cur = 1;
+                               symbols = g_list_append (symbols, expr->content.operand);
+                       }
+                       g_queue_push_head (stack, GSIZE_TO_POINTER (cur));
+               }
+               else {
+                       if (g_queue_is_empty (stack)) {
+                               /* Queue has no operands for operation, exiting */
+                               g_list_free (symbols);
+                               g_queue_free (stack);
+                               return;
+                       }
+                       switch (expr->content.operation) {
+                               case '!':
+                                       op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+                                       op1 = !op1;
+                                       g_queue_push_head (stack, GSIZE_TO_POINTER (op1));
+                                       break;
+                               case '&':
+                                       op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+                                       op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+                                       g_queue_push_head (stack, GSIZE_TO_POINTER (op1 && op2));
+                               case '|':
+                                       op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+                                       op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+                                       g_queue_push_head (stack, GSIZE_TO_POINTER (op1 || op2));
+                               default:
+                                       expr = expr->next;
+                                       continue;
+                       }
+               }
+               expr = expr->next;
+       }
+       if (!g_queue_is_empty (stack)) {
+               op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+               if (op1) {
+                       /* Remove all symbols that are in composite symbol */
+                       s = g_list_first (symbols);
+                       while (s) {
+                               g_hash_table_remove (cd->metric_res->symbols, s->data);
+                               s = g_list_next (s);
+                       }
+                       /* Add new symbol */
+                       g_hash_table_insert (cd->metric_res->symbols, key, GSIZE_TO_POINTER (op1));
+               }
+       }
+
+       g_queue_free (stack);
+       g_list_free (symbols);
+
+       return;
+}
+
+static void
+composites_metric_callback (gpointer key, gpointer value, void *data) 
+{
+       struct worker_task *task = (struct worker_task *)data;
+       struct composites_data *cd = memory_pool_alloc (task->task_pool, sizeof (struct composites_data));
+       struct metric_result *metric_res = (struct metric_result *)value;
+
+       cd->task = task;
+       cd->metric_res = (struct metric_result *)metric_res;
+
+       g_hash_table_foreach (task->cfg->composite_symbols, composites_foreach_callback, cd);
+}
+
+void make_composites (struct worker_task *task)
+{
+       g_hash_table_foreach (task->results, composites_metric_callback, task);
+}
index d7f494dc64dd881b63fbf98e71638a7889c9d098..ce8be7ecd8eb85aac13883be396c7b81ddb62c13 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -29,20 +29,15 @@ struct metric {
        double required_score;
 };
 
-struct filter_result {
-       const char *symbol;
-       u_char flag;
-       LIST_ENTRY (filter_result) next;
-};
-
 struct metric_result {
        struct metric *metric;
        double score;
-       LIST_HEAD (resultq, filter_result) results;
+       GHashTable *symbols;
 };
 
 int process_filters (struct worker_task *task);
 void insert_result (struct worker_task *task, const char *metric_name, const char *symbol, u_char flag);
+void make_composites (struct worker_task *task);
 double factor_consolidation_func (struct worker_task *task, const char *metric_name);
 
 #endif
diff --git a/main.h b/main.h
index f111ba1b4ddbd28ba98686649b7a08b6256acc43..0d9e8ca105acfd8ecc2e210795538380dc95d06b 100644 (file)
--- a/main.h
+++ b/main.h
@@ -163,7 +163,6 @@ struct c_module {
 };
 
 void start_worker (struct rspamd_worker *worker, int listen_sock);
-struct expression* parse_expression (memory_pool_t *pool, char *line);
 
 #endif
 
index 832a142817748f49a2a0725692034cfe3c84781b..0881b9788712a4ca2aea9c62106afc5b125a27c3 100644 (file)
@@ -363,23 +363,25 @@ show_metric_symbols (gpointer metric_name, gpointer metric_value, void *user_dat
        struct worker_task *task = (struct worker_task *)user_data;
        int r = 0;
        char outbuf[OUTBUFSIZ];
-       struct filter_result *result;
+       GList *symbols = NULL, *cur;
        struct metric_result *metric_res = (struct metric_result *)metric_value;
 
        if (task->proto == RSPAMC_PROTO) {
                r = snprintf (outbuf, sizeof (outbuf), "%s: ", (char *)metric_name);
        }
 
-       LIST_FOREACH (result, &metric_res->results, next) {
-               if (result->flag) {
-                       if (LIST_NEXT (result, next) != NULL) {
-                               r += snprintf (outbuf + r, sizeof (outbuf) - r, "%s,", result->symbol);
-                       }
-                       else {
-                               r += snprintf (outbuf + r, sizeof (outbuf) - r, "%s", result->symbol);
-                       }
+       symbols = g_hash_table_get_keys (metric_res->symbols);
+       cur = symbols;
+       while (cur) {
+               if (g_list_next (cur) != NULL) {
+                       r += snprintf (outbuf + r, sizeof (outbuf) - r, "%s,", (char *)cur->data);
+               }
+               else {
+                       r += snprintf (outbuf + r, sizeof (outbuf) - r, "%s", (char *)cur->data);
                }
+               cur = g_list_next (cur);
        }
+       g_list_free (symbols);
        outbuf[r++] = '\r'; outbuf[r] = '\n';
        bufferevent_write (task->bev, outbuf, r);
 }