From: Krzysztof Opasiak Date: Mon, 15 May 2017 18:56:02 +0000 (+0200) Subject: Add action execution framework X-Git-Tag: submit/tizen/20170622.101818~43 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f3ee1d1b75c23fd1f9f9c6d84ac4e965de6ed1ca;p=platform%2Fcore%2Fsystem%2Ffaultd.git Add action execution framework This framework is implemented as event handler which handles all decision made events. Currently it just iterates through the list of registered builtin action looking for a suitable action to execute. If action has not been found it just simply fails with error log and drops the event. Change-Id: Ib7f36b4b5ce523a78f72ad388611ebfdaba6a2ee Signed-off-by: Krzysztof Opasiak --- diff --git a/Makefile.am b/Makefile.am index 5cf9734..c0ebf0b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,6 +34,7 @@ SED_PROCESS = \ sbin_PROGRAMS = faultd faultd_SOURCES = \ + src/action/action_executor.c \ src/core/event.c \ src/core/event_processor.c \ src/core/service.c \ diff --git a/src/action/action_executor.c b/src/action/action_executor.c new file mode 100644 index 0000000..a2ca1bc --- /dev/null +++ b/src/action/action_executor.c @@ -0,0 +1,144 @@ +/* + * faultd + * + * Copyright © 2017 Samsung Electronics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "action_executor.h" +#include "decision_made_event.h" +#include "log.h" + +struct action_executor { + struct faultd_event_handler handler; + struct list_head builtin_actions; + sd_event *loop; +}; + +static int ae_event_match(struct faultd_event_handler *handler, + struct faultd_event *ev) +{ + /* We are interested only in decision made events */ + return faultd_event_is_of_type(ev, DECISION_MADE_EVENT_ID); +} + +static int ae_execute_action(struct faultd_event_handler *handler) +{ + struct faultd_event *ev = nqueue_pop(&handler->event_queue, + struct faultd_event, + nq_node); + struct decision_made_event *dm_ev = to_decision_made_event(ev); + struct action_executor *ae = container_of(handler, struct action_executor, + handler); + struct faultd_action *action; + + list_for_each_entry(action, &ae->builtin_actions, node) + if (strcmp(action->action_id , dm_ev->action) == 0) { + nqueue_append(&action->execution_queue, &ev->nq_node); + dm_ev = NULL; + break; + } + + /* TODO: Here is a good place to insert plugin search */ + + if (dm_ev) { + log_error("No implementation of %s action.", dm_ev->action); + faultd_event_unref(ev); + } + + return 0; +} + +static struct action_executor action_executor = { + .handler = { + .name = "action_executor_event_handler", + .event_match = ae_event_match, + .handle_event = ae_execute_action, + + .node = LIST_HEAD_INIT(action_executor.handler.node), + }, + .builtin_actions = LIST_HEAD_INIT(action_executor.builtin_actions), +}; + +FAULTD_EVENT_HANDLER_REGISTER(action_executor.handler, + action_executor_eh, + FAULTD_MODULE_TYPE_ACTION_EXECUTOR) + +static int action_executor_callback(sd_event_source *s, int fd, + uint32_t revents, void *userdata) +{ + struct faultd_action *act = userdata; + + return act->execute(act); +} + +int action_executor_action_register(struct faultd_action *act) +{ + int ret; + + if (!act->action_id || !act->execute) + return -EINVAL; + + ret = init_notify_queue_head(&act->execution_queue); + if (ret) + return ret; + + ret = sd_event_add_io(sd_event_source_get_event( + action_executor.handler.event_queue_sd_source), + &act->execution_queue_sd_source, + act->execution_queue.fd, EPOLLIN, + action_executor_callback, act); + if (ret < 0) { + log_error("Unable to add event io %d", ret); + goto cleanup_queue; + } + + list_add_tail(&act->node, &action_executor.builtin_actions); + return 0; + +cleanup_queue: + cleanup_notify_queue_head(&act->execution_queue); + + return ret; +} + +void action_executor_action_unregister(struct faultd_action *act) +{ + int ret; + + /* We log errors but go forward to cleanup everything we can */ + ret = sd_event_source_set_enabled(act->execution_queue_sd_source, + SD_EVENT_OFF); + if (ret < 0) + log_error("Could not disable queue event source %d", ret); + + sd_event_source_unref(act->execution_queue_sd_source); + + /* TODO: What to do with all pending executions? */ + while (!nqueue_empty(&act->execution_queue)) { + struct faultd_event *ev = nqueue_pop(&act->execution_queue, + struct faultd_event, + nq_node); + char *str = faultd_event_to_string(ev); + + log_error("Unhandled event: %s", str); + free(str); + faultd_event_unref(ev); + } + + list_del(&act->node); + +} diff --git a/src/action/action_executor.h b/src/action/action_executor.h new file mode 100644 index 0000000..921880f --- /dev/null +++ b/src/action/action_executor.h @@ -0,0 +1,66 @@ +/* + * faultd + * + * Copyright © 2017 Samsung Electronics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FAULTD_ACTION_EXECUTOR_H +#define FAULTD_ACTION_EXECUTOR_H + +#include "event_processor.h" + +struct faultd_action { + char *action_id; + char *impl_name; + + struct nqueue_head execution_queue; + struct sd_event_source *execution_queue_sd_source; + + /* execute first action from a queue */ + int (*execute)(struct faultd_action *act); + + /* has to be initialized */ + struct list_head node; +}; + +int action_executor_action_register(struct faultd_action *act); +void action_executor_action_unregister(struct faultd_action *act); + +#define FAULTD_ACTION_REGISTER(ACT, NAME) \ +static int action_ ##NAME## _init(struct faultd_module *module, \ + sd_event *event_loop) \ +{ \ + return action_executor_action_register(&ACT); \ +} \ + \ +static void action_ ##NAME## _cleanup(struct faultd_module *module) \ +{ \ + action_executor_action_unregister(&ACT); \ +} \ + \ +static struct faultd_module action_ ##NAME## _module = { \ + .name = "action_" #NAME "_module", \ + .type = FAULTD_MODULE_TYPE_ACTION, \ + .init = action_ ##NAME## _init, \ + .cleanup = action_ ##NAME## _cleanup, \ + .node = LIST_HEAD_INIT(action_ ##NAME## _module.node), \ +}; \ + \ +FAULTD_MODULE_REGISTER(&action_ ##NAME## _module) + +#define FAULTD_ACTION_REGISTER_SIMPLE(ACT) \ + FAULTD_ACTION_REGISTER(ACT, ACT) + +#endif /* FAULTD_ACTION_EXECUTOR_H */