]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Add locking for maps.
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 8 Jan 2013 14:24:24 +0000 (18:24 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 8 Jan 2013 14:24:24 +0000 (18:24 +0400)
Add ability to save rolling history in a file.

src/cfg_file.h
src/cfg_xml.c
src/main.c
src/map.c
src/map.h
src/roll_history.c
src/roll_history.h

index 538167ea8783fe2e208f153dbea2074d2e2600b5..e3e24759e41d40a0464d8e457f0b7e9bacd1e8fc 100644 (file)
@@ -359,6 +359,8 @@ struct config_file {
 
        gchar* rrd_file;                                                                /**< rrd file to store statistics                                               */
 
+       gchar* history_file;                                                    /**< file to save rolling history                                               */
+
        guint32 dns_timeout;                                                    /**< timeout in milliseconds for waiting for dns reply  */
        guint32 dns_retransmits;                                                /**< maximum retransmits count                                                  */
        guint32 dns_throttling_errors;                                  /**< maximum errors for starting resolver throttling    */
index f81492d774647d4abcb6f39bda352cb03f4d552e..71767cc3cd33182cb139d53aa9db17b95e002e4a 100644 (file)
@@ -330,6 +330,12 @@ static struct xml_parser_rule grammar[] = {
                                G_STRUCT_OFFSET (struct config_file, rrd_file),
                                NULL
                        },
+                       {
+                               "history_file",
+                               xml_handle_string,
+                               G_STRUCT_OFFSET (struct config_file, history_file),
+                               NULL
+                       },
                        NULL_ATTR
                },
                NULL_DEF_ATTR
index c450500ad83bf233c549327c947afdd66ff262d7..e50b223aabb0f837de661239c91538c276e295dd 100644 (file)
@@ -1093,6 +1093,11 @@ main (gint argc, gchar **argv, gchar **env)
        /* Preload all statfiles */
        preload_statfiles (rspamd_main);
 
+       /* Maybe read roll history */
+       if (rspamd_main->cfg->history_file) {
+               rspamd_roll_history_load (rspamd_main->history, rspamd_main->cfg->history_file);
+       }
+
        /* Spawn workers */
        rspamd_main->workers = g_hash_table_new (g_direct_hash, g_direct_equal);
        spawn_workers (rspamd_main);
@@ -1181,6 +1186,11 @@ main (gint argc, gchar **argv, gchar **env)
        /* Wait for workers termination */
        g_hash_table_foreach_remove (rspamd_main->workers, wait_for_workers, NULL);
 
+       /* Maybe save roll history */
+       if (rspamd_main->cfg->history_file) {
+               rspamd_roll_history_save (rspamd_main->history, rspamd_main->cfg->history_file);
+       }
+
        msg_info ("terminating...");
 
        statfile_pool_delete (rspamd_main->statfile_pool);
index 09b4df8df7d0a2ac391a97b30a2c9cc052937834..07e13b7ef1df340e5ae81b1905adb437499509ee 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -761,6 +761,11 @@ file_callback (gint fd, short what, void *ud)
        map->tv.tv_usec = 0;
        evtimer_add (&map->ev, &map->tv);
 
+       if (g_atomic_int_get (map->locked)) {
+               msg_info ("don't try to reread map as it is locked by other process, will reread it later");
+               return;
+       }
+
        if (stat (data->filename, &st) != -1 && (st.st_mtime > data->st.st_mtime || data->st.st_mtime == -1)) {
                /* File was modified since last check */
                memcpy (&data->st, &st, sizeof (struct stat));
@@ -882,6 +887,10 @@ http_callback (gint fd, short what, void *ud)
        map->tv.tv_usec = 0;
        evtimer_add (&map->ev, &map->tv);
 
+       if (g_atomic_int_get (map->locked)) {
+               msg_info ("don't try to reread map as it is locked by other process, will reread it later");
+               return;
+       }
        /* Connect asynced */
        if ((sock = connect_http (map, data, TRUE)) == -1) {
                return;
@@ -1011,6 +1020,7 @@ add_map (struct config_file *cfg, const gchar *map_line, const gchar *descriptio
        new_map->cfg = cfg;
        new_map->uri = memory_pool_strdup (cfg->cfg_pool, proto == MAP_PROTO_FILE ? def : map_line);
        new_map->id = g_random_int ();
+       new_map->locked = memory_pool_alloc0_shared (cfg->cfg_pool, sizeof (gint));
        if (description != NULL) {
                new_map->description = memory_pool_strdup (cfg->cfg_pool, description);
        }
index 5005786dca023bf8d1afec2ca67259b21c962e63..8623e68453733199bac2210a18e0aad4d1f85826 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -73,6 +73,8 @@ struct rspamd_map {
        gchar *uri;
        gchar *description;
        guint32 id;
+       /* Shared lock for temporary disabling of map reading (e.g. when this map is written by UI) */
+       gint *locked;
 };
 
 /**
index fec13045a588d7e981ed72078438f591f6cedc85..69f14176282ad428783077be4469878f9e51f07c 100644 (file)
@@ -143,3 +143,68 @@ rspamd_roll_history_update (struct roll_history *history, struct worker_task *ta
        row->len = task->msg->len;
        row->completed = TRUE;
 }
+
+/**
+ * Load previously saved history from file
+ * @param history roll history object
+ * @param filename filename to load from
+ * @return TRUE if history has been loaded
+ */
+gboolean
+rspamd_roll_history_load (struct roll_history *history, const gchar *filename)
+{
+       gint                                                                     fd;
+       struct stat                                                              st;
+
+       if (stat (filename, &st) == -1) {
+               msg_info ("cannot load history from %s: %s", filename, strerror (errno));
+               return FALSE;
+       }
+
+       if (st.st_size != sizeof (history->rows)) {
+               msg_info ("cannot load history from %s: size mismatch", filename);
+               return FALSE;
+       }
+
+       if ((fd = open (filename, O_RDONLY)) == -1) {
+               msg_info ("cannot load history from %s: %s", filename, strerror (errno));
+               return FALSE;
+       }
+
+       if (read (fd, history->rows, sizeof (history->rows)) == -1) {
+               close (fd);
+               msg_info ("cannot read history from %s: %s", filename, strerror (errno));
+               return FALSE;
+       }
+
+       close (fd);
+
+       return TRUE;
+}
+
+/**
+ * Save history to file
+ * @param history roll history object
+ * @param filename filename to load from
+ * @return TRUE if history has been saved
+ */
+gboolean
+rspamd_roll_history_save (struct roll_history *history, const gchar *filename)
+{
+       gint                                                                     fd;
+
+       if ((fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 00600)) == -1) {
+               msg_info ("cannot save history to %s: %s", filename, strerror (errno));
+               return FALSE;
+       }
+
+       if (write (fd, history->rows, sizeof (history->rows)) == -1) {
+               close (fd);
+               msg_info ("cannot write history to %s: %s", filename, strerror (errno));
+               return FALSE;
+       }
+
+       close (fd);
+
+       return TRUE;
+}
index c2e378bf9e5be0451502c275ce26fe330f822f86..58ce6e9d9dbcb45e5f92aed0cfa633d8cfbb5e5b 100644 (file)
@@ -87,4 +87,20 @@ struct roll_history* rspamd_roll_history_new (memory_pool_t *pool);
  */
 void rspamd_roll_history_update (struct roll_history *history, struct worker_task *task);
 
+/**
+ * Load previously saved history from file
+ * @param history roll history object
+ * @param filename filename to load from
+ * @return TRUE if history has been loaded
+ */
+gboolean rspamd_roll_history_load (struct roll_history *history, const gchar *filename);
+
+/**
+ * Save history to file
+ * @param history roll history object
+ * @param filename filename to load from
+ * @return TRUE if history has been saved
+ */
+gboolean rspamd_roll_history_save (struct roll_history *history, const gchar *filename);
+
 #endif /* ROLL_HISTORY_H_ */