--- /dev/null
+/*
+ * 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 <errno.h>
+
+#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);
+
+}
--- /dev/null
+/*
+ * 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 */