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>
#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? */
};
/* Strings are deep copied */
char *who_made;
char *action;
+ on_action_finished_cb on_finished;
struct epc_object *action_data;
};
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) {
}
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
ret = 0;
goto cleanup;
}
+
+ if (dm_ev->on_finished)
+ dm_ev->on_finished(dm_ev, exe_info->result);
}
ret = action_ret;
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);
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);
struct dm_event_data ev_data = {
.reason = ev,
.who_made = MODULE_NAME,
+ .on_finished = unit_control_executed,
};
struct epc_event *new_ev;
int ret;
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;