struct rspamd_fuzzy_cmd *cmd;
gpointer ptr;
guint nupdates = 0;
+ time_t now = time (NULL);
if (ctx->updates_pending &&
g_queue_get_length (ctx->updates_pending) > 0 &&
}
if (cmd->cmd == FUZZY_WRITE) {
- rspamd_fuzzy_backend_add (ctx->backend, ptr);
+ rspamd_fuzzy_backend_add (ctx->backend, ptr, now);
}
else {
rspamd_fuzzy_backend_del (ctx->backend, ptr);
}
g_queue_clear (ctx->updates_pending);
- msg_info ("updated fuzzy storage: %ud updates processed", nupdates);
+ msg_info ("updated fuzzy storage: %ud updates processed, version: %d",
+ nupdates, rspamd_fuzzy_backend_version (ctx->backend));
}
else {
msg_err ("cannot commit update transaction to fuzzy backend, "
RSPAMD_FUZZY_BACKEND_EXPIRE,
RSPAMD_FUZZY_BACKEND_VACUUM,
RSPAMD_FUZZY_BACKEND_DELETE_ORPHANED,
+ RSPAMD_FUZZY_BACKEND_VERSION,
RSPAMD_FUZZY_BACKEND_MAX
};
static struct rspamd_fuzzy_stmts {
.stmt = NULL,
.result = SQLITE_DONE
},
+ {
+ .idx = RSPAMD_FUZZY_BACKEND_VERSION,
+ .sql = "PRAGMA user_version;",
+ .args = "",
+ .stmt = NULL,
+ .result = SQLITE_ROW
+ },
};
static GQuark
gboolean
rspamd_fuzzy_backend_add (struct rspamd_fuzzy_backend *backend,
- const struct rspamd_fuzzy_cmd *cmd)
+ const struct rspamd_fuzzy_cmd *cmd,
+ time_t timestamp)
{
int rc, i;
gint64 id, flag;
(gint) cmd->flag,
cmd->digest,
(gint64) cmd->value,
- (gint64) time (NULL));
+ (gint64) timestamp);
if (rc == SQLITE_OK) {
if (cmd->shingles_count > 0) {
gboolean
rspamd_fuzzy_backend_finish_update (struct rspamd_fuzzy_backend *backend)
{
- gint rc, wal_frames, wal_checkpointed;
+ gint rc, wal_frames, wal_checkpointed, ver;
+ gint64 version = 0;
+ gchar version_buf[128];
rc = rspamd_fuzzy_backend_run_stmt (backend, TRUE,
RSPAMD_FUZZY_BACKEND_TRANSACTION_COMMIT);
}
}
+ /* Get and update version */
+ ver = rspamd_fuzzy_backend_version (backend);
+ ++ver;
+ rspamd_snprintf (version_buf, sizeof (version_buf), "PRAGMA user_version=%d;",
+ ver);
+
+ if (sqlite3_exec (backend->db, version_buf, NULL, NULL, NULL) != SQLITE_OK) {
+ msg_err_fuzzy_backend ("cannot set database version to %L: %s",
+ version, sqlite3_errmsg (backend->db));
+ }
+
return TRUE;
}
return 0;
}
+gint
+rspamd_fuzzy_backend_version (struct rspamd_fuzzy_backend *backend)
+{
+ gint ret = 0;
+
+ if (backend) {
+ if (rspamd_fuzzy_backend_run_stmt (backend, FALSE,
+ RSPAMD_FUZZY_BACKEND_VERSION) == SQLITE_OK) {
+ ret = sqlite3_column_int64 (
+ prepared_stmts[RSPAMD_FUZZY_BACKEND_VERSION].stmt, 0);
+ }
+
+ rspamd_fuzzy_backend_cleanup_stmt (backend, RSPAMD_FUZZY_BACKEND_VERSION);
+ }
+
+ return ret;
+}
+
gsize
rspamd_fuzzy_backend_expired (struct rspamd_fuzzy_backend *backend)
{
*/
gboolean rspamd_fuzzy_backend_add (
struct rspamd_fuzzy_backend *backend,
- const struct rspamd_fuzzy_cmd *cmd);
+ const struct rspamd_fuzzy_cmd *cmd,
+ time_t timestamp);
/**
* Delete digest from the database
void rspamd_fuzzy_backend_close (struct rspamd_fuzzy_backend *backend);
gsize rspamd_fuzzy_backend_count (struct rspamd_fuzzy_backend *backend);
+gint rspamd_fuzzy_backend_version (struct rspamd_fuzzy_backend *backend);
gsize rspamd_fuzzy_backend_expired (struct rspamd_fuzzy_backend *backend);
const gchar * rspamd_fuzzy_backend_id (struct rspamd_fuzzy_backend *backend);