From 83d6d6c4496e692df39843142cb8cf96279eaa20 Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Thu, 7 Nov 2019 18:01:06 -0500 Subject: [PATCH] trackers: update list/track/untrack commands MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Desnoyers Change-Id: I18e41d0e3c7826596ac0468eb5ef7bcc549c8f98 Signed-off-by: Jérémie Galarneau --- src/bin/lttng/commands/list.c | 142 ++++- src/bin/lttng/commands/track-untrack.c | 498 ++++++++++++++---- src/common/mi-lttng-3.0.xsd | 233 +++++++- src/common/mi-lttng.c | 139 ++++- src/common/mi-lttng.h | 12 +- tests/regression/tools/mi/extract_xml.c | 22 +- tests/regression/tools/mi/test_mi | 34 +- .../tools/save-load/load-42-trackers.lttng | 23 +- tests/regression/tools/save-load/test_load | 31 +- 9 files changed, 926 insertions(+), 208 deletions(-) diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index 65d8ea6f5..fb891beb7 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -809,7 +809,7 @@ static int mi_list_ust_event_fields(struct lttng_event_field *fields, int count, } } - /* Close pid, domain, domains */ + /* Close pids, domain, domains */ ret = mi_lttng_close_multi_element(writer, 3); end: return ret; @@ -1512,43 +1512,78 @@ error_channels: return ret; } +static const char *get_tracker_str(enum lttng_tracker_type tracker_type) +{ + switch (tracker_type) { + case LTTNG_TRACKER_PID: + return "PID"; + case LTTNG_TRACKER_VPID: + return "VPID"; + case LTTNG_TRACKER_UID: + return "UID"; + case LTTNG_TRACKER_VUID: + return "VUID"; + case LTTNG_TRACKER_GID: + return "GID"; + case LTTNG_TRACKER_VGID: + return "VGID"; + } + return NULL; +} + /* - * List tracker PID(s) of session and domain. + * List tracker ID(s) of session and domain. */ -static int list_tracker_pids(void) +static int list_tracker_ids(enum lttng_tracker_type tracker_type) { int ret = 0; - int enabled; - int *pids = NULL; - size_t nr_pids; + int enabled = 1; + struct lttng_tracker_id *ids = NULL; + size_t nr_ids, i; - ret = lttng_list_tracker_pids(handle, - &enabled, &pids, &nr_pids); + ret = lttng_list_tracker_ids(handle, tracker_type, &ids, &nr_ids); if (ret) { return ret; } + if (nr_ids == 1 && ids[0].type == LTTNG_ID_ALL) { + enabled = 0; + } if (enabled) { - int i; - _MSG("PID tracker: ["); + _MSG("%s tracker: [", get_tracker_str(tracker_type)); - /* Mi tracker_pid element*/ + /* Mi tracker_id element */ if (writer) { - /* Open tracker_pid and targets elements */ - ret = mi_lttng_pid_tracker_open(writer); + /* Open tracker_id and targets elements */ + ret = mi_lttng_id_tracker_open(writer, tracker_type); if (ret) { goto end; } } - for (i = 0; i < nr_pids; i++) { + for (i = 0; i < nr_ids; i++) { + struct lttng_tracker_id *id = &ids[i]; + if (i) { _MSG(","); } - _MSG(" %d", pids[i]); + switch (id->type) { + case LTTNG_ID_ALL: + _MSG(" *"); + break; + case LTTNG_ID_VALUE: + _MSG(" %d", ids[i].value); + break; + case LTTNG_ID_STRING: + _MSG(" %s", ids[i].string); + break; + case LTTNG_ID_UNKNOWN: + return CMD_ERROR; + } /* Mi */ if (writer) { - ret = mi_lttng_pid_target(writer, pids[i], 0); + ret = mi_lttng_id_target( + writer, tracker_type, id, 0); if (ret) { goto end; } @@ -1556,24 +1591,26 @@ static int list_tracker_pids(void) } _MSG(" ]\n\n"); - /* Mi close tracker_pid and targets */ + /* Mi close tracker_id and targets */ if (writer) { - ret = mi_lttng_close_multi_element(writer,2); + ret = mi_lttng_close_multi_element(writer, 2); if (ret) { goto end; } } } end: - free(pids); + for (i = 0; i < nr_ids; i++) { + free(ids[i].string); + } + free(ids); return ret; - } /* - * List all tracker of a domain + * List all trackers of a domain */ -static int list_trackers(void) +static int list_trackers(const struct lttng_domain *domain) { int ret; @@ -1585,12 +1622,59 @@ static int list_trackers(void) } } - /* pid tracker */ - ret = list_tracker_pids(); - if (ret) { - goto end; + switch (domain->type) { + case LTTNG_DOMAIN_KERNEL: + /* pid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_PID); + if (ret) { + goto end; + } + /* vpid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_VPID); + if (ret) { + goto end; + } + /* uid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_UID); + if (ret) { + goto end; + } + /* vuid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_VUID); + if (ret) { + goto end; + } + /* gid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_GID); + if (ret) { + goto end; + } + /* vgid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_VGID); + if (ret) { + goto end; + } + break; + case LTTNG_DOMAIN_UST: + /* vpid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_VPID); + if (ret) { + goto end; + } + /* vuid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_VUID); + if (ret) { + goto end; + } + /* vgid tracker */ + ret = list_tracker_ids(LTTNG_TRACKER_VGID); + if (ret) { + goto end; + } + break; + default: + break; } - if (lttng_opt_mi) { /* Close trackers element */ ret = mi_lttng_writer_close_element(writer); @@ -2185,7 +2269,7 @@ int cmd_list(int argc, const char **argv) /* Trackers */ - ret = list_trackers(); + ret = list_trackers(&domain); if (ret) { goto end; } @@ -2282,7 +2366,7 @@ int cmd_list(int argc, const char **argv) switch (domains[i].type) { case LTTNG_DOMAIN_KERNEL: case LTTNG_DOMAIN_UST: - ret = list_trackers(); + ret = list_trackers(&domains[i]); if (ret) { goto end; } diff --git a/src/bin/lttng/commands/track-untrack.c b/src/bin/lttng/commands/track-untrack.c index 3073996a9..4f51ffa30 100644 --- a/src/bin/lttng/commands/track-untrack.c +++ b/src/bin/lttng/commands/track-untrack.c @@ -38,18 +38,46 @@ enum cmd_type { CMD_UNTRACK, }; +enum tracker_type_state { + STATE_NONE = 0, + STATE_PID, + STATE_VPID, + STATE_UID, + STATE_VUID, + STATE_GID, + STATE_VGID, +}; + +struct opt_type { + int used; + int all; + char *string; +}; + +struct id_list { + size_t nr; + struct lttng_tracker_id *array; +}; + static char *opt_session_name; static int opt_kernel; static int opt_userspace; -static int opt_all; -static char *opt_pid_string; -static int opt_pid; + +static struct opt_type opt_pid, opt_vpid, opt_uid, opt_vuid, opt_gid, opt_vgid; + +static enum tracker_type_state type_state; enum { OPT_HELP = 1, OPT_LIST_OPTIONS, OPT_SESSION, OPT_PID, + OPT_VPID, + OPT_UID, + OPT_VUID, + OPT_GID, + OPT_VGID, + OPT_ALL, }; static struct poptOption long_options[] = { @@ -58,78 +86,122 @@ static struct poptOption long_options[] = { { "session", 's', POPT_ARG_STRING, &opt_session_name, OPT_SESSION, 0, 0, }, { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0, }, { "userspace", 'u', POPT_ARG_VAL, &opt_userspace, 1, 0, 0, }, - { "pid", 'p', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_pid_string, OPT_PID, 0, 0, }, - { "all", 'a', POPT_ARG_VAL, &opt_all, 1, 0, 0, }, + { "pid", 'p', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_pid.string, OPT_PID, 0, 0, }, + { "vpid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_vpid.string, OPT_VPID, 0, 0, }, + { "uid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_uid.string, OPT_UID, 0, 0, }, + { "vuid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_vuid.string, OPT_VUID, 0, 0, }, + { "gid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_gid.string, OPT_GID, 0, 0, }, + { "vgid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_vgid.string, OPT_VGID, 0, 0, }, + { "all", 'a', POPT_ARG_NONE, 0, OPT_ALL, 0, 0, }, { "list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, 0, 0, }, { 0, 0, 0, 0, 0, 0, 0, }, }; -static -int parse_pid_string(const char *_pid_string, - int all, int **_pid_list, int *nr_pids) +static struct id_list *alloc_id_list(size_t nr_items) { - const char *one_pid_str; + struct id_list *id_list; + struct lttng_tracker_id *items; + + id_list = zmalloc(sizeof(*id_list)); + if (!id_list) { + goto error; + } + items = zmalloc(nr_items * sizeof(*items)); + if (!items) { + goto error; + } + id_list->nr = nr_items; + id_list->array = items; + return id_list; +error: + free(id_list); + return NULL; +} + +static void free_id_list(struct id_list *list) +{ + size_t nr_items; + int i; + + if (!list) { + return; + } + nr_items = list->nr; + for (i = 0; i < nr_items; i++) { + struct lttng_tracker_id *item = &list->array[i]; + + free(item->string); + } + free(list); +} + +static int parse_id_string( + const char *_id_string, int all, struct id_list **_id_list) +{ + const char *one_id_str; char *iter; int retval = CMD_SUCCESS; int count = 0; - int *pid_list = NULL; - char *pid_string = NULL; + struct id_list *id_list = NULL; + char *id_string = NULL; char *endptr; - if (all && _pid_string) { - ERR("An empty PID string is expected with --all"); + if (all && _id_string) { + ERR("An empty ID string is expected with --all"); retval = CMD_ERROR; goto error; } - if (!all && !_pid_string) { - ERR("Please specify --all with an empty PID string"); + if (!all && !_id_string) { + ERR("An ID string is expected"); retval = CMD_ERROR; goto error; } if (all) { - pid_list = zmalloc(sizeof(*pid_list)); - if (!pid_list) { + /* Empty ID string means all IDs */ + id_list = alloc_id_list(1); + if (!id_list) { ERR("Out of memory"); retval = CMD_ERROR; goto error; } - /* Empty PID string means all PIDs */ - count = 1; - pid_list[0] = -1; + id_list->array[0].type = LTTNG_ID_ALL; goto assign; } - pid_string = strdup(_pid_string); - if (!pid_string) { + id_string = strdup(_id_string); + if (!id_string) { ERR("Out of memory"); retval = CMD_ERROR; goto error; } /* Count */ - one_pid_str = strtok_r(pid_string, ",", &iter); - while (one_pid_str != NULL) { + one_id_str = strtok_r(id_string, ",", &iter); + while (one_id_str != NULL) { unsigned long v; - errno = 0; - v = strtoul(one_pid_str, &endptr, 10); - if ((v == 0 && errno == EINVAL) - || (v == ULONG_MAX && errno == ERANGE) - || (*one_pid_str != '\0' && *endptr != '\0')){ - ERR("Error parsing PID %s", one_pid_str); - retval = CMD_ERROR; - goto error; - } + if (isdigit(one_id_str[0])) { + errno = 0; + v = strtoul(one_id_str, &endptr, 10); + if ((v == 0 && errno == EINVAL) || + (v == ULONG_MAX && errno == ERANGE) || + (*one_id_str != '\0' && + *endptr != '\0')) { + ERR("Error parsing ID %s", one_id_str); + retval = CMD_ERROR; + goto error; + } - if ((long) v > INT_MAX || (int) v < 0) { - ERR("Invalid PID value %ld", (long) v); - retval = CMD_ERROR; - goto error; + if ((long) v > INT_MAX || (int) v < 0) { + ERR("Invalid ID value %ld", (long) v); + retval = CMD_ERROR; + goto error; + } } count++; /* For next loop */ - one_pid_str = strtok_r(NULL, ",", &iter); + one_id_str = strtok_r(NULL, ",", &iter); } if (count == 0) { ERR("Fatal error occurred when parsing pid string"); @@ -137,88 +209,134 @@ int parse_pid_string(const char *_pid_string, goto error; } - free(pid_string); + free(id_string); /* Identity of delimiter has been lost in first pass. */ - pid_string = strdup(_pid_string); - if (!pid_string) { + id_string = strdup(_id_string); + if (!id_string) { ERR("Out of memory"); retval = CMD_ERROR; goto error; } /* Allocate */ - pid_list = zmalloc(count * sizeof(*pid_list)); - if (!pid_list) { + id_list = alloc_id_list(count); + if (!id_list) { ERR("Out of memory"); retval = CMD_ERROR; goto error; } - /* Reparse string and populate the pid list. */ + /* Reparse string and populate the id list. */ count = 0; - one_pid_str = strtok_r(pid_string, ",", &iter); - while (one_pid_str != NULL) { - unsigned long v; + one_id_str = strtok_r(id_string, ",", &iter); + while (one_id_str != NULL) { + struct lttng_tracker_id *item; - v = strtoul(one_pid_str, NULL, 10); - pid_list[count++] = (int) v; + item = &id_list->array[count++]; + if (isdigit(one_id_str[0])) { + unsigned long v; + + v = strtoul(one_id_str, NULL, 10); + item->type = LTTNG_ID_VALUE; + item->value = (int) v; + } else { + item->type = LTTNG_ID_STRING; + item->string = strdup(one_id_str); + if (!item->string) { + PERROR("Failed to allocate ID string"); + retval = CMD_ERROR; + goto error; + } + } /* For next loop */ - one_pid_str = strtok_r(NULL, ",", &iter); + one_id_str = strtok_r(NULL, ",", &iter); } assign: - *nr_pids = count; - *_pid_list = pid_list; + *_id_list = id_list; goto end; /* SUCCESS */ /* ERROR */ error: - free(pid_list); + free_id_list(id_list); end: - free(pid_string); + free(id_string); return retval; } -static -enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, - const char *session_name, const char *pid_string, - int all, struct mi_writer *writer) +static const char *get_tracker_str(enum lttng_tracker_type tracker_type) +{ + switch (tracker_type) { + case LTTNG_TRACKER_PID: + return "PID"; + case LTTNG_TRACKER_VPID: + return "VPID"; + case LTTNG_TRACKER_UID: + return "UID"; + case LTTNG_TRACKER_VUID: + return "VUID"; + case LTTNG_TRACKER_GID: + return "GID"; + case LTTNG_TRACKER_VGID: + return "VGID"; + default: + return NULL; + } + return NULL; +} + +static enum cmd_error_code track_untrack_id(enum cmd_type cmd_type, + const char *cmd_str, + const char *session_name, + const char *id_string, + int all, + struct mi_writer *writer, + enum lttng_tracker_type tracker_type) { int ret, success = 1 , i; enum cmd_error_code retval = CMD_SUCCESS; - int *pid_list = NULL; - int nr_pids; + struct id_list *id_list = NULL; struct lttng_domain dom; struct lttng_handle *handle = NULL; - int (*cmd_func)(struct lttng_handle *handle, int pid); + int (*cmd_func)(struct lttng_handle *handle, + enum lttng_tracker_type tracker_type, + const struct lttng_tracker_id *id); + const char *tracker_str; switch (cmd_type) { case CMD_TRACK: - cmd_func = lttng_track_pid; + cmd_func = lttng_track_id; break; case CMD_UNTRACK: - cmd_func = lttng_untrack_pid; + cmd_func = lttng_untrack_id; break; default: ERR("Unknown command"); retval = CMD_ERROR; goto end; } - memset(&dom, 0, sizeof(dom)); if (opt_kernel) { dom.type = LTTNG_DOMAIN_KERNEL; } else if (opt_userspace) { dom.type = LTTNG_DOMAIN_UST; + if (tracker_type == LTTNG_TRACKER_PID) { + tracker_type = LTTNG_TRACKER_VPID; + } } else { /* Checked by the caller. */ assert(0); } - - ret = parse_pid_string(pid_string, all, &pid_list, &nr_pids); + tracker_str = get_tracker_str(tracker_type); + if (!tracker_str) { + ERR("Unknown tracker type"); + retval = CMD_ERROR; + goto end; + } + ret = parse_id_string(id_string, all, &id_list); if (ret != CMD_SUCCESS) { - ERR("Error parsing PID string"); + ERR("Error parsing %s string", tracker_str); retval = CMD_ERROR; goto end; } @@ -230,28 +348,42 @@ enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_st } if (writer) { - /* Open process element */ - ret = mi_lttng_targets_open(writer); + /* Open tracker_id and targets elements */ + ret = mi_lttng_id_tracker_open(writer, tracker_type); if (ret) { - retval = CMD_ERROR; goto end; } } - for (i = 0; i < nr_pids; i++) { - DBG("%s PID %d", cmd_str, pid_list[i]); - ret = cmd_func(handle, pid_list[i]); + for (i = 0; i < id_list->nr; i++) { + struct lttng_tracker_id *item = &id_list->array[i]; + + switch (item->type) { + case LTTNG_ID_ALL: + DBG("%s all IDs", cmd_str); + break; + case LTTNG_ID_VALUE: + DBG("%s ID %d", cmd_str, item->value); + break; + case LTTNG_ID_STRING: + DBG("%s ID '%s'", cmd_str, item->string); + break; + default: + retval = CMD_ERROR; + goto end; + } + ret = cmd_func(handle, tracker_type, item); if (ret) { + char *msg = NULL; + switch (-ret) { - case LTTNG_ERR_PID_TRACKED: - WARN("PID %i already tracked in session %s", - pid_list[i], session_name); + case LTTNG_ERR_ID_TRACKED: + msg = "already tracked"; success = 1; retval = CMD_SUCCESS; break; - case LTTNG_ERR_PID_NOT_TRACKED: - WARN("PID %i not tracked in session %s", - pid_list[i], session_name); + case LTTNG_ERR_ID_NOT_TRACKED: + msg = "already not tracked"; success = 1; retval = CMD_SUCCESS; break; @@ -261,21 +393,56 @@ enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_st retval = CMD_ERROR; break; } + if (msg) { + switch (item->type) { + case LTTNG_ID_ALL: + WARN("All %ss %s in session %s", + tracker_str, msg, + session_name); + break; + case LTTNG_ID_VALUE: + WARN("%s %i %s in session %s", + tracker_str, + item->value, msg, + session_name); + break; + case LTTNG_ID_STRING: + WARN("%s '%s' %s in session %s", + tracker_str, + item->string, msg, + session_name); + break; + default: + retval = CMD_ERROR; + goto end; + } + } } else { - if (pid_list[i] != -1) { - MSG("PID %i %sed in session %s", - pid_list[i], cmd_str, - session_name); - } else { - MSG("All PIDs %sed in session %s", + switch (item->type) { + case LTTNG_ID_ALL: + MSG("All %ss %sed in session %s", tracker_str, cmd_str, session_name); + break; + case LTTNG_ID_VALUE: + MSG("%s %i %sed in session %s", tracker_str, + item->value, cmd_str, + session_name); + break; + case LTTNG_ID_STRING: + MSG("%s '%s' %sed in session %s", tracker_str, + item->string, cmd_str, + session_name); + break; + default: + retval = CMD_ERROR; + goto end; } success = 1; } /* Mi */ if (writer) { - ret = mi_lttng_pid_target(writer, pid_list[i], 1); + ret = mi_lttng_id_target(writer, tracker_type, item, 1); if (ret) { retval = CMD_ERROR; goto end; @@ -297,8 +464,8 @@ enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_st } if (writer) { - /* Close targets element */ - ret = mi_lttng_writer_close_element(writer); + /* Close targets and tracker_id elements */ + ret = mi_lttng_close_multi_element(writer, 2); if (ret) { retval = CMD_ERROR; goto end; @@ -309,7 +476,7 @@ end: if (handle) { lttng_destroy_handle(handle); } - free(pid_list); + free_id_list(id_list); return retval; } @@ -326,6 +493,12 @@ const char *get_mi_element_command(enum cmd_type cmd_type) } } +static void print_err_duplicate(const char *type) +{ + ERR("The --%s option can only be used once. A list of comma-separated values can be specified.", + type); +} + /* * Add/remove tracker to/from session. */ @@ -357,8 +530,85 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, list_cmd_options(stdout, long_options); goto end; case OPT_SESSION: + break; case OPT_PID: - opt_pid = 1; + if (opt_pid.used) { + print_err_duplicate("pid"); + command_ret = CMD_ERROR; + goto end; + } + opt_pid.used = 1; + type_state = STATE_PID; + break; + case OPT_VPID: + if (opt_vpid.used) { + print_err_duplicate("vpid"); + command_ret = CMD_ERROR; + goto end; + } + opt_vpid.used = 1; + type_state = STATE_VPID; + break; + case OPT_UID: + if (opt_uid.used) { + print_err_duplicate("uid"); + command_ret = CMD_ERROR; + goto end; + } + opt_uid.used = 1; + type_state = STATE_UID; + break; + case OPT_VUID: + if (opt_vuid.used) { + print_err_duplicate("vuid"); + command_ret = CMD_ERROR; + goto end; + } + opt_vuid.used = 1; + type_state = STATE_VUID; + break; + case OPT_GID: + if (opt_gid.used) { + print_err_duplicate("gid"); + command_ret = CMD_ERROR; + goto end; + } + opt_gid.used = 1; + type_state = STATE_GID; + break; + case OPT_VGID: + if (opt_vgid.used) { + print_err_duplicate("vgid"); + command_ret = CMD_ERROR; + goto end; + } + opt_vgid.used = 1; + type_state = STATE_VGID; + break; + case OPT_ALL: + switch (type_state) { + case STATE_PID: + opt_pid.all = 1; + break; + case STATE_VPID: + opt_vpid.all = 1; + break; + case STATE_UID: + opt_uid.all = 1; + break; + case STATE_VUID: + opt_vuid.all = 1; + break; + case STATE_GID: + opt_gid.all = 1; + break; + case STATE_VGID: + opt_vgid.all = 1; + break; + default: + command_ret = CMD_ERROR; + goto end; + } break; default: command_ret = CMD_UNDEFINED; @@ -382,13 +632,6 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, session_name = opt_session_name; } - /* Currently only PID tracker is supported */ - if (!opt_pid) { - ERR("Please specify at least one tracker with its expected arguments"); - command_ret = CMD_ERROR; - goto end; - } - /* Mi check */ if (lttng_opt_mi) { writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); @@ -414,19 +657,66 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, command_ret = CMD_ERROR; goto end; } + + ret = mi_lttng_trackers_open(writer); + if (ret) { + goto end; + } } - command_ret = track_untrack_pid(cmd_type, - cmd_str, session_name, opt_pid_string, - opt_all, writer); - if (command_ret != CMD_SUCCESS) { - success = 0; + if (opt_pid.used) { + command_ret = track_untrack_id(cmd_type, cmd_str, session_name, + opt_pid.string, opt_pid.all, writer, + LTTNG_TRACKER_PID); + if (command_ret != CMD_SUCCESS) { + success = 0; + } + } + if (opt_vpid.used) { + command_ret = track_untrack_id(cmd_type, cmd_str, session_name, + opt_vpid.string, opt_vpid.all, writer, + LTTNG_TRACKER_VPID); + if (command_ret != CMD_SUCCESS) { + success = 0; + } + } + if (opt_uid.used) { + command_ret = track_untrack_id(cmd_type, cmd_str, session_name, + opt_uid.string, opt_uid.all, writer, + LTTNG_TRACKER_UID); + if (command_ret != CMD_SUCCESS) { + success = 0; + } + } + if (opt_vuid.used) { + command_ret = track_untrack_id(cmd_type, cmd_str, session_name, + opt_vuid.string, opt_vuid.all, writer, + LTTNG_TRACKER_VUID); + if (command_ret != CMD_SUCCESS) { + success = 0; + } + } + if (opt_gid.used) { + command_ret = track_untrack_id(cmd_type, cmd_str, session_name, + opt_gid.string, opt_gid.all, writer, + LTTNG_TRACKER_GID); + if (command_ret != CMD_SUCCESS) { + success = 0; + } + } + if (opt_vgid.used) { + command_ret = track_untrack_id(cmd_type, cmd_str, session_name, + opt_vgid.string, opt_vgid.all, writer, + LTTNG_TRACKER_VGID); + if (command_ret != CMD_SUCCESS) { + success = 0; + } } /* Mi closing */ if (writer) { - /* Close output element */ - ret = mi_lttng_writer_close_element(writer); + /* Close trackers and output elements */ + ret = mi_lttng_close_multi_element(writer, 2); if (ret) { command_ret = CMD_ERROR; goto end; diff --git a/src/common/mi-lttng-3.0.xsd b/src/common/mi-lttng-3.0.xsd index 1dee284de..218d5bd98 100644 --- a/src/common/mi-lttng-3.0.xsd +++ b/src/common/mi-lttng-3.0.xsd @@ -332,6 +332,14 @@ THE SOFTWARE. + + + + + + + + @@ -339,43 +347,232 @@ THE SOFTWARE. - - - - - + + + + + + + - - - - - + - + - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + @@ -688,7 +885,7 @@ THE SOFTWARE. - + diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index d95d38ffb..f884f9385 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -1540,13 +1540,58 @@ int mi_lttng_trackers_open(struct mi_writer *writer) return mi_lttng_writer_open_element(writer, config_element_trackers); } +static int get_tracker_elements(enum lttng_tracker_type tracker_type, + const char **element_id_tracker, + const char **element_target_id) +{ + int ret = 0; + + switch (tracker_type) { + case LTTNG_TRACKER_PID: + *element_id_tracker = config_element_pid_tracker; + *element_target_id = config_element_target_pid; + break; + case LTTNG_TRACKER_VPID: + *element_id_tracker = config_element_vpid_tracker; + *element_target_id = config_element_target_vpid; + break; + case LTTNG_TRACKER_UID: + *element_id_tracker = config_element_uid_tracker; + *element_target_id = config_element_target_uid; + break; + case LTTNG_TRACKER_VUID: + *element_id_tracker = config_element_vuid_tracker; + *element_target_id = config_element_target_vuid; + break; + case LTTNG_TRACKER_GID: + *element_id_tracker = config_element_gid_tracker; + *element_target_id = config_element_target_gid; + break; + case LTTNG_TRACKER_VGID: + *element_id_tracker = config_element_vgid_tracker; + *element_target_id = config_element_target_vgid; + break; + default: + ret = LTTNG_ERR_SAVE_IO_FAIL; + } + return ret; +} + LTTNG_HIDDEN -int mi_lttng_pid_tracker_open(struct mi_writer *writer) +int mi_lttng_id_tracker_open( + struct mi_writer *writer, enum lttng_tracker_type tracker_type) { int ret; + const char *element_id_tracker, *element_target_id; + + ret = get_tracker_elements( + tracker_type, &element_id_tracker, &element_target_id); + if (ret) { + return ret; + } - /* Open element pid_tracker */ - ret = mi_lttng_writer_open_element(writer, config_element_pid_tracker); + /* Open element $id_tracker */ + ret = mi_lttng_writer_open_element(writer, element_id_tracker); if (ret) { goto end; } @@ -1568,7 +1613,9 @@ int mi_lttng_pids_open(struct mi_writer *writer) * mi api bump. The use of process element break the mi api. */ LTTNG_HIDDEN -int mi_lttng_pid(struct mi_writer *writer, pid_t pid , const char *name, +int mi_lttng_pid(struct mi_writer *writer, + pid_t pid, + const char *name, int is_open) { int ret; @@ -1612,27 +1659,81 @@ int mi_lttng_targets_open(struct mi_writer *writer) } LTTNG_HIDDEN -int mi_lttng_pid_target(struct mi_writer *writer, pid_t pid, int is_open) +int mi_lttng_id_target(struct mi_writer *writer, + enum lttng_tracker_type tracker_type, + struct lttng_tracker_id *id, + int is_open) { int ret; + const char *element_id_tracker, *element_target_id; - ret = mi_lttng_writer_open_element(writer, - config_element_target_pid); + ret = get_tracker_elements( + tracker_type, &element_id_tracker, &element_target_id); if (ret) { - goto end; + return ret; } - /* Writing pid number - * Special case for element all on track untrack command - * All pid is represented as wildcard * - */ - if ((int) pid == -1) { - ret = mi_lttng_writer_write_element_string(writer, - config_element_pid, - mi_lttng_element_track_untrack_all_wildcard); - } else { - ret = mi_lttng_writer_write_element_signed_int(writer, - config_element_pid, (int) pid); + switch (id->type) { + case LTTNG_ID_ALL: + ret = mi_lttng_writer_open_element(writer, element_target_id); + if (ret) { + goto end; + } + ret = mi_lttng_writer_open_element(writer, config_element_type); + if (ret) { + goto end; + } + ret = mi_lttng_writer_write_element_bool( + writer, config_element_all, 1); + if (ret) { + goto end; + } + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto end; + } + break; + case LTTNG_ID_VALUE: + ret = mi_lttng_writer_open_element(writer, element_target_id); + if (ret) { + goto end; + } + ret = mi_lttng_writer_open_element(writer, config_element_type); + if (ret) { + goto end; + } + ret = mi_lttng_writer_write_element_signed_int( + writer, config_element_id, id->value); + if (ret) { + goto end; + } + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto end; + } + break; + case LTTNG_ID_STRING: + ret = mi_lttng_writer_open_element(writer, element_target_id); + if (ret) { + goto end; + } + ret = mi_lttng_writer_open_element(writer, config_element_type); + if (ret) { + goto end; + } + ret = mi_lttng_writer_write_element_string( + writer, config_element_name, id->string); + if (ret) { + goto end; + } + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto end; + } + break; + case LTTNG_ID_UNKNOWN: + ret = -LTTNG_ERR_INVALID; + goto end; } if (ret) { goto end; diff --git a/src/common/mi-lttng.h b/src/common/mi-lttng.h index 7f7e8b9f8..3ea6bc6d7 100644 --- a/src/common/mi-lttng.h +++ b/src/common/mi-lttng.h @@ -606,7 +606,7 @@ int mi_lttng_event_fields_open(struct mi_writer *writer); int mi_lttng_trackers_open(struct mi_writer *writer); /* - * Machine interface: open a pid_tracker element. + * Machine interface: open a id tracker element. * * writer An instance of a machine interface writer. * @@ -615,7 +615,8 @@ int mi_lttng_trackers_open(struct mi_writer *writer); * * Note: A targets element is also opened for each tracker definition */ -int mi_lttng_pid_tracker_open(struct mi_writer *writer); +int mi_lttng_id_tracker_open( + struct mi_writer *writer, enum lttng_tracker_type tracker_type); /* * Machine interface: open a PIDs element. @@ -684,14 +685,17 @@ int mi_lttng_pid(struct mi_writer *writer, pid_t pid , const char *name, int mi_lttng_targets_open(struct mi_writer *writer); /* - * Machine interface for track/untrack a pid_target + * Machine interface for track/untrack an id_target * * writer An instance of a machine interface writer. * * Returns zero if the element's value could be written. * Negative values indicate an error. */ -int mi_lttng_pid_target(struct mi_writer *writer, pid_t pid, int is_open); +int mi_lttng_id_target(struct mi_writer *writer, + enum lttng_tracker_type tracker_type, + struct lttng_tracker_id *id, + int is_open); /* * Machine interface of a context. diff --git a/tests/regression/tools/mi/extract_xml.c b/tests/regression/tools/mi/extract_xml.c index ae07689e2..eb1fc02b4 100644 --- a/tests/regression/tools/mi/extract_xml.c +++ b/tests/regression/tools/mi/extract_xml.c @@ -33,10 +33,11 @@ * node;b; * node;c; */ -#include +#include +#include #include +#include #include -#include #include #include @@ -47,9 +48,9 @@ #if defined(LIBXML_XPATH_ENABLED) - -int opt_verbose; -int node_exist; +static int opt_verbose; +static int node_exist; +static bool result = false; /** * print_xpath_nodes: @@ -86,7 +87,7 @@ static int print_xpath_nodes(xmlDocPtr doc, xmlNodeSetPtr nodes, FILE *output) node_child_value_string = xmlNodeListGetString(doc, cur->children, 1); if (node_exist) { - fprintf(output, "true\n"); + result = true; } else if (opt_verbose) { fprintf(output, "%s;%s;\n", cur->name, node_child_value_string); @@ -98,7 +99,7 @@ static int print_xpath_nodes(xmlDocPtr doc, xmlNodeSetPtr nodes, FILE *output) } else { /* We don't want to print non-final element */ if (node_exist) { - fprintf(output, "true\n"); + result = true; } else { fprintf(stderr, "ERR:%s\n", "Xpath expression return non-final xml element"); @@ -108,7 +109,7 @@ static int print_xpath_nodes(xmlDocPtr doc, xmlNodeSetPtr nodes, FILE *output) } } else { if (node_exist) { - fprintf(output, "true\n"); + result = true; } else { /* We don't want to print non-final element */ fprintf(stderr, "ERR:%s\n", @@ -121,7 +122,7 @@ static int print_xpath_nodes(xmlDocPtr doc, xmlNodeSetPtr nodes, FILE *output) } else { cur = nodes->nodeTab[i]; if (node_exist) { - fprintf(output, "true\n"); + result = true; } else if (opt_verbose) { fprintf(output, "%s;%s;\n", cur->parent->name, cur->content); } else { @@ -221,6 +222,9 @@ static int extract_xpath(const char *xml_path, const xmlChar *xpath) xmlFreeDoc(doc); return -1; } + if (node_exist && result) { + fprintf(stdout, "true\n"); + } /* Cleanup */ xmlXPathFreeObject(xpathObj); diff --git a/tests/regression/tools/mi/test_mi b/tests/regression/tools/mi/test_mi index 8ab91cfef..8eb049122 100755 --- a/tests/regression/tools/mi/test_mi +++ b/tests/regression/tools/mi/test_mi @@ -50,8 +50,8 @@ XPATH_LIST_UST_EVENT="$XPATH_CMD_OUTPUT/lttng:domains/lttng:domain[./lttng:type XPATH_SNAPSHOT_ADD_SNAPSHOT="$XPATH_CMD_OUTPUT/lttng:snapshot_action[./lttng:name = 'add-output']/lttng:output" XPATH_SNAPSHOT_LIST="$XPATH_CMD_OUTPUT/lttng:snapshot_action[./lttng:name = 'list-output']/lttng:output" XPATH_SNAPSHOT_DEL="$XPATH_CMD_OUTPUT/lttng:snapshot_action[./lttng:name = 'del-output']/lttng:output" -XPATH_TRACK_UNTRACK_PID="$XPATH_CMD_OUTPUT/lttng:targets/lttng:pid_target" -XPATH_PID_TRACKER="$XPATH_CMD_OUTPUT/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:pid_tracker" +XPATH_TRACK_UNTRACK_VPID="$XPATH_CMD_OUTPUT/lttng:trackers/lttng:vpid_tracker/lttng:targets/lttng:vpid_target/lttng:type" +XPATH_VPID_TRACKER="$XPATH_CMD_OUTPUT/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vpid_tracker" DEVNULL=/dev/null 2>&1 @@ -766,7 +766,7 @@ function test_track_untrack () ok $? "Mi test: track pid is a success" #Verify that there is 3 process - extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_PID"/lttng:pid" result + extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_VPID"/lttng:id" result num=$(echo "$result" | wc -l) test "$num" -eq "3" ok $? "Mi test: track pid expecting 3 processes got $num" @@ -777,7 +777,7 @@ function test_track_untrack () ok $? "Mi test: session list with pid_tracker validate" #Check the good count - extract_xml $OUTPUT_DEST $XPATH_PID_TRACKER"/lttng:targets/lttng:pid_target/lttng:pid" result + extract_xml $OUTPUT_DEST $XPATH_VPID_TRACKER"/lttng:targets/lttng:vpid_target/lttng:type/lttng:id" result num=$(echo "$result" | wc -l) test "$num" -eq "3" ok $? "Mi test: tracker pid listing expecting 3 target got $num" @@ -793,7 +793,7 @@ function test_track_untrack () ok $? "Mi test: untrack pid is a success" #Verify that there is 2 untracked pids - extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_PID"/lttng:pid" result + extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_VPID"/lttng:id" result num=$(echo "$result" | wc -l) test "$num" -eq "2" ok $? "Mi test: untrack pid expecting 2 process got $num" @@ -804,7 +804,7 @@ function test_track_untrack () ok $? "Mi test: session list with pid_tracker validate" #Check the good count - extract_xml $OUTPUT_DEST $XPATH_PID_TRACKER"/lttng:targets/lttng:pid_target/lttng:pid" result + extract_xml $OUTPUT_DEST $XPATH_VPID_TRACKER"/lttng:targets/lttng:vpid_target/lttng:type/lttng:pid" result num=$(echo "$result" | wc -l) test "$num" -eq "1" ok $? "Mi test: tracker pid listing expecting 1 process got $num" @@ -820,14 +820,14 @@ function test_track_untrack () ok $? "Mi test: untrack all pid is a success" #Verify that there is 1 untracked pid - extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_PID"/lttng:pid" result + extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_VPID"/lttng:all" result num=$(echo "$result" | wc -l) test "$num" -eq "1" ok $? "Mi test: untrack pid expecting 1 process got $num" - #Test if the id is * which represent the all argument - test "$result" = "*" - ok $? "Mi test: pid expected is * got $result" + #Test if type "all" is "true" which represent the all argument + test "$result" = "true" + ok $? "Mi test: pid expected is true got $result" #Test if pid_tracker is enabled as definied by pid_tracker #behavior. If all pid are untrack than the pid_tracker is still @@ -837,7 +837,7 @@ function test_track_untrack () ok $? "Mi test: session list with pid_tracker validate" #Check the good count - extract_xml $OUTPUT_DEST $XPATH_PID_TRACKER"/lttng:targets/lttng:pid_target/lttng:pid" result + extract_xml $OUTPUT_DEST $XPATH_VPID_TRACKER"/lttng:targets/lttng:vpid_target/lttng:type/lttng:pid" result num=$(echo -n "$result" | wc -l) test "$num" -eq "0" ok $? "Mi test: tracker pid listing expecting 0 process got $num" @@ -853,14 +853,14 @@ function test_track_untrack () ok $? "Mi test: track all pid is a success" #Verify that there is 1 tracked process - extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_PID"/lttng:pid" result + extract_xml $OUTPUT_DEST $XPATH_TRACK_UNTRACK_VPID"/lttng:all" result num=$(echo "$result" | wc -l) test "$num" -eq "1" ok $? "Mi test: track pid expecting 1 process got $num" - #Test if the id is * wich represent the all argument - test "$result" = "*" - ok $? "Mi test: pid expected is * got $result" + #Test if the id is true wich represent the all argument + test "$result" = "true" + ok $? "Mi test: pid expected is true got $result" #Test if pid_tracker is enabled as definied by pid_tracker #behavior. If all pid are untrack thant the pid_tracker is @@ -869,9 +869,9 @@ function test_track_untrack () $XML_VALIDATE $OUTPUT_DEST ok $? "Mi test: session list with pid_tracker validate" - node_check_xml $OUTPUT_DEST $XPATH_PID_TRACKER result + node_check_xml $OUTPUT_DEST $XPATH_VPID_TRACKER result test "$result" = "" - ok $? "Mi test: Pid_tracker node is absent as defined" + ok $? "Mi test: VPID_tracker node is absent as defined" OUTPUT_DEST=$DEVNULL destroy_lttng_sessions diff --git a/tests/regression/tools/save-load/load-42-trackers.lttng b/tests/regression/tools/save-load/load-42-trackers.lttng index 34082dfa0..2848f3209 100644 --- a/tests/regression/tools/save-load/load-42-trackers.lttng +++ b/tests/regression/tools/save-load/load-42-trackers.lttng @@ -32,10 +32,31 @@ + + + + 666 + + + + + + + 777 + + + + + + + 888 + + + - 666 + 999 diff --git a/tests/regression/tools/save-load/test_load b/tests/regression/tools/save-load/test_load index 5e38b46b6..1f1d01d25 100755 --- a/tests/regression/tools/save-load/test_load +++ b/tests/regression/tools/save-load/test_load @@ -27,7 +27,7 @@ EVENT_NAME="tp:tptest" DIR=$(readlink -f $TESTDIR) -NUM_TESTS=67 +NUM_TESTS=72 source $TESTDIR/utils/utils.sh @@ -140,19 +140,36 @@ function test_trackers() break; fi $TESTDIR/../src/bin/lttng/$LTTNG_BIN --mi XML list "$SESSION_NAME-trackers" > $mi_output_file - mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:pid_tracker/lttng:targets/lttng:pid_target") + mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vpid_tracker/lttng:targets/lttng:vpid_target") if [[ $mi_result = "true" ]]; then - ok 0 "Pid target is present" + ok 0 "VPID target is present" else - fail "Pid target missing" + fail "VPID target missing" + fi + + mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vuid_tracker/lttng:targets/lttng:vuid_target") + if [[ $mi_result = "true" ]]; then + ok 0 "VUID target is present" + else + fail "VUID target missing" + fi + + mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vgid_tracker/lttng:targets/lttng:vgid_target") + if [[ $mi_result = "true" ]]; then + ok 0 "VGID target is present" + else + fail "VGID target missing" fi # Test to remove the target just to make sure - lttng_untrack_ok "-p 666 -u -s $SESSION_NAME-trackers" - rm $mi_output_file + lttng_untrack_ok "--vpid 666 -u -s $SESSION_NAME-trackers" + lttng_untrack_ok "--vuid 777 -u -s $SESSION_NAME-trackers" + lttng_untrack_ok "--vgid 888 -u -s $SESSION_NAME-trackers" + # Actually using vpid (backward compat) + lttng_untrack_ok "--pid 999 -u -s $SESSION_NAME-trackers" destroy_lttng_session_ok "$SESSION_NAME-trackers" - rm -rf ${mi_output_file} + rm -f ${mi_output_file} } function test_override_url_normal() -- 2.34.1