service: add support for triggers on service/instance data changes
authorFelix Fietkau <nbd@nbd.name>
Tue, 17 Dec 2024 18:49:19 +0000 (19:49 +0100)
committerFelix Fietkau <nbd@nbd.name>
Tue, 17 Dec 2024 18:49:21 +0000 (19:49 +0100)
To keep things simple, they report changes to all present data types if
any of the data fields changed. This can be refined if more fine grained
checks are needed.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
service/instance.c
service/service.c
service/service.h

index ed5d0a490532e915fdc83976f190fd6078432320..1c363fcb364142ed7a995951c6d954c76c9323c2 100644 (file)
@@ -1580,6 +1580,10 @@ instance_update(struct service_instance *in, struct service_instance *in_new)
        } else {
                if (changed)
                        instance_restart(in);
+               else if (!blobmsg_list_equal(&in->data, &in_new->data)) {
+                       service_data_trigger(&in->data);
+                       service_data_trigger(&in_new->data);
+               }
                instance_config_move(in, in_new);
                /* restart happens in the child callback handler */
        }
@@ -1588,6 +1592,7 @@ instance_update(struct service_instance *in, struct service_instance *in_new)
 void
 instance_free(struct service_instance *in)
 {
+       service_data_trigger(&in->data);
        instance_free_stdio(in);
        uloop_process_delete(&in->proc);
        uloop_timeout_cancel(&in->timeout);
@@ -1654,6 +1659,7 @@ instance_init(struct service_instance *in, struct service *s, struct blob_attr *
        in->watchdog.timeout.cb = instance_watchdog;
 
        in->valid = instance_config_parse(in);
+       service_data_trigger(&in->data);
 }
 
 void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose)
index bd0e2903a439a8a8748ddc2507b213e3c8260b8a..f64b634a6a83841a58b153b59acc9c826ec74e6c 100644 (file)
@@ -53,6 +53,17 @@ service_instance_add(struct service *s, struct blob_attr *attr)
        vlist_add(&s->instances, &in->node, (void *) in->name);
 }
 
+void service_data_trigger(struct blobmsg_list *list)
+{
+       struct blobmsg_list_node *node;
+
+       avl_for_each_element(&list->avl, node, avl) {
+               blob_buf_init(&b, 0);
+               blobmsg_add_string(&b, "name", blobmsg_name(node->data));
+               trigger_event("service.data.update", b.head);
+       }
+}
+
 static void
 service_instance_update(struct vlist_tree *tree, struct vlist_node *node_new,
                        struct vlist_node *node_old)
@@ -120,6 +131,26 @@ static const struct blobmsg_policy service_set_attrs[__SERVICE_SET_MAX] = {
        [SERVICE_SET_DATA] = { "data", BLOBMSG_TYPE_TABLE },
 };
 
+static int
+service_update_data(struct service *s, struct blob_attr *data)
+{
+       if (blob_attr_equal(s->data, data))
+               return 0;
+
+       free(s->data);
+       s->data = blob_memdup(data);
+       if (!s->data)
+               return -1;
+
+       service_data_trigger(&s->data_blob);
+       blobmsg_list_free(&s->data_blob);
+       blobmsg_list_fill(&s->data_blob, blobmsg_data(s->data),
+                       blobmsg_data_len(s->data), false);
+       service_data_trigger(&s->data_blob);
+
+       return 0;
+}
+
 static int
 service_update(struct service *s, struct blob_attr **tb, bool add)
 {
@@ -133,8 +164,6 @@ service_update(struct service *s, struct blob_attr **tb, bool add)
        }
 
        if (s->data) {
-               blobmsg_list_free(&s->data_blob);
-               free(s->data);
                s->data = NULL;
        }
 
@@ -167,13 +196,9 @@ service_update(struct service *s, struct blob_attr **tb, bool add)
                        vlist_flush(&s->instances);
        }
 
-       if (tb[SERVICE_SET_DATA] && blobmsg_data_len(tb[SERVICE_SET_DATA])) {
-               s->data = blob_memdup(tb[SERVICE_SET_DATA]);
-               if (!s->data)
-                       return -1;
-               blobmsg_list_fill(&s->data_blob, blobmsg_data(s->data),
-                               blobmsg_data_len(s->data), false);
-       }
+       if (tb[SERVICE_SET_DATA] &&
+           service_update_data(s, tb[SERVICE_SET_DATA]) < 0)
+               return -1;
 
        s->deleted = false;
 
index 6ddc04ee3aa60e19957e68e6d493705f64caccd5..4858e91fe5f0eba9d2db3e224d3596a829525499 100644 (file)
@@ -60,6 +60,7 @@ int service_start_early(char *name, char *cmdline, char *user, char *group);
 void service_stopped(struct service *s);
 void service_validate_del(struct service *s);
 void service_event(const char *type, const char *service, const char *instance);
+void service_data_trigger(struct blobmsg_list *list);
 void service_stop_all(void);