From bb783aa50c87907a2012d6979b47e10c9189892e Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 17 Oct 2011 21:04:29 +0300 Subject: [PATCH] * Add configuration utils for kvstorage --- lib/CMakeLists.txt | 1 + src/cfg_file.h | 2 +- src/cfg_utils.c | 11 +- src/cfg_xml.c | 6 +- src/cfg_xml.h | 5 +- src/classifiers/bayes.c | 6 +- src/kvstorage_config.c | 362 ++++++++++++++++++++++++++++++++++++ src/kvstorage_config.h | 81 ++++++++ src/plugins/regexp.c | 2 +- src/tokenizers/tokenizers.c | 3 - 10 files changed, 462 insertions(+), 17 deletions(-) create mode 100644 src/kvstorage_config.c create mode 100644 src/kvstorage_config.h diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 38674d6e7..f84a70227 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -48,6 +48,7 @@ SET(RSPAMDLIBSRC ../src/binlog.c ../src/html.c ../src/images.c ../src/kvstorage.c + ../src/kvstorage_config.c ../src/lmtp_proto.c ../src/logger.c ../src/map.c diff --git a/src/cfg_file.h b/src/cfg_file.h index fc1ba547a..184a1aa16 100644 --- a/src/cfg_file.h +++ b/src/cfg_file.h @@ -378,7 +378,7 @@ gchar* get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_n * @param limit string representation of limit (eg. 1M) * @return numeric value of limit */ -gsize parse_limit (const gchar *limit); +gsize parse_limit (const gchar *limit, guint len); /** * Parse time diff --git a/src/cfg_utils.c b/src/cfg_utils.c index 203133e77..ffebd5c46 100644 --- a/src/cfg_utils.c +++ b/src/cfg_utils.c @@ -268,16 +268,17 @@ get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_name) } gsize -parse_limit (const gchar *limit) +parse_limit (const gchar *limit, guint len) { gsize result = 0; - gchar *err_str; + const gchar *err_str; - if (!limit || *limit == '\0') + if (!limit || *limit == '\0' || len == 0) { return 0; + } errno = 0; - result = strtoul (limit, &err_str, 10); + result = strtoul (limit, (gchar **)&err_str, 10); if (*err_str != '\0') { /* Megabytes */ @@ -292,7 +293,7 @@ parse_limit (const gchar *limit) else if (*err_str == 'g' || *err_str == 'G') { result *= 1073741824L; } - else { + else if (len > 0 && err_str - limit != len) { msg_warn ("invalid limit value '%s' at position '%s'", limit, err_str); result = 0; } diff --git a/src/cfg_xml.c b/src/cfg_xml.c index 30192703c..d66912ab9 100644 --- a/src/cfg_xml.c +++ b/src/cfg_xml.c @@ -1521,7 +1521,7 @@ xml_handle_size (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHash gsize *dest; dest = (gsize *)G_STRUCT_MEMBER_P (dest_struct, offset); - *dest = parse_limit (data); + *dest = parse_limit (data, -1); return TRUE; } @@ -1792,7 +1792,7 @@ if (g_ascii_strcasecmp (element_name, (x)) == 0) { \ else { \ res = FALSE; \ if ((required) == TRUE) { \ - *error = g_error_new (xml_error_quark (), XML_UNMATCHED_TAG, "element %s is unexpected in this state, expected %s", element_name, (x)); \ + if (*error == NULL) *error = g_error_new (xml_error_quark (), XML_UNMATCHED_TAG, "element %s is unexpected in this state, expected %s", element_name, (x)); \ ud->state = XML_ERROR; \ } \ } \ @@ -2137,7 +2137,7 @@ check_module_option (const gchar *mname, const gchar *optname, const gchar *data } break; case MODULE_OPT_TYPE_SIZE: - (void)parse_limit (data); + (void)parse_limit (data, -1); if (errno != 0) { msg_warn ("non-numeric data for option: '%s' for module: '%s': %s", optname, mname, strerror (errno)); return FALSE; diff --git a/src/cfg_xml.h b/src/cfg_xml.h index 2e188d2f6..6740e135e 100644 --- a/src/cfg_xml.h +++ b/src/cfg_xml.h @@ -167,7 +167,7 @@ void register_worker_opt (gint wtype, const gchar *optname, element_handler_func void register_classifier_opt (const gchar *ctype, const gchar *optname); /* Register new xml subparser */ -void register_suparser (const gchar *tag, enum xml_read_state state, const GMarkupParser *parser, gpointer user_data); +void register_subparser (const gchar *tag, enum xml_read_state state, const GMarkupParser *parser, gpointer user_data); /* Check validity of module option */ gboolean check_module_option (const gchar *mname, const gchar *optname, const gchar *data); @@ -175,4 +175,7 @@ gboolean check_module_option (const gchar *mname, const gchar *optname, const gc /* Dumper functions */ gboolean xml_dump_config (struct config_file *cfg, const gchar *filename); +/* XML error quark for reporting errors */ +GQuark xml_error_quark (void); + #endif diff --git a/src/classifiers/bayes.c b/src/classifiers/bayes.c index bf7e4d9d4..265957bc9 100644 --- a/src/classifiers/bayes.c +++ b/src/classifiers/bayes.c @@ -221,7 +221,7 @@ bayes_classify (struct classifier_ctx* ctx, statfile_pool_t *pool, GTree *input, data.learned_tokens = 0; if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { - minnodes = parse_limit (value); + minnodes = parse_limit (value, -1); data.max_tokens = minnodes; } else { @@ -320,7 +320,7 @@ bayes_learn (struct classifier_ctx* ctx, statfile_pool_t *pool, const char *symb data.learned_tokens = 0; data.learned_tokens = 0; if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { - minnodes = parse_limit (value); + minnodes = parse_limit (value, -1); data.max_tokens = minnodes; } else { @@ -425,7 +425,7 @@ bayes_learn_spam (struct classifier_ctx* ctx, statfile_pool_t *pool, data.learned_tokens = 0; if (ctx->cfg->opts && (value = g_hash_table_lookup (ctx->cfg->opts, "max_tokens")) != NULL) { - minnodes = parse_limit (value); + minnodes = parse_limit (value, -1); data.max_tokens = minnodes; } else { diff --git a/src/kvstorage_config.c b/src/kvstorage_config.c new file mode 100644 index 000000000..70c9ee182 --- /dev/null +++ b/src/kvstorage_config.c @@ -0,0 +1,362 @@ +/* Copyright (c) 2010, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Rambler BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "kvstorage_config.h" +#include "main.h" +#include "cfg_xml.h" + +/* Global hash of storages indexed by id */ +GHashTable *storages = NULL; +/* Last used id for explicit numbering */ +gint last_id = 0; + +struct kvstorage_config_parser { + enum { + KVSTORAGE_STATE_INIT, + KVSTORAGE_STATE_PARAM, + KVSTORAGE_STATE_BACKEND, + KVSTORAGE_STATE_EXPIRE, + KVSTORAGE_STATE_ID, + KVSTORAGE_STATE_NAME, + KVSTORAGE_STATE_CACHE_TYPE, + KVSTORAGE_STATE_CACHE_MAX_ELTS, + KVSTORAGE_STATE_CACHE_MAX_MEM, + KVSTORAGE_STATE_BACKEND_TYPE, + KVSTORAGE_STATE_EXPIRE_TYPE, + KVSTORAGE_STATE_ERROR + } state; + struct kvstorage_config *current_storage; + memory_pool_t *pool; + gchar *cur_elt; +}; + +static void +kvstorage_config_destroy (gpointer k) +{ + struct kvstorage_config *kconf = k; + + if (kconf->name) { + g_free (kconf->name); + } + + g_free (kconf); +} + + +/* XML parse callbacks */ +/* Called for open tags */ +void kvstorage_xml_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + struct kvstorage_config_parser *kv_parser = user_data; + + switch (kv_parser->state) { + case KVSTORAGE_STATE_INIT: + /* Make temporary pool */ + if (kv_parser->pool != NULL) { + memory_pool_delete (kv_parser->pool); + } + kv_parser->pool = memory_pool_new (memory_pool_get_size ()); + + /* Create new kvstorage_config */ + kv_parser->current_storage = g_malloc0 (sizeof (struct kvstorage_config)); + kv_parser->current_storage->id = ++last_id; + break; + case KVSTORAGE_STATE_PARAM: + if (g_ascii_strcasecmp (element_name, "type") == 0) { + kv_parser->state = KVSTORAGE_STATE_CACHE_TYPE; + } + else if (g_ascii_strcasecmp (element_name, "max_elements") == 0) { + kv_parser->state = KVSTORAGE_STATE_CACHE_MAX_ELTS; + } + else if (g_ascii_strcasecmp (element_name, "max_memory") == 0) { + kv_parser->state = KVSTORAGE_STATE_CACHE_MAX_MEM; + } + else if (g_ascii_strcasecmp (element_name, "id") == 0) { + kv_parser->state = KVSTORAGE_STATE_ID; + } + else if (g_ascii_strcasecmp (element_name, "name") == 0) { + kv_parser->state = KVSTORAGE_STATE_NAME; + } + else if (g_ascii_strcasecmp (element_name, "backend") == 0) { + kv_parser->state = KVSTORAGE_STATE_BACKEND; + } + else if (g_ascii_strcasecmp (element_name, "expire") == 0) { + kv_parser->state = KVSTORAGE_STATE_EXPIRE; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", + element_name); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + kv_parser->cur_elt = memory_pool_strdup (kv_parser->pool, element_name); + break; + case KVSTORAGE_STATE_BACKEND: + if (g_ascii_strcasecmp (element_name, "type") == 0) { + kv_parser->state = KVSTORAGE_STATE_BACKEND_TYPE; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in backend definition", + element_name); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + break; + case KVSTORAGE_STATE_EXPIRE: + if (g_ascii_strcasecmp (element_name, "type") == 0) { + kv_parser->state = KVSTORAGE_STATE_EXPIRE_TYPE; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in expire definition", + element_name); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + break; + default: + /* Do nothing at other states */ + break; + } + +} + +#define CHECK_TAG(s) \ +do { \ +if (g_ascii_strcasecmp (element_name, kv_parser->cur_elt) == 0) { \ + kv_parser->state = (s); \ +} \ +else { \ + if (*error == NULL) *error = g_error_new (xml_error_quark (), XML_UNMATCHED_TAG, "element %s is unexpected in this state, expected %s", element_name, kv_parser->cur_elt); \ + kv_parser->state = KVSTORAGE_STATE_ERROR; \ +} \ +} while (0) + +/* Called for close tags */ +void kvstorage_xml_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + struct kvstorage_config_parser *kv_parser = user_data; + + switch (kv_parser->state) { + case KVSTORAGE_STATE_INIT: + case KVSTORAGE_STATE_PARAM: + if (g_ascii_strcasecmp (element_name, "keystorage") == 0) { + /* XXX: Init actual storage */ + g_hash_table_insert (storages, &kv_parser->current_storage->id, kv_parser->current_storage); + kv_parser->state = KVSTORAGE_STATE_INIT; + g_markup_parse_context_pop (context); + return; + } + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "end element %s is unexpected, expected start element", + element_name); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + break; + case KVSTORAGE_STATE_ID: + case KVSTORAGE_STATE_NAME: + case KVSTORAGE_STATE_CACHE_TYPE: + case KVSTORAGE_STATE_CACHE_MAX_ELTS: + case KVSTORAGE_STATE_CACHE_MAX_MEM: + CHECK_TAG (KVSTORAGE_STATE_PARAM); + break; + case KVSTORAGE_STATE_BACKEND_TYPE: + CHECK_TAG (KVSTORAGE_STATE_BACKEND); + break; + case KVSTORAGE_STATE_EXPIRE_TYPE: + CHECK_TAG (KVSTORAGE_STATE_EXPIRE); + break; + case KVSTORAGE_STATE_BACKEND: + if (g_ascii_strcasecmp (element_name, "backend") == 0) { + kv_parser->state = KVSTORAGE_STATE_PARAM; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", + element_name); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + break; + case KVSTORAGE_STATE_EXPIRE: + if (g_ascii_strcasecmp (element_name, "expire") == 0) { + kv_parser->state = KVSTORAGE_STATE_PARAM; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected", + element_name); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + break; + default: + /* Do nothing at other states */ + break; + } +} +#undef CHECK_TAG + +/* text is not nul-terminated */ +void kvstorage_xml_text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + struct kvstorage_config_parser *kv_parser = user_data; + gchar *err_str; + + switch (kv_parser->state) { + case KVSTORAGE_STATE_INIT: + case KVSTORAGE_STATE_PARAM: + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "text is unexpected, expected start element"); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + break; + case KVSTORAGE_STATE_ID: + kv_parser->current_storage->id = strtoul (text, &err_str, 10); + if ((gsize)(err_str - text) != text_len) { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid number: %*s", (int)text_len, text); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + else { + last_id = kv_parser->current_storage->id; + } + break; + case KVSTORAGE_STATE_NAME: + kv_parser->current_storage->name = g_malloc (text_len + 1); + rspamd_strlcpy (kv_parser->current_storage->name, text, text_len + 1); + break; + case KVSTORAGE_STATE_CACHE_MAX_ELTS: + kv_parser->current_storage->cache.max_elements = parse_limit (text, text_len); + break; + case KVSTORAGE_STATE_CACHE_MAX_MEM: + kv_parser->current_storage->cache.max_memory = parse_limit (text, text_len); + break; + case KVSTORAGE_STATE_CACHE_TYPE: + if (g_ascii_strncasecmp (text, "hash", MIN (text_len, sizeof ("hash") - 1)) == 0) { + kv_parser->current_storage->cache.type = KVSTORAGE_TYPE_CACHE_HASH; + } + else if (g_ascii_strncasecmp (text, "radix", MIN (text_len, sizeof ("radix") - 1)) == 0) { + kv_parser->current_storage->cache.type = KVSTORAGE_TYPE_CACHE_RADIX; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid cache type: %*s", (int)text_len, text); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + break; + case KVSTORAGE_STATE_BACKEND_TYPE: + if (g_ascii_strncasecmp (text, "null", MIN (text_len, sizeof ("null") - 1)) == 0) { + kv_parser->current_storage->backend.type = KVSTORAGE_TYPE_BACKEND_NULL; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid backend type: %*s", (int)text_len, text); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + break; + case KVSTORAGE_STATE_EXPIRE_TYPE: + if (g_ascii_strncasecmp (text, "lru", MIN (text_len, sizeof ("lru") - 1)) == 0) { + kv_parser->current_storage->expire.type = KVSTORAGE_TYPE_EXPIRE_LRU; + } + else { + if (*error == NULL) { + *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "invalid expire type: %*s", (int)text_len, text); + } + kv_parser->state = KVSTORAGE_STATE_ERROR; + } + break; + default: + /* Do nothing at other states */ + break; + } + +} + +/* Called on error, including one set by other +* methods in the vtable. The GError should not be freed. +*/ +void kvstorage_xml_error (GMarkupParseContext *context, + GError *error, + gpointer user_data) +{ + msg_err ("kvstorage xml parser error: %s", error->message); +} + +/** Public API */ + +/* Init subparser of kvstorage config */ +void +init_kvstorage_config (void) +{ + GMarkupParser *parser; + struct kvstorage_config_parser *kv_parser; + + if (storages == NULL) { + storages = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, kvstorage_config_destroy); + } + else { + /* Create new global table */ + g_hash_table_destroy (storages); + storages = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, kvstorage_config_destroy); + } + + /* Create and register subparser */ + parser = g_malloc0 (sizeof (GMarkupParser)); + parser->start_element = kvstorage_xml_start_element; + parser->end_element = kvstorage_xml_end_element; + parser->error = kvstorage_xml_error; + parser->text = kvstorage_xml_text; + + kv_parser = g_malloc0 (sizeof (struct kvstorage_config_parser)); + kv_parser->state = KVSTORAGE_STATE_PARAM; + + register_subparser ("keystorage", XML_READ_START, parser, kv_parser); +} + +/* Get configuration for kvstorage with specified ID */ +struct kvstorage_config* +get_kvstorage_config (gint id) +{ + if (storages == NULL) { + return NULL; + } + return g_hash_table_lookup (storages, &id); +} diff --git a/src/kvstorage_config.h b/src/kvstorage_config.h new file mode 100644 index 000000000..567dd18be --- /dev/null +++ b/src/kvstorage_config.h @@ -0,0 +1,81 @@ +/* Copyright (c) 2010, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef KVSTORAGE_CONFIG_H_ +#define KVSTORAGE_CONFIG_H_ + +#include "config.h" +#include "kvstorage.h" + +/* Type of kvstorage cache */ +enum kvstorage_cache_type { + KVSTORAGE_TYPE_CACHE_HASH, + KVSTORAGE_TYPE_CACHE_RADIX +}; + +/* Type of kvstorage backend */ +enum kvstorage_backend_type { + KVSTORAGE_TYPE_BACKEND_NULL = 0 +}; + +/* Type of kvstorage expire */ +enum kvstorage_expire_type { + KVSTORAGE_TYPE_EXPIRE_LRU +}; + +/* Cache config */ +struct kvstorage_cache_config { + gsize max_elements; + gsize max_memory; + enum kvstorage_cache_type type; +}; + +/* Backend config */ +struct kvstorage_backend_config { + enum kvstorage_backend_type type; +}; + + +/* Expire config */ +struct kvstorage_expire_config { + enum kvstorage_expire_type type; +}; + +/* The main keystorage config */ +struct kvstorage_config { + gint id; + gchar *name; + struct kvstorage_cache_config cache; + struct kvstorage_backend_config backend; + struct kvstorage_expire_config expire; + struct rspamd_kv_storage *storage; +}; + +/* Init subparser of kvstorage config */ +void init_kvstorage_config (void); + +/* Get configuration for kvstorage with specified ID */ +struct kvstorage_config* get_kvstorage_config (gint id); + +#endif /* KVSTORAGE_CONFIG_H_ */ diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index 519666662..e4eb82398 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -498,7 +498,7 @@ regexp_module_config (struct config_file *cfg) regexp_module_ctx->statfile_prefix = DEFAULT_STATFILE_PREFIX; } if ((value = get_module_opt (cfg, "regexp", "max_size")) != NULL) { - regexp_module_ctx->max_size = parse_limit (value); + regexp_module_ctx->max_size = parse_limit (value, -1); } else { regexp_module_ctx->max_size = 0; diff --git a/src/tokenizers/tokenizers.c b/src/tokenizers/tokenizers.c index 902245e7d..2eb11eff8 100644 --- a/src/tokenizers/tokenizers.c +++ b/src/tokenizers/tokenizers.c @@ -256,7 +256,6 @@ tokenize_subject (struct worker_task *task, GTree ** tree) { f_str_t subject; const gchar *sub; - token_node_t *new = NULL; struct tokenizer *osb_tokenizer; if (*tree == NULL) { @@ -268,13 +267,11 @@ tokenize_subject (struct worker_task *task, GTree ** tree) /* Try to use pre-defined subject */ if (task->subject != NULL) { - new = memory_pool_alloc (task->task_pool, sizeof (token_node_t)); subject.begin = task->subject; subject.len = strlen (task->subject); osb_tokenizer->tokenize_func (osb_tokenizer, task->task_pool, &subject, tree, FALSE, TRUE, NULL); } if ((sub = g_mime_message_get_subject (task->message)) != NULL) { - new = memory_pool_alloc (task->task_pool, sizeof (token_node_t)); subject.begin = (gchar *)sub; subject.len = strlen (sub); osb_tokenizer->tokenize_func (osb_tokenizer, task->task_pool, &subject, tree, FALSE, TRUE, NULL); -- 2.39.5