#include <common/macros.h>
#include <common/optional.h>
#include <lttng/action/action-internal.h>
+#include <lttng/action/group-internal.h>
#include <lttng/action/group.h>
+#include <lttng/action/notify-internal.h>
#include <lttng/action/notify.h>
#include <lttng/action/rotate-session.h>
#include <lttng/action/snapshot-session.h>
#include <lttng/action/start-session.h>
#include <lttng/action/stop-session.h>
#include <lttng/condition/evaluation.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/lttng-error.h>
#include <lttng/trigger/trigger-internal.h>
#include <pthread.h>
*/
typedef int (*action_executor_handler)(struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *action);
+ struct lttng_action *action);
static int action_executor_notify_handler(struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *);
-static int action_executor_start_session_handler(struct action_executor *executor,
+ struct lttng_action *);
+static int action_executor_start_session_handler(
+ struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *);
-static int action_executor_stop_session_handler(struct action_executor *executor,
+ struct lttng_action *);
+static int action_executor_stop_session_handler(
+ struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *);
-static int action_executor_rotate_session_handler(struct action_executor *executor,
+ struct lttng_action *);
+static int action_executor_rotate_session_handler(
+ struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *);
-static int action_executor_snapshot_session_handler(struct action_executor *executor,
+ struct lttng_action *);
+static int action_executor_snapshot_session_handler(
+ struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *);
+ struct lttng_action *);
static int action_executor_group_handler(struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *);
+ struct lttng_action *);
static int action_executor_generic_handler(struct action_executor *executor,
const struct action_work_item *,
- const struct lttng_action *);
+ struct lttng_action *);
static const action_executor_handler action_executors[] = {
[LTTNG_ACTION_TYPE_NOTIFY] = action_executor_notify_handler,
[LTTNG_ACTION_TYPE_GROUP] = action_executor_group_handler,
};
-static const char *action_type_names[] = {
- [LTTNG_ACTION_TYPE_NOTIFY] = "Notify",
- [LTTNG_ACTION_TYPE_START_SESSION] = "Start session",
- [LTTNG_ACTION_TYPE_STOP_SESSION] = "Stop session",
- [LTTNG_ACTION_TYPE_ROTATE_SESSION] = "Rotate session",
- [LTTNG_ACTION_TYPE_SNAPSHOT_SESSION] = "Snapshot session",
- [LTTNG_ACTION_TYPE_GROUP] = "Group",
-};
-
static const char *get_action_name(const struct lttng_action *action)
{
const enum lttng_action_type action_type = lttng_action_get_type(action);
assert(action_type != LTTNG_ACTION_TYPE_UNKNOWN);
- return action_type_names[action_type];
+ return lttng_action_type_string(action_type);
}
/* Check if this trigger allowed to interect with a given session. */
static int action_executor_notify_handler(struct action_executor *executor,
const struct action_work_item *work_item,
- const struct lttng_action *action)
+ struct lttng_action *action)
{
return notification_client_list_send_evaluation(work_item->client_list,
- lttng_trigger_get_const_condition(work_item->trigger),
+ work_item->trigger,
work_item->evaluation,
- lttng_trigger_get_credentials(work_item->trigger),
- LTTNG_OPTIONAL_GET_PTR(work_item->object_creds),
+ work_item->object_creds.is_set ?
+ &(work_item->object_creds.value) :
+ NULL,
client_handle_transmission_status, executor);
}
-static int action_executor_start_session_handler(struct action_executor *executor,
+static int action_executor_start_session_handler(
+ struct action_executor *executor,
const struct action_work_item *work_item,
- const struct lttng_action *action)
+ struct lttng_action *action)
{
int ret = 0;
const char *session_name;
WARN("Failed to start session `%s` on behalf of trigger `%s`: %s",
session_name, get_trigger_name(work_item->trigger),
lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
break;
}
return ret;
}
-static int action_executor_stop_session_handler(struct action_executor *executor,
+static int action_executor_stop_session_handler(
+ struct action_executor *executor,
const struct action_work_item *work_item,
- const struct lttng_action *action)
+ struct lttng_action *action)
{
int ret = 0;
const char *session_name;
DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%s`",
session_name, get_action_name(action),
get_trigger_name(work_item->trigger));
+ lttng_action_increase_execution_failure_count(action);
goto error_unlock_list;
}
WARN("Failed to stop session `%s` on behalf of trigger `%s`: %s",
session_name, get_trigger_name(work_item->trigger),
lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
break;
}
return ret;
}
-static int action_executor_rotate_session_handler(struct action_executor *executor,
+static int action_executor_rotate_session_handler(
+ struct action_executor *executor,
const struct action_work_item *work_item,
- const struct lttng_action *action)
+ struct lttng_action *action)
{
int ret = 0;
const char *session_name;
DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%s`",
session_name, get_action_name(action),
get_trigger_name(work_item->trigger));
+ lttng_action_increase_execution_failure_count(action);
goto error_unlock_list;
}
case LTTNG_ERR_ROTATION_PENDING:
DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation is already ongoing",
session_name, get_trigger_name(work_item->trigger));
+ lttng_action_increase_execution_failure_count(action);
break;
case LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP:
case LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR:
WARN("Failed to start a rotation of session `%s` on behalf of trigger `%s`: %s",
session_name, get_trigger_name(work_item->trigger),
lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
break;
}
return ret;
}
-static int action_executor_snapshot_session_handler(struct action_executor *executor,
+static int action_executor_snapshot_session_handler(
+ struct action_executor *executor,
const struct action_work_item *work_item,
- const struct lttng_action *action)
+ struct lttng_action *action)
{
int ret = 0;
const char *session_name;
session_lock_list();
session = session_find_by_name(session_name);
if (!session) {
- DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%p`",
+ DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%s`",
session_name, get_action_name(action),
- work_item->trigger);
+ get_trigger_name(work_item->trigger));
+ lttng_action_increase_execution_failure_count(action);
goto error_unlock_list;
}
WARN("Failed to record snapshot of session `%s` on behalf of trigger `%s`: %s",
session_name, get_trigger_name(work_item->trigger),
lttng_strerror(-cmd_ret));
+ lttng_action_increase_execution_failure_count(action);
break;
}
static int action_executor_group_handler(struct action_executor *executor,
const struct action_work_item *work_item,
- const struct lttng_action *action_group)
+ struct lttng_action *action_group)
{
int ret = 0;
unsigned int i, count;
DBG("Action group has %u action%s", count, count != 1 ? "s" : "");
for (i = 0; i < count; i++) {
- const struct lttng_action *action =
- lttng_action_group_get_at_index(
+ struct lttng_action *action =
+ lttng_action_group_borrow_mutable_at_index(
action_group, i);
ret = action_executor_generic_handler(
static int action_executor_generic_handler(struct action_executor *executor,
const struct action_work_item *work_item,
- const struct lttng_action *action)
+ struct lttng_action *action)
{
+ int ret;
const enum lttng_action_type action_type = lttng_action_get_type(action);
assert(action_type != LTTNG_ACTION_TYPE_UNKNOWN);
- DBG("Executing action `%s` of trigger `%p` action work item %" PRIu64,
+ lttng_action_increase_execution_request_count(action);
+ if (!lttng_action_should_execute(action)) {
+ DBG("Policy prevented execution of action `%s` of trigger `%s` action work item %" PRIu64,
+ get_action_name(action),
+ get_trigger_name(work_item->trigger),
+ work_item->id);
+ ret = 0;
+ goto end;
+ }
+
+ lttng_action_increase_execution_count(action);
+ DBG("Executing action `%s` of trigger `%s` action work item %" PRIu64,
get_action_name(action),
get_trigger_name(work_item->trigger),
work_item->id);
-
- return action_executors[action_type](
- executor, work_item, action);
+ ret = action_executors[action_type](executor, work_item, action);
+end:
+ return ret;
}
static int action_work_item_execute(struct action_executor *executor,
struct action_work_item *work_item)
{
int ret;
- const struct lttng_action *action =
- lttng_trigger_get_const_action(work_item->trigger);
+ struct lttng_action *action =
+ lttng_trigger_get_action(work_item->trigger);
DBG("Starting execution of action work item %" PRIu64 " of trigger `%s`",
work_item->id, get_trigger_name(work_item->trigger));
assert(executor);
- health_register(health_sessiond, HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR);
+ health_register(the_health_sessiond,
+ HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR);
rcu_register_thread();
rcu_thread_online();
rcu_thread_offline();
rcu_unregister_thread();
- health_unregister(health_sessiond);
+ health_unregister(the_health_sessiond);
return NULL;
}
{
struct action_executor *executor = _data;
+ pthread_mutex_lock(&executor->work.lock);
executor->should_quit = true;
pthread_cond_signal(&executor->work.cond);
+ pthread_mutex_unlock(&executor->work.lock);
return true;
}
work_item = zmalloc(sizeof(*work_item));
if (!work_item) {
- PERROR("Failed to allocate action executor work item on behalf of trigger `%p`",
+ PERROR("Failed to allocate action executor work item on behalf of trigger `%s`",
get_trigger_name(trigger));
executor_status = ACTION_EXECUTOR_STATUS_ERROR;
goto error_unlock;
evaluation = NULL;
cds_list_add_tail(&work_item->list_node, &executor->work.list);
executor->work.pending_count++;
- DBG("Enqueued action for trigger `%p` as work item %" PRIu64,
+ DBG("Enqueued action for trigger `%s` as work item #%" PRIu64,
get_trigger_name(trigger), work_item_id);
signal = true;
error_unlock:
- pthread_mutex_unlock(&executor->work.lock);
if (signal) {
pthread_cond_signal(&executor->work.cond);
}
+ pthread_mutex_unlock(&executor->work.lock);
lttng_evaluation_destroy(evaluation);
return executor_status;