aboutsummaryrefslogtreecommitdiffstats
path: root/src/kvstorage_config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kvstorage_config.c')
-rw-r--r--src/kvstorage_config.c603
1 files changed, 0 insertions, 603 deletions
diff --git a/src/kvstorage_config.c b/src/kvstorage_config.c
deleted file mode 100644
index f236c2b4b..000000000
--- a/src/kvstorage_config.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/* 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.
- */
-
-#include "kvstorage_config.h"
-#include "main.h"
-#include "cfg_xml.h"
-#ifdef WITH_DB
-#include "kvstorage_bdb.h"
-#endif
-#ifdef WITH_SQLITE
-#include "kvstorage_sqlite.h"
-#endif
-#include "kvstorage_file.h"
-
-#define FILE_STORAGE_LEVELS 3
-
-
-/* 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_CACHE_NO_OVERWRITE,
- KVSTORAGE_STATE_BACKEND_TYPE,
- KVSTORAGE_STATE_BACKEND_FILENAME,
- KVSTORAGE_STATE_BACKEND_SYNC_OPS,
- KVSTORAGE_STATE_BACKEND_DO_FSYNC,
- KVSTORAGE_STATE_BACKEND_DO_REF,
- KVSTORAGE_STATE_EXPIRE_TYPE,
- KVSTORAGE_STATE_ERROR
- } state;
- struct kvstorage_config *current_storage;
- rspamd_mempool_t *pool;
- gchar *cur_elt;
-};
-
-static void
-kvstorage_config_destroy (gpointer k)
-{
- struct kvstorage_config *kconf = k;
-
- if (kconf->name) {
- g_free (kconf->name);
- }
-
- if (kconf->storage) {
- rspamd_kv_storage_destroy (kconf->storage);
- }
-
- g_free (kconf);
-}
-
-/* Init kvstorage */
-static void
-kvstorage_init_callback (const gpointer key,
- const gpointer value,
- gpointer unused)
-{
- struct kvstorage_config *kconf = value;
- struct rspamd_kv_cache *cache;
- struct rspamd_kv_backend *backend = NULL;
- struct rspamd_kv_expire *expire = NULL;
-
- switch (kconf->cache.type) {
- case KVSTORAGE_TYPE_CACHE_HASH:
- cache = rspamd_kv_hash_new ();
- break;
- case KVSTORAGE_TYPE_CACHE_RADIX:
- cache = rspamd_kv_radix_new ();
- break;
-#ifdef WITH_JUDY
- case KVSTORAGE_TYPE_CACHE_JUDY:
- cache = rspamd_kv_judy_new ();
- break;
-#endif
- default:
- msg_err ("unknown cache type, internal error");
- return;
- }
-
- switch (kconf->backend.type) {
- case KVSTORAGE_TYPE_BACKEND_NULL:
- case KVSTORAGE_TYPE_BACKEND_MAX:
- backend = NULL;
- break;
- case KVSTORAGE_TYPE_BACKEND_FILE:
- backend = rspamd_kv_file_new (kconf->backend.filename,
- kconf->backend.sync_ops,
- FILE_STORAGE_LEVELS,
- kconf->backend.do_fsync,
- kconf->backend.do_ref);
- break;
-#ifdef WITH_DB
- case KVSTORAGE_TYPE_BACKEND_BDB:
- backend = rspamd_kv_bdb_new (kconf->backend.filename,
- kconf->backend.sync_ops);
- break;
-#endif
-#ifdef WITH_SQLITE
- case KVSTORAGE_TYPE_BACKEND_SQLITE:
- backend = rspamd_kv_sqlite_new (kconf->backend.filename,
- kconf->backend.sync_ops);
- break;
-#endif
- }
-
- switch (kconf->expire.type) {
- case KVSTORAGE_TYPE_EXPIRE_LRU:
- expire = rspamd_lru_expire_new ();
- break;
- }
-
- kconf->storage = rspamd_kv_storage_new (kconf->id,
- kconf->name,
- cache,
- backend,
- expire,
- kconf->cache.max_elements,
- kconf->cache.max_memory,
- kconf->cache.no_overwrite);
-}
-
-/* XML parse callbacks */
-/* Called for open tags <foo bar="baz"> */
-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:
- /* XXX: never get this state */
- break;
- case KVSTORAGE_STATE_PARAM:
- if (kv_parser->current_storage == NULL) {
- /* Make temporary pool */
- if (kv_parser->pool != NULL) {
- rspamd_mempool_delete (kv_parser->pool);
- }
- kv_parser->pool =
- rspamd_mempool_new (rspamd_mempool_suggest_size ());
-
- /* Create new kvstorage_config */
- kv_parser->current_storage =
- g_malloc0 (sizeof (struct kvstorage_config));
- kv_parser->current_storage->id = last_id++;
- }
- if (g_ascii_strcasecmp (element_name, "type") == 0) {
- kv_parser->state = KVSTORAGE_STATE_CACHE_TYPE;
- kv_parser->cur_elt = "type";
- }
- else if (g_ascii_strcasecmp (element_name, "max_elements") == 0) {
- kv_parser->state = KVSTORAGE_STATE_CACHE_MAX_ELTS;
- kv_parser->cur_elt = "max_elements";
- }
- else if (g_ascii_strcasecmp (element_name, "max_memory") == 0) {
- kv_parser->state = KVSTORAGE_STATE_CACHE_MAX_MEM;
- kv_parser->cur_elt = "max_memory";
- }
- else if (g_ascii_strcasecmp (element_name, "no_overwrite") == 0) {
- kv_parser->state = KVSTORAGE_STATE_CACHE_NO_OVERWRITE;
- kv_parser->cur_elt = "no_overwrite";
- }
- else if (g_ascii_strcasecmp (element_name, "id") == 0) {
- kv_parser->state = KVSTORAGE_STATE_ID;
- kv_parser->cur_elt = "id";
- }
- else if (g_ascii_strcasecmp (element_name, "name") == 0) {
- kv_parser->state = KVSTORAGE_STATE_NAME;
- kv_parser->cur_elt = "name";
- }
- else if (g_ascii_strcasecmp (element_name, "backend") == 0) {
- kv_parser->state = KVSTORAGE_STATE_BACKEND;
- kv_parser->cur_elt = "backend";
- }
- else if (g_ascii_strcasecmp (element_name, "expire") == 0) {
- kv_parser->state = KVSTORAGE_STATE_EXPIRE;
- kv_parser->cur_elt = "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;
- }
- break;
- case KVSTORAGE_STATE_BACKEND:
- if (g_ascii_strcasecmp (element_name, "type") == 0) {
- kv_parser->state = KVSTORAGE_STATE_BACKEND_TYPE;
- kv_parser->cur_elt = "type";
- }
- else if (g_ascii_strcasecmp (element_name, "filename") == 0) {
- kv_parser->state = KVSTORAGE_STATE_BACKEND_FILENAME;
- kv_parser->cur_elt = "filename";
- }
- else if (g_ascii_strcasecmp (element_name, "sync_ops") == 0) {
- kv_parser->state = KVSTORAGE_STATE_BACKEND_SYNC_OPS;
- kv_parser->cur_elt = "sync_ops";
- }
- else if (g_ascii_strcasecmp (element_name, "fsync") == 0) {
- kv_parser->state = KVSTORAGE_STATE_BACKEND_DO_FSYNC;
- kv_parser->cur_elt = "fsync";
- }
- else if (g_ascii_strcasecmp (element_name, "ref") == 0) {
- kv_parser->state = KVSTORAGE_STATE_BACKEND_DO_REF;
- kv_parser->cur_elt = "ref";
- }
- 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;
- kv_parser->cur_elt = "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 </foo> */
-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 */
- 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:
- case KVSTORAGE_STATE_CACHE_NO_OVERWRITE:
- CHECK_TAG (KVSTORAGE_STATE_PARAM);
- break;
- case KVSTORAGE_STATE_BACKEND_TYPE:
- case KVSTORAGE_STATE_BACKEND_FILENAME:
- case KVSTORAGE_STATE_BACKEND_SYNC_OPS:
- case KVSTORAGE_STATE_BACKEND_DO_FSYNC:
- case KVSTORAGE_STATE_BACKEND_DO_REF:
- 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;
-
- /* Strip space symbols */
- while (*text && g_ascii_isspace (*text)) {
- text++;
- }
- if (*text == '\0') {
- /* Skip empty text */
- return;
- }
-
- 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++;
- last_id = MAX (kv_parser->current_storage->id, last_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 =
- rspamd_config_parse_limit (text, text_len);
- break;
- case KVSTORAGE_STATE_CACHE_MAX_MEM:
- kv_parser->current_storage->cache.max_memory =
- rspamd_config_parse_limit (text, text_len);
- break;
- case KVSTORAGE_STATE_CACHE_NO_OVERWRITE:
- kv_parser->current_storage->cache.no_overwrite =
- rspamd_config_parse_flag (text);
- 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;
- }
-#ifdef WITH_JUDY
- else if (g_ascii_strncasecmp (text, "judy",
- MIN (text_len, sizeof ("judy") - 1)) == 0) {
- kv_parser->current_storage->cache.type = KVSTORAGE_TYPE_CACHE_JUDY;
- }
-#endif
- 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 (g_ascii_strncasecmp (text, "file",
- MIN (text_len, sizeof ("file") - 1)) == 0) {
- kv_parser->current_storage->backend.type =
- KVSTORAGE_TYPE_BACKEND_FILE;
- }
-#ifdef WITH_DB
- else if (g_ascii_strncasecmp (text, "bdb",
- MIN (text_len, sizeof ("bdb") - 1)) == 0) {
- kv_parser->current_storage->backend.type =
- KVSTORAGE_TYPE_BACKEND_BDB;
- }
-#endif
-#ifdef WITH_SQLITE
- else if (g_ascii_strncasecmp (text, "sqlite",
- MIN (text_len, sizeof ("sqlite") - 1)) == 0) {
- kv_parser->current_storage->backend.type =
- KVSTORAGE_TYPE_BACKEND_SQLITE;
- }
-#endif
- 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_BACKEND_FILENAME:
- kv_parser->current_storage->backend.filename = g_malloc (text_len + 1);
- rspamd_strlcpy (kv_parser->current_storage->backend.filename,
- text,
- text_len + 1);
- break;
- case KVSTORAGE_STATE_BACKEND_SYNC_OPS:
- kv_parser->current_storage->backend.sync_ops =
- rspamd_config_parse_limit (text, text_len);
- break;
- case KVSTORAGE_STATE_BACKEND_DO_FSYNC:
- kv_parser->current_storage->backend.do_fsync =
- rspamd_config_parse_flag (text);
- break;
- case KVSTORAGE_STATE_BACKEND_DO_REF:
- kv_parser->current_storage->backend.do_ref = rspamd_config_parse_flag (
- text);
- 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);
-}
-
-/*
- * Cleanup kvstorage after end tag was read
- */
-static void
-kvstorage_cleanup (gpointer ud)
-{
- struct kvstorage_config_parser *kv_parser = ud;
-
- g_hash_table_insert (storages,
- &kv_parser->current_storage->id,
- kv_parser->current_storage);
- kv_parser->state = KVSTORAGE_STATE_INIT;
- g_hash_table_foreach (storages, kvstorage_init_callback, NULL);
- kv_parser->current_storage = NULL;
-}
-
-/** 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;
- kv_parser->pool = rspamd_mempool_new (rspamd_mempool_suggest_size ());
-
- register_subparser ("keystorage", 0, parser, kvstorage_cleanup, 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);
-}
-
-void
-destroy_kvstorage_config (void)
-{
- if (storages != NULL) {
- g_hash_table_destroy (storages);
- storages = NULL;
- }
-}