#include "message.h"
#include "symbols_cache.h"
#include "cfg_file.h"
-#include "blake2.h"
-/* After which number of messages try to resort cache */
-#define MAX_USES 100
static const guchar rspamd_symbols_cache_magic[8] = {'r', 's', 'c', 1, 0, 0, 0, 0 };
struct rspamd_symbols_cache_header {
guchar magic[8];
guint nitems;
- guchar checksum[BLAKE2B_OUTBYTES];
+ guchar checksum[64];
guchar unused[128];
};
guint used_items;
guint uses;
struct rspamd_config *cfg;
+ rspamd_mempool_mutex_t *mtx;
+ gdouble reload_time;
+ struct event resort_ev;
};
struct counter_data {
gdouble avg_time;
gdouble weight;
guint32 frequency;
+ guint32 avg_counter;
/* Per process counter */
struct counter_data *cd;
gdouble metric_weight;
};
+/* XXX: Maybe make it configurable */
+#define CACHE_RELOAD_TIME 60.0
/* weight, frequency, time */
#define TIME_ALPHA (1.0 / 1000000.0)
#define WEIGHT_ALPHA (0.001)
elt = ucl_object_find_key (cur, "weight");
if (elt) {
- w = ucl_object_todouble (cur);
+ w = ucl_object_todouble (elt);
if (w != 0) {
item->weight = w;
}
}
elt = ucl_object_find_key (cur, "time");
+ if (elt) {
+ item->avg_time = ucl_object_todouble (elt);
+ }
+ elt = ucl_object_find_key (cur, "count");
if (elt) {
- item->avg_time = ucl_object_todouble (cur);
+ item->avg_counter = ucl_object_toint (elt);
}
elt = ucl_object_find_key (cur, "frequency");
-
if (elt) {
- item->frequency = ucl_object_toint (cur);
+ item->frequency = ucl_object_toint (elt);
}
}
}
* parent item avg_time
*/
parent->avg_time = item->avg_time;
+ parent->avg_counter = item->avg_counter;
}
ucl_object_iterate_free (it);
"weight", 0, false);
ucl_object_insert_key (elt, ucl_object_fromdouble (item->avg_time),
"time", 0, false);
+ ucl_object_insert_key (elt, ucl_object_fromdouble (item->avg_counter),
+ "count", 0, false);
ucl_object_insert_key (elt, ucl_object_fromint (item->frequency),
"frequency", 0, false);
cache->items_by_symbol = g_hash_table_new (rspamd_str_hash,
rspamd_str_equal);
cache->items_by_order = g_ptr_array_new ();
+ cache->mtx = rspamd_mempool_get_mutex (cache->static_pool);
+ cache->reload_time = CACHE_RELOAD_TIME;
return cache;
}
if (item) {
item->metric_weight = weight;
- item->weight = item->weight * weight;
+
+ if (abs (item->weight) < abs (weight) || weight < 0) {
+ item->weight = weight;
+ }
}
}
return top;
}
+
+static void
+rspamd_symbols_cache_resort_cb (gint fd, short what, gpointer ud)
+{
+ struct timeval tv;
+ gdouble tm;
+ struct symbols_cache *cache = ud;
+ struct cache_item *item, *parent;
+ guint i;
+
+ /* Plan new event */
+ tm = rspamd_time_jitter (cache->reload_time, 0);
+ msg_info ("resort symbols cache, next reload in %.2f seconds", tm);
+ g_assert (cache != NULL);
+ evtimer_set (&cache->resort_ev, rspamd_symbols_cache_resort_cb, cache);
+ double_to_tv (tm, &tv);
+ event_add (&cache->resort_ev, &tv);
+
+ rspamd_mempool_lock_mutex (cache->mtx);
+
+ /* Gather stats from shared execution times */
+ for (i = 0; i < cache->items_by_order->len; i ++) {
+ item = g_ptr_array_index (cache->items_by_order, i);
+
+ if (item->type == SYMBOL_TYPE_CALLBACK ||
+ item->type == SYMBOL_TYPE_NORMAL) {
+ if (item->cd->number > 0) {
+ item->avg_counter += item->cd->number + 1;
+ item->avg_time = item->avg_time +
+ (item->cd->value - item->avg_time) /
+ item->avg_counter;
+ item->cd->value = item->avg_time;
+ item->cd->number = item->avg_counter;
+ }
+ }
+ }
+ /* Sync virtual symbols */
+ for (i = 0; i < cache->items_by_order->len; i ++) {
+ if (item->parent != -1) {
+ parent = g_ptr_array_index (cache->items_by_order, item->parent);
+ item->avg_time = parent->avg_time;
+ item->avg_counter = parent->avg_counter;
+ }
+ }
+
+ rspamd_mempool_unlock_mutex (cache->mtx);
+
+ post_cache_init (cache);
+}
+
+void
+rspamd_symbols_cache_start_refresh (struct symbols_cache * cache,
+ struct event_base *ev_base)
+{
+ struct timeval tv;
+ gdouble tm;
+
+ tm = rspamd_time_jitter (cache->reload_time, 0);
+ g_assert (cache != NULL);
+ evtimer_set (&cache->resort_ev, rspamd_symbols_cache_resort_cb, cache);
+ event_base_set (ev_base, &cache->resort_ev);
+ double_to_tv (tm, &tv);
+ event_add (&cache->resort_ev, &tv);
+}