]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Allow to have a stack of watcher finalisers
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 21 Apr 2017 09:08:31 +0000 (10:08 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 21 Apr 2017 09:08:31 +0000 (10:08 +0100)
src/libserver/events.c
src/libserver/events.h

index 8a3d0738d014d7a23dc55a0e002af7d022c27bd7..6021f0a395d608b9aae95821e9de89579cb774e8 100644 (file)
@@ -15,6 +15,7 @@
  */
 #include "config.h"
 #include "rspamd.h"
+#include "contrib/uthash/utlist.h"
 #include "events.h"
 #include "cryptobox.h"
 
         G_STRFUNC, \
         __VA_ARGS__)
 
-struct rspamd_async_watcher {
+struct rspamd_watch_stack {
        event_watcher_t cb;
        gpointer ud;
+       struct rspamd_watch_stack *next;
+};
+
+struct rspamd_async_watcher {
+       struct rspamd_watch_stack *st;
        guint remain;
        gint id;
 };
@@ -154,6 +160,19 @@ rspamd_session_add_event (struct rspamd_async_session *session,
                g_quark_to_string (subsystem));
 }
 
+static inline void
+rspamd_session_call_watcher_stack (struct rspamd_async_session *session,
+               struct rspamd_async_watcher *w)
+{
+       struct rspamd_watch_stack *st;
+
+       LL_FOREACH (w->st, st) {
+               st->cb (session->user_data, st->ud);
+       }
+
+       w->st = NULL;
+}
+
 void
 rspamd_session_remove_event (struct rspamd_async_session *session,
        event_finalizer_t fin,
@@ -182,7 +201,7 @@ rspamd_session_remove_event (struct rspamd_async_session *session,
        if (found_ev->w) {
                if (found_ev->w->remain > 0) {
                        if (--found_ev->w->remain == 0) {
-                               found_ev->w->cb (session->user_data, found_ev->w->ud);
+                               rspamd_session_call_watcher_stack (session, found_ev->w);
                        }
                }
        }
@@ -278,19 +297,23 @@ rspamd_session_watch_start (struct rspamd_async_session *session,
                event_watcher_t cb,
                gpointer ud)
 {
+       struct rspamd_watch_stack *st_elt;
+
        g_assert (session != NULL);
        g_assert (!RSPAMD_SESSION_IS_WATCHING (session));
 
        if (session->cur_watcher == NULL) {
-               session->cur_watcher = rspamd_mempool_alloc (session->pool,
+               session->cur_watcher = rspamd_mempool_alloc0 (session->pool,
                                sizeof (*session->cur_watcher));
+               session->flags |= RSPAMD_SESSION_FLAG_WATCHING;
        }
 
-       session->cur_watcher->cb = cb;
-       session->cur_watcher->remain = 0;
-       session->cur_watcher->ud = ud;
+       st_elt = rspamd_mempool_alloc (session->pool, sizeof (*st_elt));
+       st_elt->cb = cb;
+       st_elt->ud = ud;
+       LL_PREPEND (session->cur_watcher->st, st_elt);
+
        session->cur_watcher->id = id;
-       session->flags |= RSPAMD_SESSION_FLAG_WATCHING;
 }
 
 guint
@@ -333,31 +356,52 @@ rspamd_session_events_pending (struct rspamd_async_session *session)
        return npending;
 }
 
-void
-rspamd_session_watcher_push (struct rspamd_async_session *session)
+inline void
+rspamd_session_watcher_push_callback (struct rspamd_async_session *session,
+               struct rspamd_async_watcher *w,
+               event_watcher_t cb,
+               gpointer ud)
 {
+       struct rspamd_watch_stack *st;
+
        g_assert (session != NULL);
 
-       if (RSPAMD_SESSION_IS_WATCHING (session)) {
-               session->cur_watcher->remain ++;
+       if (w == NULL) {
+               if (RSPAMD_SESSION_IS_WATCHING (session)) {
+                       w = session->cur_watcher;
+               }
+               else {
+                       return;
+               }
+       }
+
+       if (w) {
+               w->remain ++;
                msg_debug_session ("push session, watcher: %d, %d events",
-                               session->cur_watcher->id,
-                               session->cur_watcher->remain);
+                               w->id,
+                               w->remain);
+
+               if (cb) {
+                       st = rspamd_mempool_alloc (session->pool, sizeof (*st));
+                       st->cb = cb;
+                       st->ud = ud;
+
+                       LL_PREPEND (w->st, st);
+               }
        }
 }
 
+void
+rspamd_session_watcher_push (struct rspamd_async_session *session)
+{
+       rspamd_session_watcher_push_callback (session, NULL, NULL, NULL);
+}
+
 void
 rspamd_session_watcher_push_specific (struct rspamd_async_session *session,
                struct rspamd_async_watcher *w)
 {
-       g_assert (session != NULL);
-
-       if (w) {
-               w->remain ++;
-               msg_debug_session ("push specific, watcher: %d, %d events",
-                               w->id,
-                               w->remain);
-       }
+       rspamd_session_watcher_push_callback (session, w, NULL, NULL);
 }
 
 void
@@ -371,7 +415,7 @@ rspamd_session_watcher_pop (struct rspamd_async_session *session,
                                w->remain);
 
                if (--w->remain == 0) {
-                       w->cb (session->user_data, w->ud);
+                       rspamd_session_call_watcher_stack (session, w);
                }
        }
 }
index 71854f205ce7ce281402574d69a43915e5bd7107..1c9b49faf57d70f4411367d5c51ea979aff39d93 100644 (file)
@@ -111,6 +111,14 @@ guint rspamd_session_watch_stop (struct rspamd_async_session *s);
  */
 void rspamd_session_watcher_push (struct rspamd_async_session *s);
 
+/**
+ * Push callback to the watcher specified
+ */
+void rspamd_session_watcher_push_callback (struct rspamd_async_session *s,
+               struct rspamd_async_watcher *w,
+               event_watcher_t cb,
+               gpointer ud);
+
 /**
  * Increase refcount for a specific watcher
  */