summaryrefslogtreecommitdiffstats
path: root/ctdb/event/event_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctdb/event/event_context.c')
-rw-r--r--ctdb/event/event_context.c472
1 files changed, 472 insertions, 0 deletions
diff --git a/ctdb/event/event_context.c b/ctdb/event/event_context.c
new file mode 100644
index 0000000..79bcd83
--- /dev/null
+++ b/ctdb/event/event_context.c
@@ -0,0 +1,472 @@
+/*
+ CTDB event daemon - daemon state
+
+ Copyright (C) Amitay Isaacs 2018
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/dir.h"
+
+#include <talloc.h>
+#include <tevent.h>
+
+#include "lib/util/debug.h"
+#include "lib/util/dlinklist.h"
+
+#include "common/logging.h"
+#include "common/run_event.h"
+#include "common/path.h"
+
+#include "event/event_private.h"
+
+struct event_event {
+ struct event_event *prev, *next;
+
+ const char *name;
+ struct run_event_script_list *script_list;
+};
+
+struct event_component {
+ struct event_component *prev, *next;
+
+ /* component state */
+ const char *name;
+ const char *path;
+ struct run_event_context *run_ctx;
+
+ /* events list */
+ struct event_event *event;
+};
+
+struct event_client {
+ struct event_client *prev, *next;
+
+ struct sock_client_context *client;
+};
+
+struct event_context {
+ struct tevent_context *ev;
+ struct event_config *config;
+ struct run_proc_context *run_proc_ctx;
+
+ const char *script_dir;
+ const char *debug_script;
+
+ /* component list */
+ struct event_component *component;
+
+ /* client list */
+ struct event_client *client;
+};
+
+/*
+ * event_event functions
+ */
+
+static struct event_event *eventd_event_find(struct event_component *comp,
+ const char *event_name)
+{
+ struct event_event *event;
+
+ if (event_name == NULL) {
+ return NULL;
+ }
+
+ for (event = comp->event; event != NULL; event = event->next) {
+ if (strcmp(event->name, event_name) == 0) {
+ return event;
+ }
+ }
+
+ return NULL;
+}
+
+static int eventd_event_add(struct event_component *comp,
+ const char *event_name,
+ struct event_event **result)
+{
+ struct event_event *event;
+
+ if (event_name == NULL) {
+ return EINVAL;
+ }
+
+ event = eventd_event_find(comp, event_name);
+ if (event != NULL) {
+ goto done;
+ }
+
+ event = talloc_zero(comp, struct event_event);
+ if (event == NULL) {
+ return ENOMEM;
+ }
+
+ event->name = talloc_strdup(event, event_name);
+ if (event->name == NULL) {
+ talloc_free(event);
+ return ENOMEM;
+ }
+
+ DLIST_ADD_END(comp->event, event);
+
+done:
+ if (result != NULL) {
+ *result = event;
+ }
+ return 0;
+}
+
+static int eventd_event_set(struct event_component *comp,
+ const char *event_name,
+ struct run_event_script_list *script_list)
+{
+ struct event_event *event = NULL;
+ int ret;
+
+ ret = eventd_event_add(comp, event_name, &event);
+ if (ret != 0) {
+ return ret;
+ }
+
+ TALLOC_FREE(event->script_list);
+ if (script_list != NULL) {
+ event->script_list = talloc_steal(event, script_list);
+ }
+
+ return 0;
+}
+
+static int eventd_event_get(struct event_component *comp,
+ const char *event_name,
+ struct run_event_script_list **result)
+{
+ struct event_event *event;
+
+ event = eventd_event_find(comp, event_name);
+ if (event == NULL) {
+ return EINVAL;
+ }
+
+ *result = event->script_list;
+ return 0;
+}
+
+/*
+ * event_component functions
+ */
+
+static struct event_component *eventd_component_find(
+ struct event_context *eventd,
+ const char *comp_name)
+{
+ struct event_component *comp;
+
+ if (comp_name == NULL) {
+ return NULL;
+ }
+
+ for (comp = eventd->component; comp != NULL; comp = comp->next) {
+ if (strcmp(comp->name, comp_name) == 0) {
+ return comp;
+ }
+ }
+
+ return NULL;
+}
+
+static int eventd_component_add(struct event_context *eventd,
+ const char *comp_name,
+ struct event_component **result)
+{
+ struct event_component *comp;
+ int ret;
+
+ if (comp_name == NULL) {
+ return EINVAL;
+ }
+
+ comp = eventd_component_find(eventd, comp_name);
+ if (comp != NULL) {
+ goto done;
+ }
+
+ comp = talloc_zero(eventd, struct event_component);
+ if (comp == NULL) {
+ return ENOMEM;
+ }
+
+ comp->name = talloc_strdup(comp, comp_name);
+ if (comp->name == NULL) {
+ talloc_free(comp);
+ return ENOMEM;
+ }
+
+ comp->path = talloc_asprintf(comp,
+ "%s/%s",
+ eventd->script_dir,
+ comp_name);
+ if (comp->path == NULL) {
+ talloc_free(comp);
+ return ENOMEM;
+ }
+
+ ret = run_event_init(eventd,
+ eventd->run_proc_ctx,
+ comp->path,
+ eventd->debug_script,
+ &comp->run_ctx);
+ if (ret != 0) {
+ talloc_free(comp);
+ return ret;
+ }
+
+ DLIST_ADD_END(eventd->component, comp);
+
+done:
+ if (result != NULL) {
+ *result = comp;
+ }
+ return 0;
+}
+
+/*
+ * event_client functions
+ */
+
+static struct event_client *eventd_client_find(
+ struct event_context *eventd,
+ struct sock_client_context *client)
+{
+ struct event_client *e;
+
+ for (e = eventd->client; e != NULL; e = e->next) {
+ if (e->client == client) {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+int eventd_client_add(struct event_context *eventd,
+ struct sock_client_context *client)
+{
+ struct event_client *e;
+
+ e = talloc_zero(eventd, struct event_client);
+ if (e == NULL) {
+ return ENOMEM;
+ }
+
+ e->client = client;
+
+ DLIST_ADD_END(eventd->client, e);
+
+ return 0;
+}
+
+void eventd_client_del(struct event_context *eventd,
+ struct sock_client_context *client)
+{
+ struct event_client *e;
+
+ e = eventd_client_find(eventd, client);
+ if (e == NULL) {
+ return;
+ }
+
+ DLIST_REMOVE(eventd->client, e);
+
+ talloc_free(e);
+}
+
+bool eventd_client_exists(struct event_context *eventd,
+ struct sock_client_context *client)
+{
+ struct event_client *e;
+
+ e = eventd_client_find(eventd, client);
+ if (e == NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+/* public functions */
+
+int event_context_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct event_config *config,
+ struct event_context **result)
+{
+ struct event_context *eventd;
+ const char *debug_script;
+ int ret;
+
+ eventd = talloc_zero(mem_ctx, struct event_context);
+ if (eventd == NULL) {
+ return ENOMEM;
+ }
+
+ eventd->ev = ev;
+ eventd->config = config;
+
+ ret = run_proc_init(eventd, ev, &eventd->run_proc_ctx);
+ if (ret != 0) {
+ talloc_free(eventd);
+ return ret;
+ }
+
+ eventd->script_dir = path_etcdir_append(eventd, "events");
+ if (eventd->script_dir == NULL) {
+ talloc_free(eventd);
+ return ENOMEM;
+ }
+
+ /* FIXME
+ status = directory_exist(eventd->script_dir);
+ if (! status) {
+ talloc_free(eventd);
+ return EINVAL;
+ }
+ */
+
+ debug_script = event_config_debug_script(config);
+ if (debug_script != NULL) {
+ eventd->debug_script = path_etcdir_append(eventd,
+ debug_script);
+ if (eventd->debug_script == NULL) {
+ D_WARNING("Failed to set debug script to %s\n",
+ debug_script);
+ }
+ }
+
+ *result = eventd;
+ return 0;
+}
+
+struct event_config *eventd_config(struct event_context *eventd)
+{
+ return eventd->config;
+}
+
+int eventd_run_ctx(struct event_context *eventd,
+ const char *comp_name,
+ struct run_event_context **result)
+{
+ struct event_component *comp;
+ int ret;
+
+ ret = eventd_component_add(eventd, comp_name, &comp);
+ if (ret != 0) {
+ return ret;
+ }
+
+ *result = comp->run_ctx;
+ return 0;
+}
+
+int eventd_set_event_result(struct event_context *eventd,
+ const char *comp_name,
+ const char *event_name,
+ struct run_event_script_list *script_list)
+{
+ struct event_component *comp;
+
+ comp = eventd_component_find(eventd, comp_name);
+ if (comp == NULL) {
+ return ENOENT;
+ }
+
+ return eventd_event_set(comp, event_name, script_list);
+}
+
+int eventd_get_event_result(struct event_context *eventd,
+ const char *comp_name,
+ const char *event_name,
+ struct run_event_script_list **result)
+{
+ struct event_component *comp;
+ int ret;
+
+ ret = eventd_component_add(eventd, comp_name, &comp);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return eventd_event_get(comp, event_name, result);
+}
+
+struct ctdb_event_script_list *eventd_script_list(
+ TALLOC_CTX *mem_ctx,
+ struct run_event_script_list *script_list)
+{
+ struct ctdb_event_script_list *value;
+ int num_scripts = 0;
+ int i;
+
+ value = talloc_zero(mem_ctx, struct ctdb_event_script_list);
+ if (value == NULL) {
+ return NULL;
+ }
+
+ if (script_list != NULL) {
+ num_scripts = script_list->num_scripts;
+ }
+
+ if (num_scripts <= 0) {
+ return value;
+ }
+
+ value->script = talloc_array(value,
+ struct ctdb_event_script,
+ num_scripts);
+ if (value->script == NULL) {
+ goto fail;
+ }
+
+ for (i=0; i<num_scripts; i++) {
+ struct run_event_script *rscript = &script_list->script[i];
+ struct ctdb_event_script *escript = &value->script[i];
+
+ escript->name = talloc_strdup(value, rscript->name);
+ if (escript->name == NULL) {
+ goto fail;
+ }
+
+ escript->begin = rscript->begin;
+ escript->end = rscript->end;
+ escript->result = rscript->summary;
+
+ if (rscript->output == NULL) {
+ escript->output = NULL;
+ continue;
+ }
+
+ escript->output = talloc_strdup(value, rscript->output);
+ if (escript->output == NULL) {
+ goto fail;
+ }
+ }
+ value->num_scripts = num_scripts;
+
+ return value;
+
+fail:
+ talloc_free(value);
+ return NULL;
+}