+ size_before_payload = payload->buffer.size;
+
+ /* Trigger name. */
+ ret = lttng_dynamic_buffer_append(
+ &payload->buffer, trigger->name, size_name);
+ if (ret) {
+ goto end;
+ }
+
+ ret = lttng_condition_serialize(trigger->condition, payload);
+ if (ret) {
+ goto end;
+ }
+
+ ret = lttng_action_serialize(trigger->action, payload);
+ if (ret) {
+ goto end;
+ }
+
+ /* Update payload size. */
+ header = (typeof(header)) (payload->buffer.data + header_offset);
+ header->length = payload->buffer.size - size_before_payload;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+bool lttng_trigger_is_equal(
+ const struct lttng_trigger *a, const struct lttng_trigger *b)
+{
+ if (a->firing_policy.type != b->firing_policy.type) {
+ return false;
+ }
+
+ if (a->firing_policy.threshold != b->firing_policy.threshold) {
+ return false;
+ }
+
+ /*
+ * Name is not taken into account since it is cosmetic only.
+ */
+ if (!lttng_condition_is_equal(a->condition, b->condition)) {
+ return false;
+ }
+
+ if (!lttng_action_is_equal(a->action, b->action)) {
+ return false;
+ }
+
+ if (!lttng_credentials_is_equal(lttng_trigger_get_credentials(a),
+ lttng_trigger_get_credentials(b))) {
+ return false;
+ }
+
+ return true;
+}
+
+enum lttng_trigger_status lttng_trigger_set_name(struct lttng_trigger *trigger,
+ const char* name)
+{
+ char *name_copy = NULL;
+ enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
+
+ if (!trigger || !name ||
+ strlen(name) == 0) {
+ status = LTTNG_TRIGGER_STATUS_INVALID;
+ goto end;
+ }
+
+ name_copy = strdup(name);
+ if (!name_copy) {
+ status = LTTNG_TRIGGER_STATUS_ERROR;
+ goto end;
+ }
+
+ free(trigger->name);
+
+ trigger->name = name_copy;
+ name_copy = NULL;
+end:
+ return status;
+}
+
+enum lttng_trigger_status lttng_trigger_get_name(
+ const struct lttng_trigger *trigger, const char **name)
+{
+ enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
+
+ if (!trigger || !name) {
+ status = LTTNG_TRIGGER_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!trigger->name) {
+ status = LTTNG_TRIGGER_STATUS_UNSET;
+ }
+
+ *name = trigger->name;
+end:
+ return status;
+}
+
+LTTNG_HIDDEN
+int lttng_trigger_assign_name(struct lttng_trigger *dst,
+ const struct lttng_trigger *src)
+{
+ int ret = 0;
+ enum lttng_trigger_status status;
+
+ status = lttng_trigger_set_name(dst, src->name);
+ if (status != LTTNG_TRIGGER_STATUS_OK) {
+ ret = -1;
+ ERR("Failed to set name for trigger");
+ goto end;
+ }
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+void lttng_trigger_set_tracer_token(struct lttng_trigger *trigger,
+ uint64_t token)
+{
+ assert(trigger);
+ LTTNG_OPTIONAL_SET(&trigger->tracer_token, token);
+}
+
+LTTNG_HIDDEN
+uint64_t lttng_trigger_get_tracer_token(const struct lttng_trigger *trigger)
+{
+ assert(trigger);
+
+ return LTTNG_OPTIONAL_GET(trigger->tracer_token);
+}
+
+LTTNG_HIDDEN
+int lttng_trigger_generate_name(struct lttng_trigger *trigger,
+ uint64_t unique_id)
+{
+ int ret = 0;
+ char *generated_name = NULL;
+
+ ret = asprintf(&generated_name, "T%" PRIu64 "", unique_id);
+ if (ret < 0) {
+ ERR("Failed to generate trigger name");
+ ret = -1;
+ goto end;
+ }
+
+ ret = 0;
+ free(trigger->name);
+ trigger->name = generated_name;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+void lttng_trigger_get(struct lttng_trigger *trigger)
+{
+ urcu_ref_get(&trigger->ref);
+}
+
+LTTNG_HIDDEN
+void lttng_trigger_put(struct lttng_trigger *trigger)
+{
+ if (!trigger) {
+ return;
+ }
+
+ urcu_ref_put(&trigger->ref , trigger_destroy_ref);
+}
+
+static void delete_trigger_array_element(void *ptr)
+{
+ struct lttng_trigger *trigger = ptr;
+
+ lttng_trigger_put(trigger);
+}
+
+LTTNG_HIDDEN
+struct lttng_triggers *lttng_triggers_create(void)
+{
+ struct lttng_triggers *triggers = NULL;
+
+ triggers = zmalloc(sizeof(*triggers));
+ if (!triggers) {
+ goto end;
+ }
+
+ lttng_dynamic_pointer_array_init(&triggers->array, delete_trigger_array_element);
+
+end:
+ return triggers;
+}
+
+LTTNG_HIDDEN
+struct lttng_trigger *lttng_triggers_borrow_mutable_at_index(
+ const struct lttng_triggers *triggers, unsigned int index)
+{
+ struct lttng_trigger *trigger = NULL;
+
+ assert(triggers);
+ if (index >= lttng_dynamic_pointer_array_get_count(&triggers->array)) {
+ goto end;
+ }
+
+ trigger = (struct lttng_trigger *)
+ lttng_dynamic_pointer_array_get_pointer(
+ &triggers->array, index);
+end:
+ return trigger;
+}
+
+LTTNG_HIDDEN
+int lttng_triggers_add(
+ struct lttng_triggers *triggers, struct lttng_trigger *trigger)
+{
+ int ret;
+
+ assert(triggers);
+ assert(trigger);
+
+ lttng_trigger_get(trigger);
+
+ ret = lttng_dynamic_pointer_array_add_pointer(&triggers->array, trigger);