}
/* Cache for regular expressions that are used in functions */
-static GHashTable *re_cache = NULL;
-
void *
-re_cache_check (const char *line)
+re_cache_check (const char *line, memory_pool_t *pool)
{
+ GHashTable *re_cache;
+
+ re_cache = memory_pool_get_variable (pool, "re_cache");
+
if (re_cache == NULL) {
re_cache = g_hash_table_new (g_str_hash, g_str_equal);
+ memory_pool_set_variable (pool, "re_cache", re_cache, (pool_destruct_func)g_hash_table_destroy);
return NULL;
}
return g_hash_table_lookup (re_cache, line);
}
void
-re_cache_add (char *line, void *pointer)
+re_cache_add (char *line, void *pointer, memory_pool_t *pool)
{
+ GHashTable *re_cache;
+
+ re_cache = memory_pool_get_variable (pool, "re_cache");
+
if (re_cache == NULL) {
re_cache = g_hash_table_new (g_str_hash, g_str_equal);
+ memory_pool_set_variable (pool, "re_cache", re_cache, (pool_destruct_func)g_hash_table_destroy);
}
g_hash_table_insert (re_cache, line, pointer);
}
/* Avoid multiply regexp structures for similar regexps */
- if ((check = (struct rspamd_regexp *)re_cache_check (begin)) != NULL) {
+ if ((check = (struct rspamd_regexp *)re_cache_check (begin, pool)) != NULL) {
/* Additional check for headers */
if (result->type == REGEXP_HEADER || result->type == REGEXP_RAW_HEADER) {
if (result->header && check->header) {
}
/* Add to cache for further usage */
- re_cache_add (result->regexp_text, result);
+ re_cache_add (result->regexp_text, result, pool);
return result;
}
}
if (*param_pattern == '/') {
/* This is regexp, so compile and create g_regexp object */
- if ((re = re_cache_check (param_pattern)) == NULL) {
+ if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) {
re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode);
if (re == NULL) {
msg_warn ("cannot compile regexp for function");
return FALSE;
}
- re_cache_add (param_pattern, re);
+ re_cache_add (param_pattern, re, task->cfg->cfg_pool);
}
if ((r = task_cache_check (task, re)) == -1) {
if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) {
if (*param_pattern == '/') {
/* This is regexp, so compile and create g_regexp object */
- if ((re = re_cache_check (param_pattern)) == NULL) {
+ if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) {
re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode);
if (re == NULL) {
msg_warn ("cannot compile regexp for function");
return FALSE;
}
- re_cache_add (param_pattern, re);
+ re_cache_add (param_pattern, re, task->cfg->cfg_pool);
}
if ((r = task_cache_check (task, re)) == -1) {
if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) {
if (*param_pattern == '/') {
/* This is regexp, so compile and create g_regexp object */
- if ((re = re_cache_check (param_pattern)) == NULL) {
+ if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) {
re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode);
if (re == NULL) {
msg_warn ("cannot compile regexp for function");
return FALSE;
}
- re_cache_add (param_pattern, re);
+ re_cache_add (param_pattern, re, task->cfg->cfg_pool);
}
if ((r = task_cache_check (task, re)) == -1) {
if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) {
if (*subtype == '/') {
/* This is regexp, so compile and create g_regexp object */
- if ((re = re_cache_check (subtype)) == NULL) {
+ if ((re = re_cache_check (subtype, task->cfg->cfg_pool)) == NULL) {
re = parse_regexp (task->cfg->cfg_pool, subtype, task->cfg->raw_mode);
if (re == NULL) {
msg_warn ("cannot compile regexp for function");
return FALSE;
}
- re_cache_add (subtype, re);
+ re_cache_add (subtype, re, task->cfg->cfg_pool);
}
if ((r = task_cache_check (task, re)) == -1) {
if (g_regex_match (re->regexp, subtype, 0, NULL) == TRUE) {
if (*param_type == '/') {
/* This is regexp, so compile and create g_regexp object */
- if ((re = re_cache_check (param_type)) == NULL) {
+ if ((re = re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) {
re = parse_regexp (task->cfg->cfg_pool, param_type, task->cfg->raw_mode);
if (re == NULL) {
msg_warn ("cannot compile regexp for function");
cur = g_list_next (cur);
continue;
}
- re_cache_add (param_type, re);
+ re_cache_add (param_type, re, task->cfg->cfg_pool);
}
if ((r = task_cache_check (task, re)) == -1) {
if (g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) {
* @param line symbolic representation
* @param pointer regexp data
*/
-void re_cache_add (char *line, void *pointer);
+void re_cache_add (char *line, void *pointer, memory_pool_t *pool);
/**
* Check regexp in cache
* @param line symbolic representation
* @return pointer to regexp data or NULL if regexp is not found
*/
-void * re_cache_check (const char *line);
+void * re_cache_check (const char *line, memory_pool_t *pool);
/**
* Add regexp to regexp task cache
msg_err ("unsupported version of fuzzy hash file: %d", version);
return FALSE;
}
+ msg_info ("reading fuzzy hashes storage file of version %d of size %d", version, (int)(st.st_size - sizeof (header)) / sizeof (struct rspamd_fuzzy_node));
}
else {
/* Old version */
rspamd_hash_t *counters;
static struct rspamd_worker *fork_worker (struct rspamd_main *, struct worker_conf *);
-static gboolean load_rspamd_config (struct config_file *cfg);
+static gboolean load_rspamd_config (struct config_file *cfg, gboolean init_modules);
static void init_metrics_cache (struct config_file *cfg);
sig_atomic_t do_restart;
tmp_cfg->cfg_name = cfg_file;
init_lua (tmp_cfg);
- if (! load_rspamd_config (tmp_cfg)) {
+ if (! load_rspamd_config (tmp_cfg, FALSE)) {
msg_err ("cannot parse new config file, revert to old one");
free_config (tmp_cfg);
}
close_log ();
g_free (rspamd->cfg);
rspamd->cfg = tmp_cfg;
- post_load_config (rspamd->cfg);
config_logger (rspamd, FALSE);
/* Perform modules configuring */
l = g_list_first (rspamd->cfg->filters);
filt = l->data;
if (filt->module) {
(void)filt->module->module_reconfig_func (rspamd->cfg);
+ msg_info ("reconfig of %s", filt->module->name);
}
l = g_list_next (l);
}
}
static gboolean
-load_rspamd_config (struct config_file *cfg)
+load_rspamd_config (struct config_file *cfg, gboolean init_modules)
{
GList *l;
struct filter *filt;
/* Do post-load actions */
post_load_config (cfg);
+
+ if (init_modules) {
+ /* Init C modules */
+ l = g_list_first (cfg->filters);
- /* Init C modules */
- l = g_list_first (cfg->filters);
-
- while (l) {
- filt = l->data;
- if (filt->module) {
- cur_module = memory_pool_alloc (cfg->cfg_pool, sizeof (struct module_ctx));
- if (filt->module->module_init_func (cfg, &cur_module) == 0) {
- g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module);
+ while (l) {
+ filt = l->data;
+ if (filt->module) {
+ cur_module = memory_pool_alloc (cfg->cfg_pool, sizeof (struct module_ctx));
+ if (filt->module->module_init_func (cfg, &cur_module) == 0) {
+ g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module);
+ }
}
+ l = g_list_next (l);
}
- l = g_list_next (l);
}
return TRUE;
}
}
- if (! load_rspamd_config (rspamd->cfg)) {
+ if (! load_rspamd_config (rspamd->cfg, TRUE)) {
exit (EXIT_FAILURE);
}
new->shared_pool = NULL;
new->first_pool = new->cur_pool;
new->destructors = NULL;
+ /* Set it upon first call of set variable */
+ new->variables = NULL;
mem_pool_stat->pools_allocated++;
mem_pool_stat->chunks_freed++;
STAT_UNLOCK ();
}
+ if (pool->variables) {
+ g_hash_table_destroy (pool->variables);
+ }
mem_pool_stat->pools_freed++;
g_slice_free (memory_pool_t, pool);
memory_pool_unlock_mutex (lock->__w_lock);
}
+void
+memory_pool_set_variable (memory_pool_t *pool, const gchar *name, gpointer value, pool_destruct_func destructor)
+{
+ if (pool->variables == NULL) {
+ pool->variables = g_hash_table_new (g_str_hash, g_str_equal);
+ }
+
+ g_hash_table_insert (pool->variables, memory_pool_strdup (pool, name), value);
+ if (destructor != NULL) {
+ memory_pool_add_destructor (pool, destructor, value);
+ }
+}
+
+gpointer
+memory_pool_get_variable (memory_pool_t *pool, const gchar *name)
+{
+ if (pool->variables == NULL) {
+ return NULL;
+ }
+
+ return g_hash_table_lookup (pool->variables, name);
+}
+
+
/*
* vi:ts=4
*/
struct _pool_chain *first_pool; /**< first page */
struct _pool_chain_shared *shared_pool; /**< shared chain */
struct _pool_destructors *destructors; /**< destructors chain */
+ GHashTable *variables; /**< private memory pool variables */
} memory_pool_t;
/**
*/
memory_pool_ssize_t memory_pool_get_size ();
+/**
+ * Set memory pool variable
+ * @param pool memory pool object
+ * @param name name of variable
+ * @param gpointer value value of variable
+ * @param destructor pointer to function-destructor
+ */
+void memory_pool_set_variable (memory_pool_t *pool, const gchar *name, gpointer value, pool_destruct_func destructor);
+
+/**
+ * Get memory pool variable
+ * @param pool memory pool object
+ * @param name name of variable
+ * @return NULL or pointer to variable data
+ */
+gpointer memory_pool_get_variable (memory_pool_t *pool, const gchar *name);
+
+
/**
* Macro that return free space in pool page
* @param x pool page struct
regexp_module_ctx = g_malloc (sizeof (struct regexp_ctx));
regexp_module_ctx->filter = regexp_common_filter;
- regexp_module_ctx->regexp_pool = memory_pool_new (1024);
+ regexp_module_ctx->regexp_pool = memory_pool_new (memory_pool_get_size ());
regexp_module_ctx->autolearn_symbols = g_hash_table_new (g_str_hash, g_str_equal);
*ctx = (struct module_ctx *)regexp_module_ctx;
regexp_module_reconfig (struct config_file *cfg)
{
memory_pool_delete (regexp_module_ctx->regexp_pool);
- regexp_module_ctx->regexp_pool = memory_pool_new (1024);
+ regexp_module_ctx->regexp_pool = memory_pool_new (memory_pool_get_size ());
return regexp_module_config (cfg);
}
qsort (cache->items, cache->used_items, sizeof (struct cache_item), cache_logic_cmp);
}
+/* Unmap cache file */
+static void
+unmap_cache_file (gpointer arg)
+{
+ struct symbols_cache *cache = arg;
+
+ /* A bit ugly usage */
+ munmap (cache->map, cache->used_items * sizeof (struct saved_cache_item));
+}
+
static gboolean
-mmap_cache_file (struct symbols_cache *cache, int fd)
+mmap_cache_file (struct symbols_cache *cache, int fd, memory_pool_t *pool)
{
void *map;
int i;
}
/* Close descriptor as it would never be used */
close (fd);
+ cache->map = map;
/* Now free old values for saved cache items and fill them with mmapped ones */
for (i = 0; i < cache->used_items; i++) {
g_free (cache->items[i].s);
cache->items[i].s = ((struct saved_cache_item *)map) + i;
}
-
+
post_cache_init (cache);
+
return TRUE;
}
/* Fd must be opened for writing, after creating file is mmapped */
static gboolean
-create_cache_file (struct symbols_cache *cache, const char *filename, int fd)
+create_cache_file (struct symbols_cache *cache, const char *filename, int fd, memory_pool_t *pool)
{
int i;
GChecksum *cksum;
return FALSE;
}
- return mmap_cache_file (cache, fd);
+ return mmap_cache_file (cache, fd, pool);
}
void
if (*cache == NULL) {
*cache = g_new0 (struct symbols_cache, 1);
}
+
if ((*cache)->items == NULL) {
(*cache)->cur_items = MIN_CACHE;
(*cache)->used_items = 0;
item->user_data = user_data;
item->s->weight = weight;
(*cache)->used_items++;
+ msg_info ("used items: %d, added symbol: %s", (*cache)->used_items, name);
set_counter (item->s->symbol, 0);
}
+static void
+free_cache (gpointer arg)
+{
+ struct symbols_cache *cache = arg;
+ int i;
+
+ if (cache->map == NULL) {
+ /* Free items in memory, otherwise */
+ for (i = 0; i < cache->cur_items; i++) {
+ g_free (cache->items[i].s);
+ }
+ }
+ else {
+ unmap_cache_file (cache);
+ }
+
+ g_free (cache);
+}
+
gboolean
init_symbols_cache (memory_pool_t * pool, struct symbols_cache *cache, const char *filename)
{
GChecksum *cksum;
u_char *mem_sum, *file_sum;
gsize cklen;
+ gboolean res;
if (cache == NULL || cache->items == NULL) {
return FALSE;
post_cache_init (cache);
return TRUE;
}
+
/* First of all try to stat file */
if (stat (filename, &st) == -1) {
return FALSE;
}
else {
- return create_cache_file (cache, filename, fd);
+ return create_cache_file (cache, filename, fd, pool);
}
}
else {
return FALSE;
}
else {
- return create_cache_file (cache, filename, fd);
+ return create_cache_file (cache, filename, fd, pool);
}
}
g_free (file_sum);
g_checksum_free (cksum);
/* MMap cache file and copy saved_cache structures */
- return mmap_cache_file (cache, fd);
+ res = mmap_cache_file (cache, fd, pool);
+ memory_pool_add_destructor (pool, (pool_destruct_func)free_cache, cache);
+ return res;
}
gboolean
guint cur_items;
guint used_items;
guint uses;
+ gpointer map;
memory_pool_rwlock_t *lock;
};