action_executor: Add callback for action finish 78/206578/5
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Mon, 20 May 2019 10:36:29 +0000 (12:36 +0200)
committerMaciej Slodczyk <m.slodczyk2@partner.samsung.com>
Thu, 6 Jun 2019 15:58:55 +0000 (17:58 +0200)
Some decision makers could need to be aware of the action result.
Instead of requiring database, they can now register an optional
callback to be called on action execution.

Note, that asynchronous actions need to call this explicitly at the
completion (unit_start being an example)

Change-Id: I9321d5ec02dc271c26971c1d5b3474a20e8a1dad
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
include/decision_made_event.h
src/action/action_executor.c
src/action/unit_start.c
src/decision_makers/unit_control_dm.c
src/event_types/decision_made_event.c

index 40907ca8a6030b27895123bc58775410beb939eb..c296b19d204fedf9b926630935ae9433c49f904c 100644 (file)
 #define DM_EV_ACTION_DATA "actd"
 #define DM_EV_REASON "rsn"
 
+typedef void (*on_action_finished_cb)(struct action_executed_event *ev, int result);
+
 struct decision_made_event {
        struct epc_event event;
        struct epc_event *reason;
        char *who_made;
        char *action;
+       on_action_finished_cb on_finished;
        struct epc_object *action_data;
        /* TODO: what more do we need? */
 };
@@ -46,6 +49,7 @@ struct dm_event_data {
        /* Strings are deep copied */
        char *who_made;
        char *action;
+       on_action_finished_cb on_finished;
 
        struct epc_object *action_data;
 };
index 6983ccdaf55fc43c251836a0d74c521814056e6d..a1695037c5be39a2df92b55d9200fca58d52a7cd 100644 (file)
@@ -97,6 +97,7 @@ static int action_executor_callback(sd_event_source *s, int fd,
        struct action_executed_event *exe_info;
        int action_ret;
        int ret;
+       struct decision_made_event *dm_ev;
 
        ret = epc_object_new(&ae_data.action_log);
        if (ret < 0) {
@@ -113,6 +114,7 @@ static int action_executor_callback(sd_event_source *s, int fd,
        }
 
        exe_info = to_action_executed_event(ev);
+       dm_ev = to_decision_made_event(exe_info->reason);
 
        /*
         * If action is not fully executed after returning from this function
@@ -131,6 +133,9 @@ static int action_executor_callback(sd_event_source *s, int fd,
                        ret = 0;
                        goto cleanup;
                }
+
+               if (dm_ev->on_finished)
+                       dm_ev->on_finished(dm_ev, exe_info->result);
        }
 
        ret = action_ret;
index b01ed9d65dd68eb86ae9dd88fc972c8deddc440b..955faa8a7346cfa2cff3aba353777d16dbe13cbb 100644 (file)
@@ -32,11 +32,15 @@ struct unit_action_data {
 
 static int finish_action(struct unit_action_data *data, int result, const char *err_msg)
 {
+       struct decision_made_event *dm_ev = to_decision_made_event(data->exe_info->reason);
        int ret;
 
        if (err_msg)
                epc_object_append_string(data->exe_info->action_log, "error", err_msg);
 
+       if (dm_ev->on_finished)
+               dm_ev->on_finished(dm_ev, result);
+
        data->exe_info->result = result;
        ret = event_processor_report_event(&data->exe_info->event);
        epc_event_unref(&data->exe_info->event);
index 8dc802684599334d71f40084e4e8c8d2da507783..fcf6406607383d268b67d9be7f7fd05be3fdc5f9 100644 (file)
@@ -193,6 +193,29 @@ static int parse_unit_list(sd_bus_message *reply, struct list_head *units)
        return ret;
 }
 
+static void unit_control_executed(struct decision_made_event *dm_ev, int result)
+{
+       struct unit_control_event *event = to_unit_control_event(dm_ev->reason);
+       _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+       int ret;
+
+       if (result < 0)
+               event->err_code = result;
+
+       event->jobs_cnt--;
+       if (event->jobs_cnt == 0) {
+               if (event->err_code < 0) {
+                       sd_bus_error_set_errno(&error, event->err_code);
+                       ret = sd_bus_reply_method_error(event->m, &error);
+               } else {
+                       ret = sd_bus_reply_method_return(event->m, "s", "ok");
+               }
+               sd_bus_message_unref(event->m);
+       }
+
+       epc_event_unref(&event->event);
+}
+
 static int unit_control_execute(const char *unit, const char *command, struct epc_event *ev)
 {
        assert(unit);
@@ -202,6 +225,7 @@ static int unit_control_execute(const char *unit, const char *command, struct ep
        struct dm_event_data ev_data = {
                .reason = ev,
                .who_made = MODULE_NAME,
+               .on_finished = unit_control_executed,
        };
        struct epc_event *new_ev;
        int ret;
index 9ba47a908308c769ed32aee38451edc989d39183..4ab4165ba55ba9f943429023a3508b2b36dc20f5 100644 (file)
@@ -41,6 +41,7 @@ static int allocate_dm_event(struct epc_event_type *type,
 
        dm_ev->who_made = strdup(dm_ev_data->who_made);
        dm_ev->action = strdup(dm_ev_data->action);
+       dm_ev->on_finished = dm_ev_data->on_finished;
 
        if (!dm_ev->who_made || !dm_ev->action) {
                ret = -ENOMEM;