#ifndef LTTNG_ACTION_INTERNAL_H
#define LTTNG_ACTION_INTERNAL_H
-#include <lttng/action/action.h>
-#include <common/macros.h>
#include <common/buffer-view.h>
#include <common/dynamic-buffer.h>
+#include <common/macros.h>
#include <common/payload-view.h>
#include <common/payload.h>
+#include <lttng/lttng.h>
+#include <pthread.h>
#include <stdbool.h>
#include <sys/types.h>
#include <urcu/ref.h>
struct lttng_action **action);
typedef const struct lttng_rate_policy *(*action_get_rate_policy_cb)(
const struct lttng_action *action);
+typedef enum lttng_action_status (*action_add_error_query_results_cb)(
+ const struct lttng_action *action,
+ struct lttng_error_query_results *results);
struct lttng_action {
struct urcu_ref ref;
action_equal_cb equal;
action_destroy_cb destroy;
action_get_rate_policy_cb get_rate_policy;
+ action_add_error_query_results_cb add_error_query_results;
/* Internal use only. */
uint64_t execution_counter;
/*
* The number of time the action execution failed.
+ * An unsigned long is used to use a type which makes atomic
+ * operations possible.
*/
- uint64_t execution_failure_counter;
+ unsigned long execution_failure_counter;
};
struct lttng_action_comm {
action_serialize_cb serialize,
action_equal_cb equal,
action_destroy_cb destroy,
- action_get_rate_policy_cb get_rate_policy);
+ action_get_rate_policy_cb get_rate_policy,
+ action_add_error_query_results_cb add_error_query_results);
LTTNG_HIDDEN
bool lttng_action_validate(struct lttng_action *action);
LTTNG_HIDDEN
bool lttng_action_should_execute(const struct lttng_action *action);
+LTTNG_HIDDEN
+enum lttng_action_status lttng_action_add_error_query_results(
+ const struct lttng_action *action,
+ struct lttng_error_query_results *results);
+
+/*
+ * For use by the various lttng_action implementation. Implements the default
+ * behavior to the generic error "execution failure counter" that all actions
+ * (except group, which passes-through) provide.
+ */
+LTTNG_HIDDEN
+enum lttng_action_status lttng_action_generic_add_error_query_results(
+ const struct lttng_action *action,
+ struct lttng_error_query_results *results);
+
#endif /* LTTNG_ACTION_INTERNAL_H */
const struct lttng_error_query *query);
LTTNG_HIDDEN
-const struct lttng_action *lttng_error_query_action_borrow_action_target(
+struct lttng_action *lttng_error_query_action_borrow_action_target(
const struct lttng_error_query *query,
- const struct lttng_trigger *trigger);
+ struct lttng_trigger *trigger);
LTTNG_HIDDEN
int lttng_error_query_serialize(const struct lttng_error_query *query,
#include <common/dynamic-array.h>
#include <common/macros.h>
#include <common/optional.h>
-#include <lttng/trigger/trigger.h>
+#include <lttng/lttng.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
LTTNG_HIDDEN
void lttng_trigger_unlock(struct lttng_trigger *trigger);
+LTTNG_HIDDEN
+enum lttng_trigger_status lttng_trigger_add_error_results(
+ const struct lttng_trigger *trigger,
+ struct lttng_error_query_results *results);
+
+LTTNG_HIDDEN
+enum lttng_trigger_status lttng_trigger_add_action_error_query_results(
+ struct lttng_trigger *trigger,
+ struct lttng_error_query_results *results);
+
#endif /* LTTNG_TRIGGER_INTERNAL_H */
clear.c clear.h \
tracker.c tracker.h \
event-notifier-error-accounting.c event-notifier-error-accounting.h \
- action-executor.c action-executor.h
+ action-executor.c action-executor.h\
+ trigger-error-query.c
lttng_sessiond_LDFLAGS = -rdynamic
#include "common/buffer-view.h"
#include "common/compat/socket.h"
-#include "common/dynamic-buffer.h"
#include "common/dynamic-array.h"
-#include "common/payload.h"
-#include "common/payload-view.h"
+#include "common/dynamic-buffer.h"
#include "common/fd-handle.h"
-#include "common/sessiond-comm/sessiond-comm.h"
-#include "common/payload.h"
#include "common/payload-view.h"
+#include "common/payload.h"
+#include "common/sessiond-comm/sessiond-comm.h"
#include "lttng/lttng-error.h"
#include "lttng/tracker.h"
#include <common/compat/getenv.h>
#include <common/tracker.h>
#include <common/unix.h>
#include <common/utils.h>
+#include <lttng/error-query-internal.h>
#include <lttng/event-internal.h>
#include <lttng/session-descriptor-internal.h>
#include <lttng/session-internal.h>
#include <sys/stat.h>
#include <unistd.h>
+#include "agent-thread.h"
+#include "clear.h"
#include "client.h"
-#include "lttng-sessiond.h"
#include "cmd.h"
+#include "health-sessiond.h"
#include "kernel.h"
+#include "lttng-sessiond.h"
+#include "manage-consumer.h"
#include "save.h"
-#include "health-sessiond.h"
#include "testpoint.h"
#include "utils.h"
-#include "manage-consumer.h"
-#include "clear.h"
-#include "agent-thread.h"
static bool is_root;
return ret_code;
}
+static enum lttng_error_code receive_lttng_error_query(struct command_ctx *cmd_ctx,
+ int sock,
+ int *sock_error,
+ struct lttng_error_query **_query)
+{
+ int ret;
+ size_t query_len;
+ ssize_t sock_recv_len;
+ enum lttng_error_code ret_code;
+ struct lttng_payload query_payload;
+ struct lttng_error_query *query = NULL;
+
+ lttng_payload_init(&query_payload);
+ query_len = (size_t) cmd_ctx->lsm.u.error_query.length;
+ ret = lttng_dynamic_buffer_set_size(&query_payload.buffer, query_len);
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ sock_recv_len = lttcomm_recv_unix_sock(
+ sock, query_payload.buffer.data, query_len);
+ if (sock_recv_len < 0 || sock_recv_len != query_len) {
+ ERR("Failed to receive error query in command payload");
+ *sock_error = 1;
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+
+ /* Receive fds, if any. */
+ if (cmd_ctx->lsm.fd_count > 0) {
+ sock_recv_len = lttcomm_recv_payload_fds_unix_sock(
+ sock, cmd_ctx->lsm.fd_count, &query_payload);
+ if (sock_recv_len > 0 &&
+ sock_recv_len != cmd_ctx->lsm.fd_count * sizeof(int)) {
+ ERR("Failed to receive all file descriptors for error query in command payload: expected fd count = %u, ret = %d",
+ cmd_ctx->lsm.fd_count, (int) ret);
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ *sock_error = 1;
+ goto end;
+ } else if (sock_recv_len <= 0) {
+ ERR("Failed to receive file descriptors for error query in command payload: expected fd count = %u, ret = %d",
+ cmd_ctx->lsm.fd_count, (int) ret);
+ ret_code = LTTNG_ERR_FATAL;
+ *sock_error = 1;
+ goto end;
+ }
+ }
+
+ /* Deserialize error query. */
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &query_payload, 0, -1);
+
+ if (lttng_error_query_create_from_payload(&view, &query) !=
+ query_len) {
+ ERR("Invalid error query received as part of command payload");
+ ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+ goto end;
+ }
+ }
+
+ *_query = query;
+ ret_code = LTTNG_OK;
+
+end:
+ lttng_payload_reset(&query_payload);
+ return ret_code;
+}
+
/*
* Version of setup_lttng_msg() without command header.
*/
case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
case LTTNG_CLEAR_SESSION:
case LTTNG_LIST_TRIGGERS:
+ case LTTNG_EXECUTE_ERROR_QUERY:
need_domain = false;
break;
default:
switch (cmd_ctx->lsm.cmd_type) {
case LTTNG_REGISTER_TRIGGER:
case LTTNG_UNREGISTER_TRIGGER:
+ case LTTNG_EXECUTE_ERROR_QUERY:
need_consumerd = false;
break;
default:
case LTTNG_ROTATION_GET_INFO:
case LTTNG_REGISTER_TRIGGER:
case LTTNG_LIST_TRIGGERS:
+ case LTTNG_EXECUTE_ERROR_QUERY:
break;
default:
/* Setup lttng message with no payload */
case LTTNG_REGISTER_TRIGGER:
case LTTNG_UNREGISTER_TRIGGER:
case LTTNG_LIST_TRIGGERS:
+ case LTTNG_EXECUTE_ERROR_QUERY:
need_tracing_session = false;
break;
default:
ret = LTTNG_OK;
break;
}
+ case LTTNG_EXECUTE_ERROR_QUERY:
+ {
+ struct lttng_error_query *query;
+ const struct lttng_credentials cmd_creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid),
+ .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid),
+ };
+ struct lttng_error_query_results *results = NULL;
+ size_t original_payload_size;
+ size_t payload_size;
+
+ ret = setup_empty_lttng_msg(cmd_ctx);
+ if (ret) {
+ ret = LTTNG_ERR_NOMEM;
+ goto setup_error;
+ }
+
+ original_payload_size = cmd_ctx->reply_payload.buffer.size;
+
+ ret = receive_lttng_error_query(
+ cmd_ctx, *sock, sock_error, &query);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ ret = cmd_execute_error_query(&cmd_creds, query, &results,
+ the_notification_thread_handle);
+ lttng_error_query_destroy(query);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ assert(results);
+ ret = lttng_error_query_results_serialize(
+ results, &cmd_ctx->reply_payload);
+ lttng_error_query_results_destroy(results);
+ if (ret) {
+ ERR("Failed to serialize error query result set in reply to `execute error query` command");
+ ret = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ payload_size = cmd_ctx->reply_payload.buffer.size -
+ original_payload_size;
+
+ update_lttng_msg(cmd_ctx, 0, payload_size);
+
+ ret = LTTNG_OK;
+
+ break;
+ }
default:
ret = LTTNG_ERR_UND;
break;
*
*/
-#include "bin/lttng-sessiond/session.h"
+
#define _LGPL_SOURCE
#include <assert.h>
#include <inttypes.h>
+#include <stdio.h>
+#include <sys/stat.h>
#include <urcu/list.h>
#include <urcu/uatomic.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <common/defaults.h>
+#include <common/buffer-view.h>
#include <common/common.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <common/relayd/relayd.h>
-#include <common/utils.h>
#include <common/compat/string.h>
-#include <common/kernel-ctl/kernel-ctl.h>
+#include <common/defaults.h>
#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
-#include <common/payload.h>
+#include <common/kernel-ctl/kernel-ctl.h>
#include <common/payload-view.h>
+#include <common/payload.h>
+#include <common/relayd/relayd.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/string-utils/string-utils.h>
#include <common/trace-chunk.h>
-#include <lttng/location-internal.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/condition/condition.h>
+#include <common/utils.h>
+#include <lttng/action/action-internal.h>
+#include <lttng/action/action.h>
+#include <lttng/channel-internal.h>
+#include <lttng/channel.h>
#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/on-event.h>
+#include <lttng/condition/condition.h>
#include <lttng/condition/on-event-internal.h>
-#include <lttng/event-rule/event-rule.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/error-query-internal.h>
#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/action/action.h>
-#include <lttng/channel.h>
-#include <lttng/channel-internal.h>
-#include <lttng/rotate-internal.h>
+#include <lttng/event-rule/event-rule.h>
#include <lttng/location-internal.h>
-#include <lttng/session-internal.h>
-#include <lttng/userspace-probe-internal.h>
-#include <lttng/session-descriptor-internal.h>
#include <lttng/lttng-error.h>
+#include <lttng/rotate-internal.h>
+#include <lttng/session-descriptor-internal.h>
+#include <lttng/session-internal.h>
#include <lttng/tracker.h>
-#include <common/string-utils/string-utils.h>
+#include <lttng/trigger/trigger-internal.h>
+#include <lttng/userspace-probe-internal.h>
+#include "agent-thread.h"
+#include "agent.h"
+#include "buffer-registry.h"
#include "channel.h"
+#include "cmd.h"
#include "consumer.h"
+#include "event-notifier-error-accounting.h"
#include "event.h"
#include "health-sessiond.h"
-#include "kernel.h"
#include "kernel-consumer.h"
+#include "kernel.h"
#include "lttng-sessiond.h"
-#include "utils.h"
#include "lttng-syscall.h"
-#include "agent.h"
-#include "buffer-registry.h"
-#include "notification-thread.h"
#include "notification-thread-commands.h"
+#include "notification-thread.h"
#include "rotate.h"
#include "rotation-thread.h"
+#include "session.h"
#include "timer.h"
-#include "agent-thread.h"
#include "tracker.h"
-
-#include "cmd.h"
+#include "utils.h"
/* Sleep for 100ms between each check for the shm path's deletion. */
#define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000
lttng_triggers_destroy(triggers);
return ret;
}
+
+enum lttng_error_code cmd_execute_error_query(const struct lttng_credentials *cmd_creds,
+ const struct lttng_error_query *query,
+ struct lttng_error_query_results **_results,
+ struct notification_thread_handle *notification_thread)
+{
+ enum lttng_error_code ret_code;
+ const struct lttng_trigger *query_target_trigger;
+ struct lttng_action *query_target_action;
+ struct lttng_trigger *matching_trigger = NULL;
+ const char *trigger_name;
+ uid_t trigger_owner;
+ enum lttng_trigger_status trigger_status;
+ struct lttng_error_query_results *results = NULL;
+
+ switch (lttng_error_query_get_target_type(query)) {
+ case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
+ query_target_trigger = lttng_error_query_trigger_borrow_target(query);
+ break;
+ case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
+ query_target_trigger = lttng_error_query_action_borrow_trigger_target(
+ query);
+ break;
+ default:
+ abort();
+ }
+
+ assert(query_target_trigger);
+
+ ret_code = notification_thread_command_get_trigger(notification_thread,
+ query_target_trigger, &matching_trigger);
+ if (ret_code != LTTNG_OK) {
+ goto end;
+ }
+
+ /* No longer needed. */
+ query_target_trigger = NULL;
+
+ if (lttng_error_query_get_target_type(query) ==
+ LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION) {
+ /* Get the sessiond-side version of the target action. */
+ query_target_action =
+ lttng_error_query_action_borrow_action_target(
+ query, matching_trigger);
+ }
+
+ trigger_status = lttng_trigger_get_name(matching_trigger, &trigger_name);
+ trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ?
+ trigger_name : "(unnamed)";
+ trigger_status = lttng_trigger_get_owner_uid(matching_trigger,
+ &trigger_owner);
+ assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+ results = lttng_error_query_results_create();
+ if (!results) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ DBG("Running \"execute error query\" command: trigger name = '%s', trigger owner uid = %d, command creds uid = %d",
+ trigger_name, (int) trigger_owner,
+ (int) lttng_credentials_get_uid(cmd_creds));
+
+ /*
+ * Validate the trigger credentials against the command credentials.
+ * Only the root user can target a trigger with non-matching
+ * credentials.
+ */
+ if (!lttng_credentials_is_equal_uid(
+ lttng_trigger_get_credentials(matching_trigger),
+ cmd_creds)) {
+ if (lttng_credentials_get_uid(cmd_creds) != 0) {
+ ERR("Trigger credentials do not match the command credentials: trigger name = '%s', trigger owner uid = %d, command creds uid = %d",
+ trigger_name, (int) trigger_owner,
+ (int) lttng_credentials_get_uid(cmd_creds));
+ ret_code = LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+ }
+
+ switch (lttng_error_query_get_target_type(query)) {
+ case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER:
+ trigger_status = lttng_trigger_add_error_results(
+ matching_trigger, results);
+
+ switch (trigger_status) {
+ case LTTNG_TRIGGER_STATUS_OK:
+ break;
+ default:
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ break;
+ case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION:
+ {
+ const enum lttng_action_status action_status =
+ lttng_action_add_error_query_results(
+ query_target_action, results);
+
+ switch (action_status) {
+ case LTTNG_ACTION_STATUS_OK:
+ break;
+ default:
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ *_results = results;
+ results = NULL;
+ ret_code = LTTNG_OK;
+end:
+ lttng_trigger_put(matching_trigger);
+ lttng_error_query_results_destroy(results);
+ return ret_code;
+}
+
/*
* Send relayd sockets from snapshot output to consumer. Ignore request if the
* snapshot output is *not* set with a remote destination.
int cmd_list_triggers(struct command_ctx *cmd_ctx,
struct notification_thread_handle *notification_thread_handle,
struct lttng_triggers **return_triggers);
+enum lttng_error_code cmd_execute_error_query(const struct lttng_credentials *cmd_creds,
+ const struct lttng_error_query *query,
+ struct lttng_error_query_results **_results,
+ struct notification_thread_handle *notification_thread);
int cmd_rotate_session(struct ltt_session *session,
struct lttng_rotate_session_return *rotate_return,
--- /dev/null
+/*
+ * Copyright (C) 2021 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "event-notifier-error-accounting.h"
+#include <lttng/error-query-internal.h>
+#include <lttng/trigger/trigger-internal.h>
+#include <lttng/action/action-internal.h>
+
+LTTNG_HIDDEN
+enum lttng_trigger_status lttng_trigger_add_error_results(
+ const struct lttng_trigger *trigger,
+ struct lttng_error_query_results *results)
+{
+ enum lttng_trigger_status status;
+ uint64_t discarded_tracer_messages_count;
+ enum event_notifier_error_accounting_status error_accounting_status;
+ struct lttng_error_query_result *discarded_tracer_messages_counter = NULL;
+ const char *trigger_name;
+ uid_t trigger_owner;
+
+ status = lttng_trigger_get_name(trigger, &trigger_name);
+ trigger_name = status == LTTNG_TRIGGER_STATUS_OK ?
+ trigger_name : "(unnamed)";
+ status = lttng_trigger_get_owner_uid(trigger,
+ &trigger_owner);
+ assert(status == LTTNG_TRIGGER_STATUS_OK);
+
+ error_accounting_status = event_notifier_error_accounting_get_count(
+ trigger, &discarded_tracer_messages_count);
+ if (error_accounting_status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
+ ERR("Failed to retrieve tracer discarded messages count for triger: triggger name = '%s', trigger owner uid = %d",
+ trigger_name, (int) trigger_owner);
+ status = LTTNG_TRIGGER_STATUS_ERROR;
+ goto end;
+ }
+
+ discarded_tracer_messages_counter = lttng_error_query_result_counter_create(
+ "discarded tracer messages",
+ "Count of messages discarded by the tracer due to a communication error with the session daemon",
+ discarded_tracer_messages_count);
+ if (!discarded_tracer_messages_counter) {
+ status = LTTNG_TRIGGER_STATUS_ERROR;
+ goto end;
+ }
+
+ if (lttng_error_query_results_add_result(
+ results, discarded_tracer_messages_counter)) {
+ status = LTTNG_TRIGGER_STATUS_ERROR;
+ goto end;
+ }
+
+ /* Ownership transferred to the results. */
+ discarded_tracer_messages_counter = NULL;
+
+ status = LTTNG_TRIGGER_STATUS_OK;
+end:
+ lttng_error_query_result_destroy(discarded_tracer_messages_counter);
+ return status;
+}
+
+LTTNG_HIDDEN
+enum lttng_trigger_status lttng_trigger_add_action_error_query_results(
+ struct lttng_trigger *trigger,
+ struct lttng_error_query_results *results)
+{
+ enum lttng_trigger_status status;
+ const char *trigger_name;
+ uid_t trigger_owner;
+ enum lttng_action_status action_status;
+
+ status = lttng_trigger_get_name(trigger, &trigger_name);
+ trigger_name = status == LTTNG_TRIGGER_STATUS_OK ?
+ trigger_name : "(unnamed)";
+ status = lttng_trigger_get_owner_uid(trigger,
+ &trigger_owner);
+ assert(status == LTTNG_TRIGGER_STATUS_OK);
+
+ action_status = lttng_action_add_error_query_results(
+ lttng_trigger_get_action(trigger), results);
+ switch (action_status) {
+ case LTTNG_ACTION_STATUS_OK:
+ status = LTTNG_TRIGGER_STATUS_OK;
+ goto end;
+ default:
+ status = LTTNG_TRIGGER_STATUS_ERROR;
+ goto end;
+ }
+
+ status = LTTNG_TRIGGER_STATUS_OK;
+end:
+ return status;
+}
#include <lttng/action/snapshot-session-internal.h>
#include <lttng/action/start-session-internal.h>
#include <lttng/action/stop-session-internal.h>
+#include <lttng/error-query-internal.h>
LTTNG_HIDDEN
const char *lttng_action_type_string(enum lttng_action_type action_type)
action_serialize_cb serialize,
action_equal_cb equal,
action_destroy_cb destroy,
- action_get_rate_policy_cb get_rate_policy)
+ action_get_rate_policy_cb get_rate_policy,
+ action_add_error_query_results_cb add_error_query_results)
{
urcu_ref_init(&action->ref);
action->type = type;
action->equal = equal;
action->destroy = destroy;
action->get_rate_policy = get_rate_policy;
+ action->add_error_query_results = add_error_query_results;
action->execution_request_counter = 0;
action->execution_counter = 0;
LTTNG_HIDDEN
void lttng_action_increase_execution_failure_count(struct lttng_action *action)
{
- action->execution_failure_counter++;
+ uatomic_inc(&action->execution_failure_counter);
}
LTTNG_HIDDEN
end:
return execute;
}
+
+LTTNG_HIDDEN
+enum lttng_action_status lttng_action_add_error_query_results(
+ const struct lttng_action *action,
+ struct lttng_error_query_results *results)
+{
+ return action->add_error_query_results(action, results);
+}
+
+LTTNG_HIDDEN
+enum lttng_action_status lttng_action_generic_add_error_query_results(
+ const struct lttng_action *action,
+ struct lttng_error_query_results *results)
+{
+ enum lttng_action_status action_status;
+ struct lttng_error_query_result *error_counter = NULL;
+ const uint64_t execution_failure_counter =
+ uatomic_read(&action->execution_failure_counter);
+
+ error_counter = lttng_error_query_result_counter_create(
+ "total execution failures",
+ "Aggregated count of errors encountered when executing the action",
+ execution_failure_counter);
+ if (!error_counter) {
+ action_status = LTTNG_ACTION_STATUS_ERROR;
+ goto end;
+ }
+
+ if (lttng_error_query_results_add_result(
+ results, error_counter)) {
+ action_status = LTTNG_ACTION_STATUS_ERROR;
+ goto end;
+ }
+
+ /* Ownership transferred to the results. */
+ error_counter = NULL;
+ action_status = LTTNG_ACTION_STATUS_OK;
+end:
+ lttng_error_query_result_destroy(error_counter);
+ return action_status;
+}
return consumed_len;
}
+static enum lttng_action_status lttng_action_group_add_error_query_results(
+ const struct lttng_action *action,
+ struct lttng_error_query_results *results)
+{
+ unsigned int i, count;
+ enum lttng_action_status action_status;
+ const struct lttng_action_group *group =
+ container_of(action, typeof(*group), parent);
+
+ action_status = lttng_action_group_get_count(action, &count);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ goto end;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct lttng_action *inner_action =
+ lttng_action_group_borrow_mutable_at_index(action, i);
+
+ action_status = lttng_action_add_error_query_results(
+ inner_action, results);
+ if (action_status != LTTNG_ACTION_STATUS_OK) {
+ goto end;
+ }
+ }
+end:
+ return action_status;
+}
+
struct lttng_action *lttng_action_group_create(void)
{
struct lttng_action_group *action_group;
lttng_action_group_validate,
lttng_action_group_serialize,
lttng_action_group_is_equal, lttng_action_group_destroy,
- NULL);
+ NULL,
+ lttng_action_group_add_error_query_results);
lttng_dynamic_pointer_array_init(&action_group->actions,
destroy_lttng_action_group_element);
lttng_action_notify_serialize,
lttng_action_notify_is_equal,
lttng_action_notify_destroy,
- lttng_action_notify_internal_get_rate_policy);
+ lttng_action_notify_internal_get_rate_policy,
+ lttng_action_generic_add_error_query_results);
notify->policy = policy;
policy = NULL;
lttng_action_rotate_session_serialize,
lttng_action_rotate_session_is_equal,
lttng_action_rotate_session_destroy,
- lttng_action_rotate_session_internal_get_rate_policy);
+ lttng_action_rotate_session_internal_get_rate_policy,
+ lttng_action_generic_add_error_query_results);
status = lttng_action_rotate_session_set_rate_policy(action, policy);
if (status != LTTNG_ACTION_STATUS_OK) {
lttng_action_snapshot_session_serialize,
lttng_action_snapshot_session_is_equal,
lttng_action_snapshot_session_destroy,
- lttng_action_snapshot_session_internal_get_rate_policy);
+ lttng_action_snapshot_session_internal_get_rate_policy,
+ lttng_action_generic_add_error_query_results);
status = lttng_action_snapshot_session_set_rate_policy(action, policy);
if (status != LTTNG_ACTION_STATUS_OK) {
lttng_action_start_session_serialize,
lttng_action_start_session_is_equal,
lttng_action_start_session_destroy,
- lttng_action_start_session_internal_get_rate_policy);
+ lttng_action_start_session_internal_get_rate_policy,
+ lttng_action_generic_add_error_query_results);
status = lttng_action_start_session_set_rate_policy(action, policy);
if (status != LTTNG_ACTION_STATUS_OK) {
lttng_action_stop_session_serialize,
lttng_action_stop_session_is_equal,
lttng_action_stop_session_destroy,
- lttng_action_stop_session_internal_get_rate_policy);
+ lttng_action_stop_session_internal_get_rate_policy,
+ lttng_action_generic_add_error_query_results);
status = lttng_action_stop_session_set_rate_policy(action, policy);
if (status != LTTNG_ACTION_STATUS_OK) {
goto error;
}
+ counter->value = value;
goto end;
error:
lttng_error_query_result_destroy(&counter->parent);
}
LTTNG_HIDDEN
-const struct lttng_action *lttng_error_query_action_borrow_action_target(
+struct lttng_action *lttng_error_query_action_borrow_action_target(
const struct lttng_error_query *query,
- const struct lttng_trigger *trigger)
+ struct lttng_trigger *trigger)
{
- const struct lttng_action *target_action = NULL;
+ struct lttng_action *target_action = NULL;
const struct lttng_error_query_action *query_action =
container_of(query, typeof(*query_action), parent);
- const struct lttng_action *trigger_action =
- lttng_trigger_get_const_action(trigger);
+ struct lttng_action *trigger_action =
+ lttng_trigger_get_action(trigger);
if (!query_action->action_index.is_set) {
target_action = trigger_action;
goto end;
}
- target_action = lttng_action_group_get_at_index(trigger_action,
+ target_action = lttng_action_group_borrow_mutable_at_index(
+ trigger_action,
LTTNG_OPTIONAL_GET(query_action->action_index));
}
$(top_builddir)/src/bin/lttng-sessiond/process-utils.$(OBJEXT) \
$(top_builddir)/src/bin/lttng-sessiond/thread.$(OBJEXT) \
$(top_builddir)/src/bin/lttng-sessiond/tracker.$(OBJEXT) \
+ $(top_builddir)/src/bin/lttng-sessiond/trigger-error-query.$(OBJEXT) \
$(top_builddir)/src/common/libcommon.la \
$(top_builddir)/src/common/testpoint/libtestpoint.la \
$(top_builddir)/src/common/compat/libcompat.la \