+ state = argpar_state_create(*argc, *argv, notify_action_opt_descrs);
+ if (!state) {
+ ERR("Failed to allocate an argpar state.");
+ goto error;
+ }
+
+ while (true) {
+ enum argpar_state_parse_next_status status;
+
+ ARGPAR_ITEM_DESTROY_AND_RESET(item);
+ status = argpar_state_parse_next(state, &item, &error);
+ if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
+ ERR("%s", error);
+ goto error;
+ } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
+ /* Just stop parsing here. */
+ break;
+ } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
+ break;
+ }
+
+ assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
+
+ if (item->type == ARGPAR_ITEM_TYPE_OPT) {
+ const struct argpar_item_opt *item_opt =
+ (const struct argpar_item_opt *) item;
+
+ switch (item_opt->descr->id) {
+ case OPT_FIRE_ONCE_AFTER:
+ {
+ if (!assign_string(&fire_once_after_str,
+ item_opt->arg,
+ "--fire-once-after")) {
+ goto error;
+ }
+
+ break;
+ }
+ case OPT_FIRE_EVERY:
+ {
+ if (!assign_string(&fire_every_str,
+ item_opt->arg,
+ "--fire-every")) {
+ goto error;
+ }
+
+ break;
+ }
+
+ default:
+ abort();
+ }
+ } else {
+ const struct argpar_item_non_opt *item_non_opt;
+
+ assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
+
+ item_non_opt = (const struct argpar_item_non_opt *) item;
+
+ switch (item_non_opt->non_opt_index) {
+ default:
+ ERR("Unexpected argument `%s`.",
+ item_non_opt->arg);
+ goto error;
+ }
+ }
+ }
+
+ *argc -= argpar_state_get_ingested_orig_args(state);
+ *argv += argpar_state_get_ingested_orig_args(state);
+
+ if (fire_once_after_str && fire_every_str) {
+ ERR("--fire-once and --fire-every are mutually exclusive.");
+ goto error;
+ }
+
+ if (fire_once_after_str) {
+ unsigned long long threshold;
+
+ if (utils_parse_unsigned_long_long(
+ fire_once_after_str, &threshold) != 0) {
+ ERR("Failed to parse `%s` as an integer.",
+ fire_once_after_str);
+ goto error;
+ }
+
+ if (threshold == 0) {
+ ERR("Once after N policy threshold cannot be `0`.");
+ goto error;
+ }
+
+ policy = lttng_firing_policy_once_after_n_create(threshold);
+ if (!policy) {
+ ERR("Failed to create policy once after `%s`.",
+ fire_once_after_str);
+ goto error;
+ }
+ }
+
+ if (fire_every_str) {
+ unsigned long long interval;
+ if (utils_parse_unsigned_long_long(fire_every_str, &interval) !=
+ 0) {
+ ERR("Failed to parse `%s` as an integer.",
+ fire_every_str);
+ goto error;
+ }
+ if (interval == 0) {
+ ERR("Every N policy interval cannot be `0`.");
+ goto error;
+ }
+
+ policy = lttng_firing_policy_every_n_create(interval);
+ if (!policy) {
+ ERR("Failed to create policy every `%s`.",
+ fire_every_str);
+ goto error;
+ }
+ }
+
+ action = lttng_action_notify_create();
+ if (!action) {
+ ERR("Failed to create notify action");
+ goto error;
+ }
+
+ if (policy) {
+ enum lttng_action_status status;
+ status = lttng_action_notify_set_firing_policy(action, policy);
+ if (status != LTTNG_ACTION_STATUS_OK) {
+ ERR("Failed to set firing policy");
+ goto error;
+ }
+ }
+
+ goto end;
+
+error:
+ lttng_action_destroy(action);
+ action = NULL;
+ free(error);
+end:
+ free(fire_once_after_str);
+ free(fire_every_str);
+ lttng_firing_policy_destroy(policy);
+ argpar_state_destroy(state);
+ argpar_item_destroy(item);
+ return action;
+}