/*
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 .
*/
#include "replace.h"
#include "system/dir.h"
#include
#include
#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; iscript[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;
}