eventscript: introduce enum for different event script calls.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 24 Nov 2009 00:46:49 +0000 (11:16 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 24 Nov 2009 00:46:49 +0000 (11:16 +1030)
Rather than doing strcmp everywhere, pass an explicit enum around.  This
also subtly documents what options are available.  The "options" arg
is now used for extra arguments only.

Unfortunately, gcc complains on empty format strings, so we make
ctdb_event_script() take no varargs, and add ctdb_event_script_args().  We
leave ctdb_event_script_callback() taking varargs, which means callers
have to do "%s", "".

For the moment, we have CTDB_EVENT_UNKNOWN for handling forced scripts
from the ctdb tool.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
include/ctdb_private.h
server/ctdb_control.c
server/ctdb_monitor.c
server/ctdb_recover.c
server/ctdb_recoverd.c
server/ctdb_takeover.c
server/eventscript.c

index e3ebb8acd83b59bb9d18359ed6148c0bc8796e65..0a0864e1c9e08a8935576c211c32badfbf3128e0 100644 (file)
@@ -858,6 +858,19 @@ enum ctdb_trans2_commit_error {
        CTDB_TRANS2_COMMIT_SOMEFAIL=3 /* some nodes failed the commit, some allowed it */
 };
 
+/* different calls to event scripts. */
+enum ctdb_eventscript_call {
+       CTDB_EVENT_STARTUP,             /* CTDB starting up: no args. */
+       CTDB_EVENT_START_RECOVERY,      /* CTDB recovery starting: no args. */
+       CTDB_EVENT_RECOVERED,           /* CTDB recovery finished: no args. */
+       CTDB_EVENT_TAKE_IP,             /* IP taken: interface, IP address, netmask bits. */
+       CTDB_EVENT_RELEASE_IP,          /* IP released: interface, IP address, netmask bits. */
+       CTDB_EVENT_STOPPED,             /* This node is stopped: no args. */
+       CTDB_EVENT_MONITOR,             /* Please check if service is healthy: no args. */
+       CTDB_EVENT_STATUS,              /* Report service status: no args. */
+       CTDB_EVENT_SHUTDOWN,            /* CTDB shutting down: no args. */
+       CTDB_EVENT_UNKNOWN,             /* Other: manually invoked from "ctdb eventscript". */
+};
 
 /* internal prototypes */
 void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
@@ -1326,12 +1339,15 @@ int32_t ctdb_control_get_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA ind
 int32_t ctdb_control_set_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata);
 
 void ctdb_takeover_client_destructor_hook(struct ctdb_client *client);
-int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+int ctdb_event_script(struct ctdb_context *ctdb, enum ctdb_eventscript_call call);
+int ctdb_event_script_args(struct ctdb_context *ctdb, enum ctdb_eventscript_call call,
+                          const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
 int ctdb_event_script_callback(struct ctdb_context *ctdb, 
                               TALLOC_CTX *mem_ctx,
                               void (*callback)(struct ctdb_context *, int, void *),
                               void *private_data,
-                              const char *fmt, ...) PRINTF_ATTRIBUTE(5,6);
+                              enum ctdb_eventscript_call call,
+                              const char *fmt, ...) PRINTF_ATTRIBUTE(6,7);
 void ctdb_release_all_ips(struct ctdb_context *ctdb);
 
 void set_nonblocking(int fd);
index bf82e515fbd081a623df555d4c47600bd69cd89c..970e0056e464bd87130f67eec63344ec6d5d5038 100644 (file)
@@ -286,7 +286,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
                if (ctdb->methods != NULL) {
                        ctdb->methods->shutdown(ctdb);
                }
-               ctdb_event_script(ctdb, "shutdown");
+               ctdb_event_script(ctdb, CTDB_EVENT_SHUTDOWN);
                DEBUG(DEBUG_NOTICE,("Received SHUTDOWN command. Stopping CTDB daemon.\n"));
                exit(0);
 
index 2c97f45ab29cd2d7d55aeb67bc71206c4bb67143..efb767a330b1444c6ac4260ea9e9eeb8fd27971a 100644 (file)
@@ -224,7 +224,7 @@ static void ctdb_check_health(struct event_context *ev, struct timed_event *te,
        if (!ctdb->done_startup) {
                ret = ctdb_event_script_callback(ctdb, 
                                                 ctdb->monitor->monitor_context, ctdb_startup_callback, 
-                                                ctdb, "startup");
+                                                ctdb, CTDB_EVENT_STARTUP, "%s", "");
        } else {
                int i;
                int skip_monitoring = 0;
@@ -248,7 +248,7 @@ static void ctdb_check_health(struct event_context *ev, struct timed_event *te,
                } else {
                        ret = ctdb_event_script_callback(ctdb, 
                                        ctdb->monitor->monitor_context, ctdb_health_callback,
-                                       ctdb, "monitor");
+                                       ctdb, CTDB_EVENT_MONITOR, "%s", "");
                }
        }
 
index 1cd4835c82441f89eb11f3d3347870a8af041bf8..76b0a9b528f7375c8eb40741b21b782b22914d62 100644 (file)
@@ -964,7 +964,7 @@ int32_t ctdb_control_end_recovery(struct ctdb_context *ctdb,
 
        ret = ctdb_event_script_callback(ctdb, state,
                                         ctdb_end_recovery_callback, 
-                                        state, "recovered");
+                                        state, CTDB_EVENT_RECOVERED, "%s", "");
 
        if (ret != 0) {
                ctdb_enable_monitoring(ctdb);
@@ -1016,7 +1016,8 @@ int32_t ctdb_control_start_recovery(struct ctdb_context *ctdb,
 
        ret = ctdb_event_script_callback(ctdb, state,
                                         ctdb_start_recovery_callback, 
-                                        state, "startrecovery");
+                                        state, CTDB_EVENT_START_RECOVERY,
+                                        "%s", "");
 
        if (ret != 0) {
                DEBUG(DEBUG_ERR,(__location__ " Failed to start recovery\n"));
@@ -1156,7 +1157,7 @@ static void ctdb_recd_ping_timeout(struct event_context *ev, struct timed_event
        if (ctdb->methods != NULL) {
                ctdb->methods->shutdown(ctdb);
        }
-       ctdb_event_script(ctdb, "shutdown");
+       ctdb_event_script(ctdb, CTDB_EVENT_SHUTDOWN);
        DEBUG(DEBUG_ERR, ("Recovery daemon ping timeout. Daemon has been shut down.\n"));
        exit(0);
 }
@@ -1228,7 +1229,7 @@ int32_t ctdb_control_stop_node(struct ctdb_context *ctdb, struct ctdb_req_contro
 
        ret = ctdb_event_script_callback(ctdb, state,
                                         ctdb_stop_node_callback, 
-                                        state, "stopped");
+                                        state, CTDB_EVENT_STOPPED, "%s", "");
 
        if (ret != 0) {
                ctdb_enable_monitoring(ctdb);
index ecdcd99dd189676c645e5978d3f03ddc2fa102f1..d304e24d944fbce717a9091c01edf19d8995295d 100644 (file)
@@ -3288,7 +3288,7 @@ static void ctdb_check_recd(struct event_context *ev, struct timed_event *te,
                if (ctdb->methods != NULL) {
                        ctdb->methods->shutdown(ctdb);
                }
-               ctdb_event_script(ctdb, "shutdown");
+               ctdb_event_script(ctdb, CTDB_EVENT_SHUTDOWN);
 
                exit(10);       
        }
index d53f2d47b0ea6bcf7396a0473d9a4b17abc6fd83..6bc4e37add1bf1f5c35c47bc4b8ad7245756b0dc 100644 (file)
@@ -236,7 +236,8 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
 
        ret = ctdb_event_script_callback(ctdb, 
                                         state, takeover_ip_callback, state,
-                                        "takeip %s %s %u",
+                                        CTDB_EVENT_TAKE_IP,
+                                        "%s %s %u",
                                         vnn->iface, 
                                         talloc_strdup(state, ctdb_addr_to_str(&pip->addr)),
                                         vnn->public_netmask_bits);
@@ -391,7 +392,8 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
 
        ret = ctdb_event_script_callback(ctdb, 
                                         state, release_ip_callback, state,
-                                        "releaseip %s %s %u",
+                                        CTDB_EVENT_RELEASE_IP,
+                                        "%s %s %u",
                                         vnn->iface, 
                                         talloc_strdup(state, ctdb_addr_to_str(&pip->addr)),
                                         vnn->public_netmask_bits);
@@ -1352,7 +1354,7 @@ void ctdb_release_all_ips(struct ctdb_context *ctdb)
                if (vnn->pnn == ctdb->pnn) {
                        vnn->pnn = -1;
                }
-               ctdb_event_script(ctdb, "releaseip %s %s %u",
+               ctdb_event_script_args(ctdb, CTDB_EVENT_RELEASE_IP, "%s %s %u",
                                  vnn->iface, 
                                  talloc_strdup(ctdb, ctdb_addr_to_str(&vnn->public_address)),
                                  vnn->public_netmask_bits);
@@ -2093,7 +2095,8 @@ int32_t ctdb_control_del_public_address(struct ctdb_context *ctdb, TDB_DATA inda
 
                        ret = ctdb_event_script_callback(ctdb, 
                                         mem_ctx, delete_ip_callback, mem_ctx,
-                                        "releaseip %s %s %u",
+                                        CTDB_EVENT_RELEASE_IP,
+                                        "%s %s %u",
                                         vnn->iface, 
                                         talloc_strdup(mem_ctx, ctdb_addr_to_str(&vnn->public_address)),
                                         vnn->public_netmask_bits);
index 801ff4ecc98db2e139d6097dbf291e78007ce5a2..58ec29ba585144de562515284d1d6b46c6ef4306 100644 (file)
@@ -32,6 +32,19 @@ static struct {
        const char *script_running;
 } child_state;
 
+static const char *call_names[] = {
+       "startup",
+       "startrecovery",
+       "recovered",
+       "takeip",
+       "releaseip",
+       "stopped",
+       "monitor",
+       "status",
+       "shutdown",
+       ""
+};
+
 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *p);
 
 /*
@@ -737,13 +750,14 @@ static int event_script_destructor(struct ctdb_event_script_state *state)
 static int ctdb_event_script_callback_v(struct ctdb_context *ctdb, 
                                        void (*callback)(struct ctdb_context *, int, void *),
                                        void *private_data,
+                                       enum ctdb_eventscript_call call,
                                        const char *fmt, va_list ap)
 {
        TALLOC_CTX *mem_ctx;
        struct ctdb_event_script_state *state;
        int ret;
 
-       if (!strcmp(fmt, "monitor") || !strcmp(fmt, "status")) {
+       if (call == CTDB_EVENT_MONITOR || call == CTDB_EVENT_STATUS) {
                /* if this was a "monitor" or a status event, we recycle the
                   context to start a new monitor event
                */
@@ -781,7 +795,9 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
        state->ctdb = ctdb;
        state->callback = callback;
        state->private_data = private_data;
-       state->options = talloc_vasprintf(state, fmt, ap);
+       state->options = talloc_asprintf(state, "%s ", call_names[call]);
+       if (state->options)
+               state->options = talloc_vasprintf_append(discard_const_p(char, state->options), fmt, ap);
        state->timeout = timeval_set(ctdb->tunable.script_timeout, 0);
        if (state->options == NULL) {
                DEBUG(DEBUG_ERR, (__location__ " could not allocate state->options\n"));
@@ -847,13 +863,14 @@ int ctdb_event_script_callback(struct ctdb_context *ctdb,
                               TALLOC_CTX *mem_ctx,
                               void (*callback)(struct ctdb_context *, int, void *),
                               void *private_data,
+                              enum ctdb_eventscript_call call,
                               const char *fmt, ...)
 {
        va_list ap;
        int ret;
 
        va_start(ap, fmt);
-       ret = ctdb_event_script_callback_v(ctdb, callback, private_data, fmt, ap);
+       ret = ctdb_event_script_callback_v(ctdb, callback, private_data, call, fmt, ap);
        va_end(ap);
 
        return ret;
@@ -879,20 +896,20 @@ static void event_script_callback(struct ctdb_context *ctdb, int status, void *p
   run the event script, waiting for it to complete. Used when the caller
   doesn't want to continue till the event script has finished.
  */
-int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
+int ctdb_event_script_args(struct ctdb_context *ctdb, enum ctdb_eventscript_call call,
+                          const char *fmt, ...)
 {
        va_list ap;
        int ret;
        struct callback_status status;
 
        va_start(ap, fmt);
-       ret = ctdb_event_script_callback_v(ctdb, 
-                       event_script_callback, &status, fmt, ap);
-       va_end(ap);
-
+       ret = ctdb_event_script_callback_v(ctdb,
+                       event_script_callback, &status, call, fmt, ap);
        if (ret != 0) {
                return ret;
        }
+       va_end(ap);
 
        status.status = -1;
        status.done = false;
@@ -902,6 +919,11 @@ int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
        return status.status;
 }
 
+int ctdb_event_script(struct ctdb_context *ctdb, enum ctdb_eventscript_call call)
+{
+       /* GCC complains about empty format string, so use %s and "". */
+       return ctdb_event_script_args(ctdb, call, "%s", "");
+}
 
 struct eventscript_callback_state {
        struct ctdb_req_control *c;
@@ -955,7 +977,7 @@ int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb,
 
        ret = ctdb_event_script_callback(ctdb,
                         state, run_eventscripts_callback, state,
-                        "%s", (const char *)indata.dptr);
+                        CTDB_EVENT_UNKNOWN, "%s", (const char *)indata.dptr);
 
        if (ret != 0) {
                ctdb_enable_monitoring(ctdb);