]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
ctdb-event: Replace "no data" event scripts with previous data
authorMartin Schwenke <mschwenke@ddn.com>
Mon, 29 Sep 2025 07:24:53 +0000 (17:24 +1000)
committerRalph Boehme <slow@samba.org>
Tue, 7 Oct 2025 11:09:41 +0000 (11:09 +0000)
If an event script list contains results with "no data" (summary ==
-ENODATA), then overwrite these with results from the previous run,
where possible.

To maintain current behaviour in "ctdb event status ...", stop
processing scripts if the begin timestamp in the list goes backwards.
This maintains backward compatibility, where only status for scripts
from the most recent run are shown.

Signed-off-by: Martin Schwenke <mschwenke@ddn.com>
Reviewed-by: Ralph Boehme <slow@samba.org>
Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Tue Oct  7 11:09:41 UTC 2025 on atb-devel-224

ctdb/event/event_context.c
ctdb/event/event_tool.c

index e26d9ae4d1c048d663b1cb4a59c37026f6aa8593..afde9b0542e23011feb528dc592f8d90dea27e96 100644 (file)
@@ -134,6 +134,9 @@ static int eventd_event_set(struct event_component *comp,
                            struct run_event_script_list *script_list)
 {
        struct event_event *event = NULL;
+       struct run_event_script_list *old_list = NULL;
+       unsigned int n = 0;
+       unsigned int o = 0;
        int ret;
 
        ret = eventd_event_add(comp, event_name, &event);
@@ -146,9 +149,62 @@ static int eventd_event_set(struct event_component *comp,
                return 0;
        }
 
-       TALLOC_FREE(event->script_list);
+       old_list = event->script_list;
        event->script_list = talloc_steal(event, script_list);
 
+       /* No previous run, so the loop below can't be run */
+       if (old_list == NULL) {
+               goto done;
+       }
+
+       /* The loop below is a no-op if no script failed, so optimise */
+       if (script_list->summary == 0) {
+               goto done;
+       }
+
+       /*
+        * Replace any "no data" items in the new list with the data
+        * from the old list
+        */
+       while (n < script_list->num_scripts && o < old_list->num_scripts) {
+               struct run_event_script *new = &script_list->script[n];
+               struct run_event_script *old = &old_list->script[o];
+
+               /*
+                * If these are the same event, copy data if "no
+                * data". Otherwise step through the lists.
+                */
+               ret = strcmp(new->name, old->name);
+               if (ret < 0) {
+                       n++;
+                       continue;
+               }
+               if (ret > 0) {
+                       o++;
+                       continue;
+               }
+
+               if (new->summary == -ENODATA) {
+                       /*
+                        * Do not do a struct assignment here.  This
+                        * would cause name and output to point to
+                        * memory allocated off old_list, and that is
+                        * freed below.
+                        */
+                       new->begin = old->begin;
+                       new->end = old->end;
+                       new->result = old->result;
+                       new->summary = old->summary;
+                       new->output = talloc_move(event->script_list,
+                                                 &old->output);
+               }
+
+               n++;
+               o++;
+       }
+
+done:
+       TALLOC_FREE(old_list);
        return 0;
 }
 
index 1acf94f14926ee033ba4d729128a3aea179a37e6..baf4763cb1f9dac66213f593be49c46e507a6355 100644 (file)
@@ -262,6 +262,7 @@ static void print_status(const char *component,
                         int result,
                         struct ctdb_event_reply_status *status)
 {
+       struct timeval prev = { .tv_sec = 0, };
        int i;
 
        if (result != 0) {
@@ -282,11 +283,27 @@ static void print_status(const char *component,
 
        for (i=0; i<status->script_list->num_scripts; i++) {
                struct ctdb_event_script *s = &status->script_list->script[i];
+               int ret = 0;
 
+               /*
+                * Occurs when a new script is enabled, it hasn't
+                * been previously run, and a previous script fails
+                */
                if (s->result == -ENODATA) {
                        continue;
                }
+
+               /*
+                * Occurs when data for s is from a previous run, so
+                * it was run before the previous script
+                */
+               ret = tevent_timeval_compare(&s->begin, &prev);
+               if (ret == -1) {
+                       break;
+               }
+
                print_status_one(s);
+               prev = s->begin;
        }
 }