summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2024-12-17 18:49:19 +0000
committerFelix Fietkau2024-12-17 18:49:21 +0000
commit2e206dbe77ecdbc715a5aa22f19397162a912e7e (patch)
treee75786740f1dc49f927857014c7cd059e3a1da63
parente2f05deb93949f447d397e8cd3a341bc8e53cd38 (diff)
downloadprocd-2e206dbe77ecdbc715a5aa22f19397162a912e7e.tar.gz
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 <nbd@nbd.name>
-rw-r--r--service/instance.c6
-rw-r--r--service/service.c43
-rw-r--r--service/service.h1
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)
@@ -121,6 +132,26 @@ static const struct blobmsg_policy service_set_attrs[__SERVICE_SET_MAX] = {
};
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)
{
struct blob_attr *cur;
@@ -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);