Eventscripts: remove the horrible horrible circular reference between state and callb...
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Wed, 22 Feb 2012 06:38:12 +0000 (17:38 +1100)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Sun, 26 Feb 2012 22:13:10 +0000 (09:13 +1100)
Instead, tie them together via referencing a permanent linked list hung off the ctdb structure.

include/ctdb_private.h
server/eventscript.c

index 675ea49c241f1d6495b28f10f5394fe1d79d32a6..e3a9a1577ada71504f7893bf23b3daa21371520a 100644 (file)
@@ -495,6 +495,9 @@ struct ctdb_context {
 
        /* Used to defer db attach requests while in recovery mode */
        struct ctdb_deferred_attach_context *deferred_attach;
+
+       /* list of event script callback functions that are active */
+       struct event_script_callback *script_callbacks;
 };
 
 struct ctdb_db_context {
index 17cc3d421c8a4a111b53170a7f6ff6553f4ff770..c42aaa4480f4fa0f3f6abe64890b3b8bece1d8ce 100644 (file)
@@ -26,6 +26,7 @@
 #include "../include/ctdb_private.h"
 #include "lib/tevent/tevent.h"
 #include "../common/rb_tree.h"
+#include "lib/util/dlinklist.h"
 
 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *p);
 
@@ -41,7 +42,8 @@ static void sigterm(int sig)
 
 /* This is attached to the event script state. */
 struct event_script_callback {
-       struct ctdb_event_script_state *state;
+       struct event_script_callback *next, *prev;
+       struct ctdb_context *ctdb;
 
        /* Warning: this can free us! */
        void (*fn)(struct ctdb_context *, int, void *);
@@ -611,8 +613,18 @@ static int event_script_destructor(struct ctdb_event_script_state *state)
        }
 
        /* This is allowed to free us; talloc will prevent double free anyway,
-        * but beware if you call this outside the destructor! */
-       callback = state->callback;
+        * but beware if you call this outside the destructor!
+        * the callback hangs off a different context so we walk the list
+        * of "active" callbacks until we find the one state points to.
+        * if we cant find it it means the callback has been removed.
+        */
+       for (callback = state->ctdb->script_callbacks; callback != NULL; callback = callback->next) {
+               if (callback == state->callback) {
+                       break;
+               }
+       }
+       
+       state->callback = NULL;
 
        if (callback) {
                /* Make sure destructor doesn't free itself! */
@@ -669,8 +681,7 @@ static bool check_options(enum ctdb_eventscript_call call, const char *options)
 
 static int remove_callback(struct event_script_callback *callback)
 {
-       /* Detach ourselves from the running script state */
-       callback->state->callback = NULL;
+       DLIST_REMOVE(callback->ctdb->script_callbacks, callback);
        return 0;
 }
 
@@ -694,9 +705,10 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
        /* The callback isn't done if the context is freed. */
        state->callback = talloc(mem_ctx, struct event_script_callback);
        CTDB_NO_MEMORY(ctdb, state->callback);
+       DLIST_ADD(ctdb->script_callbacks, state->callback);
        talloc_set_destructor(state->callback, remove_callback);
-       state->callback->state = state;
-       state->callback->fn = callback;
+       state->callback->ctdb         = ctdb;
+       state->callback->fn           = callback;
        state->callback->private_data = private_data;
 
        state->ctdb = ctdb;