diff options
-rw-r--r-- | service.c | 114 | ||||
-rw-r--r-- | service.h | 2 |
2 files changed, 96 insertions, 20 deletions
@@ -6,33 +6,83 @@ struct avl_tree services; static struct blob_buf b; static void -service_instance_update(struct vlist_tree *tree, struct vlist_node *node_new, - struct vlist_node *node_old) +start_instance(struct service_instance *in) { - struct service_instance *in_o = NULL, *in_n = NULL; + in->restart = false; +} - if (node_old) - in_o = container_of(node_old, struct service_instance, node); +static void +instance_timeout(struct uloop_timeout *t) +{ + struct service_instance *in; - if (node_new) - in_n = container_of(node_new, struct service_instance, node); + in = container_of(t, struct service_instance, timeout); + kill(in->proc.pid, SIGKILL); + uloop_process_delete(&in->proc); + in->proc.cb(&in->proc, -1); +} - do { - if (!in_o || !in_n) - break; +static void +instance_exit(struct uloop_process *p, int ret) +{ + struct service_instance *in; + + in = container_of(p, struct service_instance, proc); + uloop_timeout_cancel(&in->timeout); + if (in->restart) + start_instance(in); +} - /* full match, nothing to do */ +static void +stop_instance(struct service_instance *in, bool restart) +{ + if (!in->proc.pending) return; - } while (0); - if (in_o) { - /* kill old process */ - free(in_o); - } + kill(in->proc.pid, SIGTERM); +} - if (in_n) { - /* start new process */ - } +static bool +instance_config_changed(struct service_instance *in, struct service_instance *in_new) +{ + int len = blob_pad_len(in->config); + + if (len != blob_pad_len(in_new->config)) + return true; + + if (memcmp(in->config, in_new->config, blob_pad_len(in->config)) != 0) + return true; + + return false; +} + +static bool +update_instance(struct service_instance *in, struct service_instance *in_new) +{ + bool changed = instance_config_changed(in, in_new); + + in->config = in_new->config; + if (!changed) + return false; + + stop_instance(in, true); + return true; +} + +static void +free_instance(struct service_instance *in) +{ + uloop_process_delete(&in->proc); + uloop_timeout_cancel(&in->timeout); + free(in); +} + +static void +init_instance(struct service_instance *in, struct blob_attr *config) +{ + in->config = config; + in->timeout.cb = instance_timeout; + in->proc.cb = instance_exit; } static void @@ -48,10 +98,33 @@ service_instance_add(struct service *s, struct blob_attr *attr) if (!in) return; - in->config = attr; + init_instance(in, attr); vlist_add(&s->instances, &in->node, (void *) name); } +static void +service_instance_update(struct vlist_tree *tree, struct vlist_node *node_new, + struct vlist_node *node_old) +{ + struct service_instance *in_o = NULL, *in_n = NULL; + + if (node_old) + in_o = container_of(node_old, struct service_instance, node); + + if (node_new) + in_n = container_of(node_new, struct service_instance, node); + + if (in_o && in_n) { + update_instance(in_o, in_n); + free_instance(in_n); + } else if (in_o) { + stop_instance(in_o, false); + free_instance(in_o); + } else if (in_n) { + start_instance(in_n); + } +} + static struct service * service_alloc(const char *name) { @@ -59,6 +132,7 @@ service_alloc(const char *name) s = calloc(1, sizeof(*s)); vlist_init(&s->instances, avl_strcmp, service_instance_update); + s->instances.keep_old = true; return s; } @@ -15,7 +15,9 @@ struct service_instance { struct vlist_node node; const char *name; + bool restart; struct blob_attr *config; struct uloop_process proc; + struct uloop_timeout timeout; }; |