diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2017-01-03 13:22:59 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2017-01-03 13:22:59 +0000 |
commit | e5a9a2248124f691d8ee9e27db623fa17278af3e (patch) | |
tree | 222904579e1d81c86d0d97f19d3960867b5dd871 /src/libutil/rrd.c | |
parent | 0ba131089412a41c632703109903185d1e057aff (diff) | |
download | rspamd-e5a9a2248124f691d8ee9e27db623fa17278af3e.tar.gz rspamd-e5a9a2248124f691d8ee9e27db623fa17278af3e.zip |
[Feature] Rework RRD ds count, add conversion path
Diffstat (limited to 'src/libutil/rrd.c')
-rw-r--r-- | src/libutil/rrd.c | 194 |
1 files changed, 157 insertions, 37 deletions
diff --git a/src/libutil/rrd.c b/src/libutil/rrd.c index fca4ecad2..b6d43f5a8 100644 --- a/src/libutil/rrd.c +++ b/src/libutil/rrd.c @@ -21,6 +21,10 @@ #include "cryptobox.h" #include <math.h> +#define RSPAMD_RRD_DS_COUNT METRIC_ACTION_MAX +#define RSPAMD_RRD_OLD_DS_COUNT 4 +#define RSPAMD_RRD_RRA_COUNT 4 + #define msg_err_rrd(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \ "rrd", file->id, \ G_STRFUNC, \ @@ -1266,54 +1270,31 @@ rspamd_rrd_close (struct rspamd_rrd_file * file) return 0; } -struct rspamd_rrd_file * -rspamd_rrd_file_default (const gchar *path, - GError **err) +static struct rspamd_rrd_file * +rspamd_rrd_create_file (const gchar *path, gboolean finalize, GError **err) { struct rspamd_rrd_file *file; - struct rrd_ds_def ds[4]; - struct rrd_rra_def rra[4]; + struct rrd_ds_def ds[RSPAMD_RRD_DS_COUNT]; + struct rrd_rra_def rra[RSPAMD_RRD_RRA_COUNT]; + gint i; GArray ar; - g_assert (path != NULL); - - if (access (path, R_OK) != -1) { - /* We can open rrd file */ - file = rspamd_rrd_open (path, err); - - if (file == NULL) { - return NULL; - } - - - if (file->stat_head->ds_cnt != 4 || file->stat_head->rra_cnt != 4) { - msg_err_rrd ("rrd file is not suitable for rspamd: it has " - "%ul ds and %ul rra", file->stat_head->ds_cnt, - file->stat_head->rra_cnt); - g_set_error (err, rrd_error_quark (), EINVAL, "bad rrd file"); - rspamd_rrd_close (file); - - return NULL; - } - - return file; - } - /* Try to create new rrd file */ - file = rspamd_rrd_create (path, 4, 4, 1, rspamd_get_calendar_ticks (), err); + file = rspamd_rrd_create (path, RSPAMD_RRD_DS_COUNT, RSPAMD_RRD_RRA_COUNT, + 1, rspamd_get_calendar_ticks (), err); if (file == NULL) { return NULL; } /* Create DS and RRA */ - rrd_make_default_ds ("spam", rrd_dst_to_string (RRD_DST_COUNTER), 1, &ds[0]); - rrd_make_default_ds ("probable", rrd_dst_to_string (RRD_DST_COUNTER), 1, - &ds[1]); - rrd_make_default_ds ("greylist", rrd_dst_to_string (RRD_DST_COUNTER), 1, - &ds[2]); - rrd_make_default_ds ("ham", rrd_dst_to_string (RRD_DST_COUNTER), 1, &ds[3]); + + for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { + rrd_make_default_ds (rspamd_action_to_str (i), + rrd_dst_to_string (RRD_DST_COUNTER), 1, &ds[i]); + } + ar.data = (gchar *)ds; ar.len = sizeof (ds); @@ -1342,7 +1323,7 @@ rspamd_rrd_file_default (const gchar *path, return NULL; } - if (!rspamd_rrd_finalize (file, err)) { + if (finalize && !rspamd_rrd_finalize (file, err)) { rspamd_rrd_close (file); return NULL; } @@ -1350,6 +1331,145 @@ rspamd_rrd_file_default (const gchar *path, return file; } +static void +rspamd_rrd_convert_ds (struct rspamd_rrd_file *old, + struct rspamd_rrd_file *cur, gint idx_old, gint idx_new) +{ + struct rrd_pdp_prep *pdp_prep_old, *pdp_prep_new; + struct rrd_cdp_prep *cdp_prep_old, *cdp_prep_new; + gdouble *val_old, *val_new; + gulong rra_cnt, i, j, points_cnt, old_ds, new_ds; + + rra_cnt = old->stat_head->rra_cnt; + pdp_prep_old = &old->pdp_prep[idx_old]; + pdp_prep_new = &cur->pdp_prep[idx_new]; + memcpy (pdp_prep_new, pdp_prep_old, sizeof (*pdp_prep_new)); + memcpy (&old->rra_ptr[idx_old], &cur->rra_ptr[idx_new], sizeof (*old->rra_ptr)); + val_old = old->rrd_value; + val_new = cur->rrd_value; + old_ds = old->stat_head->ds_cnt; + new_ds = cur->stat_head->ds_cnt; + + for (i = 0; i < rra_cnt; i++) { + cdp_prep_old = &old->cdp_prep[i] + idx_old; + cdp_prep_new = &cur->cdp_prep[i] + idx_new; + memcpy (cdp_prep_new, cdp_prep_old, sizeof (*cdp_prep_new)); + points_cnt = old->rra_def[i].row_cnt; + + for (j = 0; j < points_cnt; j ++) { + val_new[j * new_ds + idx_new] = val_old[j * old_ds + idx_old]; + } + + val_new += points_cnt * new_ds; + val_old += points_cnt * old_ds; + } +} + +static struct rspamd_rrd_file * +rspamd_rrd_convert (const gchar *path, struct rspamd_rrd_file *old, + GError **err) +{ + struct rspamd_rrd_file *rrd; + gchar tpath[PATH_MAX]; + + g_assert (old != NULL); + + rspamd_snprintf (tpath, sizeof (tpath), "%s.new", path); + rrd = rspamd_rrd_create_file (tpath, TRUE, err); + + if (rrd) { + /* Copy old data */ + memcpy (rrd->live_head, old->live_head, sizeof (*rrd->live_head)); + + /* + * Old DSes: + * 0 - spam -> reject + * 1 - probable spam -> add header + * 2 - greylist -> greylist + * 3 - ham -> ham + */ + rspamd_rrd_convert_ds (old, rrd, 0, METRIC_ACTION_REJECT); + rspamd_rrd_convert_ds (old, rrd, 1, METRIC_ACTION_ADD_HEADER); + rspamd_rrd_convert_ds (old, rrd, 2, METRIC_ACTION_GREYLIST); + rspamd_rrd_convert_ds (old, rrd, 3, METRIC_ACTION_NOACTION); + + if (unlink (path) == -1) { + g_set_error (err, rrd_error_quark (), errno, "cannot unlink old rrd file %s: %s", + path, strerror (errno)); + unlink (tpath); + rspamd_rrd_close (rrd); + + return NULL; + } + + if (rename (tpath, path) == -1) { + g_set_error (err, rrd_error_quark (), errno, "cannot rename old rrd file %s: %s", + path, strerror (errno)); + unlink (tpath); + rspamd_rrd_close (rrd); + + return NULL; + } + } + + return rrd; +} + +struct rspamd_rrd_file * +rspamd_rrd_file_default (const gchar *path, + GError **err) +{ + struct rspamd_rrd_file *file, *nf; + + g_assert (path != NULL); + + if (access (path, R_OK) != -1) { + /* We can open rrd file */ + file = rspamd_rrd_open (path, err); + + if (file == NULL) { + return NULL; + } + + + if (file->stat_head->rra_cnt != RSPAMD_RRD_RRA_COUNT) { + msg_err_rrd ("rrd file is not suitable for rspamd: it has " + "%ul ds and %ul rra", file->stat_head->ds_cnt, + file->stat_head->rra_cnt); + g_set_error (err, rrd_error_quark (), EINVAL, "bad rrd file"); + rspamd_rrd_close (file); + + return NULL; + } + else if (file->stat_head->ds_cnt == RSPAMD_RRD_OLD_DS_COUNT) { + /* Old rrd, need to convert */ + msg_info_rrd ("rrd file %s is not suitable for rspamd, convert it", + path); + + nf = rspamd_rrd_convert (path, file, err); + rspamd_rrd_close (file); + + return nf; + } + else if (file->stat_head->ds_cnt == RSPAMD_RRD_DS_COUNT) { + return file; + } + else { + msg_err_rrd ("rrd file is not suitable for rspamd: it has " + "%ul ds and %ul rra", file->stat_head->ds_cnt, + file->stat_head->rra_cnt); + g_set_error (err, rrd_error_quark (), EINVAL, "bad rrd file"); + rspamd_rrd_close (file); + + return NULL; + } + } + + file = rspamd_rrd_create_file (path, TRUE, err); + + return file; +} + struct rspamd_rrd_query_result * rspamd_rrd_query (struct rspamd_rrd_file *file, gulong rra_num) |