#include <lttng/trigger/trigger-internal.h>
#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule.h>
+#include <lttng/condition/on-event-internal.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/condition/buffer-usage.h>
#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-expr-internal.h>
#include <lttng/action/action-internal.h>
+#include <lttng/action/group.h>
#include <common/credentials.h>
#include <common/payload.h>
#include <common/payload-view.h>
#include <inttypes.h>
LTTNG_HIDDEN
-bool lttng_trigger_validate(struct lttng_trigger *trigger)
+bool lttng_trigger_validate(const struct lttng_trigger *trigger)
{
bool valid;
return trigger ? trigger->condition : NULL;
}
-LTTNG_HIDDEN
const struct lttng_condition *lttng_trigger_get_const_condition(
const struct lttng_trigger *trigger)
{
- return trigger->condition;
+ return trigger ? trigger->condition : NULL;
}
-
/*
* Note: the lack of reference counting 'get' on the action object is normal.
* This API was exposed as such in 2.11. The client is not expected to call
return trigger ? trigger->action : NULL;
}
-LTTNG_HIDDEN
const struct lttng_action *lttng_trigger_get_const_action(
const struct lttng_trigger *trigger)
{
- return trigger->action;
+ return trigger ? trigger->action : NULL;
}
static void trigger_destroy_ref(struct urcu_ref *ref)
}
/*
- * Name is not taken into account since it is cosmetic only.
+ * FIXME: frdeso: this is a change of behavior.
+ * See internal tracker issue 1028.
*/
+ if (strcmp(a->name, b->name) != 0) {
+ return false;
+ }
+
if (!lttng_condition_is_equal(a->condition, b->condition)) {
return false;
}
/* Apply to any domain. */
type = LTTNG_DOMAIN_NONE;
break;
- case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT:
+ case LTTNG_CONDITION_TYPE_ON_EVENT:
/* Return the domain of the event rule. */
- c_status = lttng_condition_event_rule_get_rule(
+ c_status = lttng_condition_on_event_get_rule(
trigger->condition, &event_rule);
assert(c_status == LTTNG_CONDITION_STATUS_OK);
type = lttng_event_rule_get_domain_type(event_rule);
return type;
}
+
+/*
+ * Generate bytecode related to the trigger.
+ * On success LTTNG_OK. On error, returns lttng_error code.
+ */
+LTTNG_HIDDEN
+enum lttng_error_code lttng_trigger_generate_bytecode(
+ struct lttng_trigger *trigger,
+ const struct lttng_credentials *creds)
+{
+ enum lttng_error_code ret;
+ struct lttng_condition *condition = NULL;
+
+ condition = lttng_trigger_get_condition(trigger);
+ if (!condition) {
+ ret = LTTNG_ERR_INVALID_TRIGGER;
+ goto end;
+ }
+
+ switch (lttng_condition_get_type(condition)) {
+ case LTTNG_CONDITION_TYPE_ON_EVENT:
+ {
+ struct lttng_event_rule *event_rule;
+ const enum lttng_condition_status condition_status =
+ lttng_condition_on_event_borrow_rule_mutable(
+ condition, &event_rule);
+
+ assert(condition_status == LTTNG_CONDITION_STATUS_OK);
+
+ /* Generate the filter bytecode. */
+ ret = lttng_event_rule_generate_filter_bytecode(
+ event_rule, creds);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+ /* Generate the capture bytecode. */
+ ret = lttng_condition_on_event_generate_capture_descriptor_bytecode(
+ condition);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+ ret = LTTNG_OK;
+ break;
+ }
+ default:
+ ret = LTTNG_OK;
+ break;
+ }
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+struct lttng_trigger *lttng_trigger_copy(const struct lttng_trigger *trigger)
+{
+ int ret;
+ struct lttng_payload copy_buffer;
+ struct lttng_trigger *copy = NULL;
+
+ lttng_payload_init(©_buffer);
+
+ ret = lttng_trigger_serialize(trigger, ©_buffer);
+ if (ret < 0) {
+ goto end;
+ }
+
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ ©_buffer, 0, -1);
+ ret = lttng_trigger_create_from_payload(
+ &view, ©);
+ if (ret < 0) {
+ copy = NULL;
+ goto end;
+ }
+ }
+
+end:
+ lttng_payload_reset(©_buffer);
+ return copy;
+}
+
+
+static
+bool action_type_needs_tracer_notifier(enum lttng_action_type action_type)
+{
+ switch (action_type) {
+ case LTTNG_ACTION_TYPE_NOTIFY:
+ case LTTNG_ACTION_TYPE_START_SESSION:
+ case LTTNG_ACTION_TYPE_STOP_SESSION:
+ case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION:
+ case LTTNG_ACTION_TYPE_ROTATE_SESSION:
+ return true;
+ case LTTNG_ACTION_TYPE_INCREMENT_VALUE:
+ return false;
+ case LTTNG_ACTION_TYPE_GROUP:
+ case LTTNG_ACTION_TYPE_UNKNOWN:
+ default:
+ abort();
+ }
+}
+
+static
+bool action_needs_tracer_notifier(const struct lttng_action *action)
+{
+ bool needs_tracer_notifier = false;
+ unsigned int i, count;
+ enum lttng_action_status action_status;
+ enum lttng_action_type action_type;
+
+ assert(action);
+ /* If there is only one action. Check if it needs a tracer notifier. */
+ action_type = lttng_action_get_type(action);
+ if (action_type != LTTNG_ACTION_TYPE_GROUP) {
+ needs_tracer_notifier = action_type_needs_tracer_notifier(
+ action_type);
+ goto end;
+ }
+
+ /*
+ * Iterate over all the actions of the action group and check if any of
+ * them needs a tracer notifier.
+ */
+ action_status = lttng_action_group_get_count(action, &count);
+ assert(action_status == LTTNG_ACTION_STATUS_OK);
+ for (i = 0; i < count; i++) {
+ const struct lttng_action *inner_action =
+ lttng_action_group_get_at_index(action, i);
+
+ action_type = lttng_action_get_type(inner_action);
+ if (action_type_needs_tracer_notifier(action_type)) {
+ needs_tracer_notifier = true;
+ goto end;
+ }
+ }
+
+end:
+ return needs_tracer_notifier;
+}
+
+LTTNG_HIDDEN
+bool lttng_trigger_needs_tracer_notifier(const struct lttng_trigger *trigger)
+{
+ bool needs_tracer_notifier = false;
+ const struct lttng_condition *condition =
+ lttng_trigger_get_const_condition(trigger);
+ const struct lttng_action *action =
+ lttng_trigger_get_const_action(trigger);
+
+ switch (lttng_condition_get_type(condition)) {
+ case LTTNG_CONDITION_TYPE_ON_EVENT:
+ needs_tracer_notifier = action_needs_tracer_notifier(action);
+ goto end;
+ case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
+ case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
+ case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
+ case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
+ goto end;
+ case LTTNG_CONDITION_TYPE_UNKNOWN:
+ default:
+ abort();
+ }
+end:
+ return needs_tracer_notifier;
+}