From 2e206dbe77ecdbc715a5aa22f19397162a912e7e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 Dec 2024 19:49:19 +0100 Subject: [PATCH] service: add support for triggers on service/instance data changes 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 --- service/instance.c | 6 ++++++ service/service.c | 43 ++++++++++++++++++++++++++++++++++--------- service/service.h | 1 + 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/service/instance.c b/service/instance.c index ed5d0a4..1c363fc 100644 --- a/service/instance.c +++ b/service/instance.c @@ -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) diff --git a/service/service.c b/service/service.c index bd0e290..f64b634 100644 --- a/service/service.c +++ b/service/service.c @@ -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; diff --git a/service/service.h b/service/service.h index 6ddc04e..4858e91 100644 --- a/service/service.h +++ b/service/service.h @@ -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); -- 2.30.2