Add action execution framework 53/129253/3
authorKrzysztof Opasiak <k.opasiak@samsung.com>
Mon, 15 May 2017 18:56:02 +0000 (20:56 +0200)
committerKrzysztof Opasiak <k.opasiak@samsung.com>
Wed, 17 May 2017 20:57:10 +0000 (22:57 +0200)
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 <k.opasiak@samsung.com>
Makefile.am
src/action/action_executor.c [new file with mode: 0644]
src/action/action_executor.h [new file with mode: 0644]

index 5cf973477c53eaff2415adcb7e9f64f7143f5128..c0ebf0bba86f8861bab4fdf691259966dda81002 100644 (file)
@@ -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 (file)
index 0000000..a2ca1bc
--- /dev/null
@@ -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 <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);
+
+}
diff --git a/src/action/action_executor.h b/src/action/action_executor.h
new file mode 100644 (file)
index 0000000..921880f
--- /dev/null
@@ -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 */