diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-07-09 18:48:21 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-07-09 18:48:21 +0100 |
commit | 96d20fb28f752149c17df289ec7adc2180f2ba65 (patch) | |
tree | 0c1c0bd6c13ddafa7169ab9e0f4d044bf1de01da | |
parent | aac27905de964f0f91f6a9366f596b1197d574ff (diff) | |
download | rspamd-96d20fb28f752149c17df289ec7adc2180f2ba65.tar.gz rspamd-96d20fb28f752149c17df289ec7adc2180f2ba65.zip |
Try to fix sqlite3 blocking.
Issue: #331
-rw-r--r-- | src/libstat/learn_cache/sqlite3_cache.c | 55 |
1 files changed, 43 insertions, 12 deletions
diff --git a/src/libstat/learn_cache/sqlite3_cache.c b/src/libstat/learn_cache/sqlite3_cache.c index 017ee6108..a9e74edbb 100644 --- a/src/libstat/learn_cache/sqlite3_cache.c +++ b/src/libstat/learn_cache/sqlite3_cache.c @@ -33,7 +33,7 @@ #include <sqlite3.h> static const char *create_tables_sql = - "BEGIN;" + "BEGIN IMMEDIATE;" "CREATE TABLE IF NOT EXISTS learns(" "id INTEGER PRIMARY KEY," "flag INTEGER NOT NULL," @@ -54,11 +54,13 @@ rspamd_stat_cache_sqlite3_init(struct rspamd_stat_ctx *ctx, struct rspamd_stat_sqlite3_ctx *new = NULL; struct rspamd_classifier_config *clf; const ucl_object_t *obj, *elt; + static const char sqlite_wal[] = "PRAGMA journal_mode=WAL;", + fallback_journal[] = "PRAGMA journal_mode=OFF;"; GList *cur; gchar dbpath[PATH_MAX]; sqlite3 *sqlite; gboolean has_sqlite_cache = FALSE; - gint rc; + gint rc, fd; rspamd_snprintf (dbpath, sizeof (dbpath), SQLITE_CACHE_PATH); cur = cfg->classifiers; @@ -93,19 +95,29 @@ rspamd_stat_cache_sqlite3_init(struct rspamd_stat_ctx *ctx, if (has_sqlite_cache) { if ((rc = sqlite3_open_v2 (dbpath, &sqlite, - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_NOMUTEX, NULL)) + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL)) != SQLITE_OK) { - msg_err ("Cannot open sqlite db %s: %s", SQLITE_CACHE_PATH, + msg_err ("Cannot open sqlite db %s: %s", dbpath, sqlite3_errmsg (sqlite)); return NULL; } + else { + msg_debug ("opened sqlite cache at the path %s", dbpath); + } + + if (sqlite3_exec (sqlite, sqlite_wal, NULL, NULL, NULL) != SQLITE_OK) { + msg_warn ("WAL mode is not supported, locking issues might occur"); + sqlite3_exec (sqlite, fallback_journal, NULL, NULL, NULL); + } if ((rc = sqlite3_exec (sqlite, create_tables_sql, NULL, NULL, NULL)) != SQLITE_OK) { msg_err ("Cannot initialize sqlite db %s: %s", SQLITE_CACHE_PATH, sqlite3_errmsg (sqlite)); sqlite3_close (sqlite); + rspamd_file_unlock (fd, FALSE); + close (fd); return NULL; } @@ -122,9 +134,14 @@ rspamd_stat_cache_sqlite3_check (const guchar *h, gsize len, gboolean is_spam, struct rspamd_stat_sqlite3_ctx *ctx) { static const gchar select_sql[] = "SELECT flag FROM learns WHERE digest=?1"; - static const gchar insert_sql[] = "INSERT INTO learns(digest, flag) VALUES " - "(?1, ?2);"; - static const gchar update_sql[] = "UPDATE learns SET flag=?1 WHERE digest=?2"; + static const gchar insert_sql[] = "" + "" + "INSERT INTO learns(digest, flag) VALUES (?1, ?2);" + ""; + static const gchar update_sql[] = "" + "" + "UPDATE learns SET flag=?1 WHERE digest=?2;" + ""; sqlite3_stmt *st = NULL; gint rc, ret = RSPAMD_LEARN_OK, flag; @@ -151,34 +168,48 @@ rspamd_stat_cache_sqlite3_check (const guchar *h, gsize len, gboolean is_spam, /* Need to relearn */ if ((rc = sqlite3_prepare_v2 (ctx->db, update_sql, -1, &st, NULL)) != SQLITE_OK) { - msg_err ("Cannot prepare sql %s: %s", update_sql, + msg_err ("cannot prepare sql %s: %s", update_sql, sqlite3_errmsg (ctx->db)); } else { sqlite3_bind_int (st, 1, is_spam ? 1 : 0); sqlite3_bind_text (st, 2, h, len, SQLITE_STATIC); - sqlite3_step (st); + + if ((rc = sqlite3_step (st)) != SQLITE_DONE) { + msg_err ("error during executing sql %s: %s", update_sql, + sqlite3_errmsg (ctx->db)); + } + sqlite3_finalize (st); } return RSPAMD_LEARN_UNLEARN; } } - else { + else if (rc != SQLITE_ERROR && rc != SQLITE_BUSY) { /* Insert result new id */ sqlite3_finalize (st); if ((rc = sqlite3_prepare_v2 (ctx->db, insert_sql, -1, &st, NULL)) != SQLITE_OK) { - msg_err ("Cannot prepare sql %s: %s", insert_sql, + msg_err ("cannot prepare sql %s: %s", insert_sql, sqlite3_errmsg (ctx->db)); } else { sqlite3_bind_text (st, 1, h, len, SQLITE_STATIC); sqlite3_bind_int (st, 2, is_spam ? 1 : 0); - sqlite3_step (st); + + if ((rc = sqlite3_step (st)) != SQLITE_DONE) { + msg_err ("error during executing sql %s: %s", insert_sql, + sqlite3_errmsg (ctx->db)); + } + sqlite3_finalize (st); } } + else { + msg_err ("error during executing sql %s: %s", select_sql, + sqlite3_errmsg (ctx->db)); + } return ret; } |