@@ -36,7 +36,8 @@ struct rspamd_config; | |||
struct rspamd_stat_cache { | |||
const char *name; | |||
gpointer (*init)(struct rspamd_stat_ctx *ctx, struct rspamd_config *cfg); | |||
gpointer (*init)(struct rspamd_stat_ctx *ctx, | |||
struct rspamd_config *cfg, const ucl_object_t *cf); | |||
gint (*process)(struct rspamd_task *task, | |||
gboolean is_spam, | |||
gpointer ctx); | |||
@@ -45,7 +46,8 @@ struct rspamd_stat_cache { | |||
}; | |||
gpointer rspamd_stat_cache_sqlite3_init(struct rspamd_stat_ctx *ctx, | |||
struct rspamd_config *cfg); | |||
struct rspamd_config *cfg, | |||
const ucl_object_t *cf); | |||
gint rspamd_stat_cache_sqlite3_process ( | |||
struct rspamd_task *task, | |||
gboolean is_spam, gpointer c); |
@@ -121,71 +121,51 @@ struct rspamd_stat_sqlite3_ctx { | |||
gpointer | |||
rspamd_stat_cache_sqlite3_init(struct rspamd_stat_ctx *ctx, | |||
struct rspamd_config *cfg) | |||
struct rspamd_config *cfg, | |||
const ucl_object_t *cf) | |||
{ | |||
struct rspamd_stat_sqlite3_ctx *new = NULL; | |||
struct rspamd_classifier_config *clf; | |||
const ucl_object_t *obj, *elt; | |||
GList *cur; | |||
const ucl_object_t *elt; | |||
gchar dbpath[PATH_MAX]; | |||
const gchar *path; | |||
sqlite3 *sqlite; | |||
gboolean has_sqlite_cache = FALSE; | |||
GError *err = NULL; | |||
rspamd_snprintf (dbpath, sizeof (dbpath), SQLITE_CACHE_PATH); | |||
cur = cfg->classifiers; | |||
while (cur) { | |||
clf = cur->data; | |||
if (cf) { | |||
elt = ucl_object_find_key (cf, "path"); | |||
obj = ucl_object_find_key (clf->opts, "cache"); | |||
/* Sqlite3 cache is the default learn cache method */ | |||
if (obj == NULL) { | |||
has_sqlite_cache = TRUE; | |||
break; | |||
if (elt != NULL) { | |||
path = ucl_object_tostring (elt); | |||
} | |||
else { | |||
path = SQLITE_CACHE_PATH; | |||
} | |||
else if (ucl_object_type (obj) == UCL_OBJECT) { | |||
elt = ucl_object_find_key (obj, "name"); | |||
} | |||
if (ucl_object_type (elt) == UCL_STRING && | |||
g_ascii_strcasecmp (ucl_object_tostring (elt), "sqlite3") == 0) { | |||
rspamd_snprintf (dbpath, sizeof (dbpath), "%s", path); | |||
has_sqlite_cache = TRUE; | |||
elt = ucl_object_find_key (obj, "path"); | |||
if (elt != NULL && ucl_object_type (elt) == UCL_STRING) { | |||
rspamd_snprintf (dbpath, sizeof (dbpath), "%s", | |||
ucl_object_tostring (elt)); | |||
} | |||
} | |||
} | |||
sqlite = rspamd_sqlite3_open_or_create (cfg->cfg_pool, | |||
dbpath, create_tables_sql, &err); | |||
cur = g_list_next (cur); | |||
if (sqlite == NULL) { | |||
msg_err ("cannot open sqlite3 cache: %e", err); | |||
g_error_free (err); | |||
err = NULL; | |||
} | |||
else { | |||
new = g_slice_alloc (sizeof (*new)); | |||
new->db = sqlite; | |||
new->prstmt = rspamd_sqlite3_init_prstmt (sqlite, prepared_stmts, | |||
RSPAMD_STAT_CACHE_MAX, &err); | |||
if (has_sqlite_cache) { | |||
sqlite = rspamd_sqlite3_open_or_create (cfg->cfg_pool, | |||
dbpath, create_tables_sql, &err); | |||
if (sqlite == NULL) { | |||
msg_err_config ("cannot open sqlite3 cache: %e", err); | |||
if (new->prstmt == NULL) { | |||
msg_err ("cannot open sqlite3 cache: %e", err); | |||
g_error_free (err); | |||
err = NULL; | |||
} | |||
else { | |||
new = g_slice_alloc (sizeof (*new)); | |||
new->db = sqlite; | |||
new->prstmt = rspamd_sqlite3_init_prstmt (sqlite, prepared_stmts, | |||
RSPAMD_STAT_CACHE_MAX, &err); | |||
if (new->prstmt == NULL) { | |||
msg_err_config ("cannot open sqlite3 cache: %e", err); | |||
g_error_free (err); | |||
err = NULL; | |||
sqlite3_close (sqlite); | |||
g_slice_free1 (sizeof (*new), new); | |||
new = NULL; | |||
} | |||
sqlite3_close (sqlite); | |||
g_slice_free1 (sizeof (*new), new); | |||
new = NULL; | |||
} | |||
} | |||
@@ -98,20 +98,25 @@ rspamd_stat_init (struct rspamd_config *cfg) | |||
struct rspamd_statfile_config *stf; | |||
struct rspamd_stat_backend *bk; | |||
struct rspamd_statfile *st; | |||
struct rspamd_classifier *cl; | |||
const ucl_object_t *cache_obj = NULL, *cache_name_obj; | |||
const gchar *cache_name = NULL; | |||
if (stat_ctx == NULL) { | |||
stat_ctx = g_slice_alloc0 (sizeof (*stat_ctx)); | |||
} | |||
stat_ctx->backends = stat_backends; | |||
stat_ctx->backends_subrs = stat_backends; | |||
stat_ctx->backends_count = G_N_ELEMENTS (stat_backends); | |||
stat_ctx->classifiers = stat_classifiers; | |||
stat_ctx->classifiers_subrs = stat_classifiers; | |||
stat_ctx->classifiers_count = G_N_ELEMENTS (stat_classifiers); | |||
stat_ctx->tokenizers = stat_tokenizers; | |||
stat_ctx->tokenizers_subrs = stat_tokenizers; | |||
stat_ctx->tokenizers_count = G_N_ELEMENTS (stat_tokenizers); | |||
stat_ctx->caches = stat_caches; | |||
stat_ctx->caches_subrs = stat_caches; | |||
stat_ctx->caches_count = G_N_ELEMENTS (stat_caches); | |||
stat_ctx->cfg = cfg; | |||
stat_ctx->statfiles = g_ptr_array_new (); | |||
stat_ctx->classifiers = g_ptr_array_new (); | |||
REF_RETAIN (stat_ctx->cfg); | |||
/* Create statfiles from the classifiers */ | |||
@@ -133,16 +138,37 @@ rspamd_stat_init (struct rspamd_config *cfg) | |||
clf->tokenizer, NULL); | |||
} | |||
cl = g_slice_alloc0 (sizeof (*cl)); | |||
cl->cfg = clf; | |||
cl->statfiles_ids = g_array_new (FALSE, FALSE, sizeof (gint)); | |||
/* Init classifier cache */ | |||
if (clf->opts) { | |||
cache_obj = ucl_object_find_key (clf->opts, "cache"); | |||
if (cache_obj) { | |||
cache_name_obj = ucl_object_find_key (cache_obj, "name"); | |||
} | |||
if (cache_name_obj) { | |||
cache_name = ucl_object_tostring (cache_name_obj); | |||
} | |||
} | |||
cl->cache = rspamd_stat_get_cache (cache_name); | |||
g_assert (cl->cache != NULL); | |||
cl->cachecf = cl->cache->init (stat_ctx, cfg, cache_obj); | |||
curst = clf->statfiles; | |||
while (curst) { | |||
stf = curst->data; | |||
st = g_slice_alloc0 (sizeof (*st)); | |||
st->clcf = clf; | |||
st->classifier = cl; | |||
st->stcf = stf; | |||
st->tkcf = stat_ctx->tkcf; | |||
st->bkcf = stat_ctx->backends[i].init (stat_ctx, cfg, st); | |||
msg_debug_config ("added backend %s", stat_ctx->backends[i].name); | |||
st->bkcf = stat_ctx->backends_subrs[i].init (stat_ctx, cfg, st); | |||
msg_debug_config ("added backend %s", | |||
stat_ctx->backends_subrs[i].name); | |||
if (st->bkcf == NULL) { | |||
msg_err_config ("cannot init backend %s for statfile %s", | |||
@@ -151,19 +177,17 @@ rspamd_stat_init (struct rspamd_config *cfg) | |||
g_slice_free1 (sizeof (*st), st); | |||
} | |||
else { | |||
st->id = stat_ctx->statfiles->len; | |||
g_ptr_array_add (stat_ctx->statfiles, st); | |||
g_array_append_val (cl->statfiles_ids, st->id); | |||
} | |||
curst = curst->next; | |||
} | |||
cur = cur->next; | |||
} | |||
g_ptr_array_add (stat_ctx->classifiers, cl); | |||
/* Init caches */ | |||
for (i = 0; i < stat_ctx->caches_count; i ++) { | |||
stat_ctx->caches[i].ctx = stat_ctx->caches[i].init (stat_ctx, cfg); | |||
msg_debug_config ("added cache %s", stat_ctx->caches[i].name); | |||
cur = cur->next; | |||
} | |||
} | |||
@@ -176,9 +200,9 @@ rspamd_stat_close (void) | |||
g_assert (stat_ctx != NULL); | |||
for (i = 0; i < stat_ctx->backends_count; i ++) { | |||
if (stat_ctx->backends[i].close != NULL) { | |||
stat_ctx->backends[i].close (stat_ctx->backends[i].ctx); | |||
msg_debug_config ("closed backend %s", stat_ctx->backends[i].name); | |||
if (stat_ctx->backends_subrs[i].close != NULL) { | |||
stat_ctx->backends_subrs[i].close (stat_ctx->backends_subrs[i].ctx); | |||
msg_debug_config ("closed backend %s", stat_ctx->backends_subrs[i].name); | |||
} | |||
} | |||
@@ -197,8 +221,8 @@ rspamd_stat_get_classifier (const gchar *name) | |||
guint i; | |||
for (i = 0; i < stat_ctx->classifiers_count; i ++) { | |||
if (strcmp (name, stat_ctx->classifiers[i].name) == 0) { | |||
return &stat_ctx->classifiers[i]; | |||
if (strcmp (name, stat_ctx->classifiers_subrs[i].name) == 0) { | |||
return &stat_ctx->classifiers_subrs[i]; | |||
} | |||
} | |||
@@ -215,8 +239,8 @@ rspamd_stat_get_backend (const gchar *name) | |||
} | |||
for (i = 0; i < stat_ctx->backends_count; i ++) { | |||
if (strcmp (name, stat_ctx->backends[i].name) == 0) { | |||
return &stat_ctx->backends[i]; | |||
if (strcmp (name, stat_ctx->backends_subrs[i].name) == 0) { | |||
return &stat_ctx->backends_subrs[i]; | |||
} | |||
} | |||
@@ -233,8 +257,26 @@ rspamd_stat_get_tokenizer (const gchar *name) | |||
} | |||
for (i = 0; i < stat_ctx->tokenizers_count; i ++) { | |||
if (strcmp (name, stat_ctx->tokenizers[i].name) == 0) { | |||
return &stat_ctx->tokenizers[i]; | |||
if (strcmp (name, stat_ctx->tokenizers_subrs[i].name) == 0) { | |||
return &stat_ctx->tokenizers_subrs[i]; | |||
} | |||
} | |||
return NULL; | |||
} | |||
struct rspamd_stat_cache * | |||
rspamd_stat_get_cache (const gchar *name) | |||
{ | |||
guint i; | |||
if (name == NULL || name[0] == '\0') { | |||
name = RSPAMD_DEFAULT_CACHE; | |||
} | |||
for (i = 0; i < stat_ctx->caches_count; i++) { | |||
if (strcmp (name, stat_ctx->caches_subrs[i].name) == 0) { | |||
return &stat_ctx->caches_subrs[i]; | |||
} | |||
} | |||
@@ -95,17 +95,18 @@ typedef struct token_node_s { | |||
struct rspamd_stat_ctx { | |||
/* Subroutines for all objects */ | |||
struct rspamd_stat_classifier *classifiers; | |||
struct rspamd_stat_classifier *classifiers_subrs; | |||
guint classifiers_count; | |||
struct rspamd_stat_tokenizer *tokenizers; | |||
struct rspamd_stat_tokenizer *tokenizers_subrs; | |||
guint tokenizers_count; | |||
struct rspamd_stat_backend *backends; | |||
struct rspamd_stat_backend *backends_subrs; | |||
guint backends_count; | |||
struct rspamd_stat_cache *caches; | |||
struct rspamd_stat_cache *caches_subrs; | |||
guint caches_count; | |||
/* Runtime configuration */ | |||
GPtrArray *statfiles; /* struct statfile */ | |||
GPtrArray *statfiles; /* struct rspamd_statfile */ | |||
GPtrArray *classifiers; /* struct rspamd_classifier */ | |||
struct rspamd_config *cfg; | |||
/* Global tokenizer */ | |||
struct rspamd_stat_tokenizer *tokenizer; | |||
@@ -122,6 +123,7 @@ struct rspamd_stat_ctx * rspamd_stat_get_ctx (void); | |||
struct rspamd_stat_classifier * rspamd_stat_get_classifier (const gchar *name); | |||
struct rspamd_stat_backend * rspamd_stat_get_backend (const gchar *name); | |||
struct rspamd_stat_tokenizer * rspamd_stat_get_tokenizer (const gchar *name); | |||
struct rspamd_stat_cache * rspamd_stat_get_cache (const gchar *name); | |||
static GQuark rspamd_stat_quark (void) | |||
{ |