From 52c51a47e4b002d741c89de8dc786da59e894a1a Mon Sep 17 00:00:00 2001 From: Pierre-Marc Fournier Date: Tue, 5 May 2009 16:36:22 -0400 Subject: [PATCH] add feature to enable/disable markers --- libust/tracectl.c | 84 +++++++++++++++++++- libustcomm/ustcomm.c | 26 +++++-- ust/ust.c | 179 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 245 insertions(+), 44 deletions(-) diff --git a/libust/tracectl.c b/libust/tracectl.c index 2101d5c..b3dd4c2 100644 --- a/libust/tracectl.c +++ b/libust/tracectl.c @@ -68,7 +68,7 @@ struct blocked_consumer { struct list_head list; }; -static void print_markers(void) +static void print_markers(FILE *fp) { struct marker_iter iter; @@ -77,7 +77,7 @@ static void print_markers(void) marker_iter_start(&iter); while(iter.marker) { - fprintf(stderr, "marker: %s_%s \"%s\"\n", iter.marker->channel, iter.marker->name, iter.marker->format); + fprintf(fp, "marker: %s_%s %d \"%s\"\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format); marker_iter_next(&iter); } unlock_markers(); @@ -232,7 +232,48 @@ int listener_main(void *p) len = strlen(recvbuf); if(!strcmp(recvbuf, "print_markers")) { - print_markers(); + print_markers(stderr); + } + else if(!strcmp(recvbuf, "list_markers")) { + char *ptr; + size_t size; + FILE *fp; + + fp = open_memstream(&ptr, &size); + print_markers(fp); + fclose(fp); + + result = ustcomm_send_reply(&ustcomm_app.server, ptr, &src); + + free(ptr); + } + else if(!strcmp(recvbuf, "start")) { + /* start is an operation that setups the trace, allocates it and starts it */ + result = ltt_trace_setup(trace_name); + if(result < 0) { + ERR("ltt_trace_setup failed"); + return; + } + + result = ltt_trace_set_type(trace_name, trace_type); + if(result < 0) { + ERR("ltt_trace_set_type failed"); + return; + } + + result = ltt_trace_alloc(trace_name); + if(result < 0) { + ERR("ltt_trace_alloc failed"); + return; + } + + inform_consumer_daemon(); + + result = ltt_trace_start(trace_name); + if(result < 0) { + ERR("ltt_trace_start failed"); + continue; + } } else if(!strcmp(recvbuf, "trace_setup")) { DBG("trace setup"); @@ -551,6 +592,42 @@ int listener_main(void *p) free(channel_name); free(consumed_old_str); } + else if(nth_token_is(recvbuf, "enable_marker", 0) == 1) { + char *channel_slash_name = nth_token(recvbuf, 1); + char channel_name[256]=""; + char marker_name[256]=""; + struct marker_iter iter; + + result = sscanf(channel_slash_name, "%255[^/]/%255s", channel_name, marker_name); + + if(channel_name == NULL || marker_name == NULL) { + WARN("invalid marker name"); + goto next_cmd; + } + printf("%s %s\n", channel_name, marker_name); + + result = ltt_marker_connect(channel_name, marker_name, "default"); + if(result < 0) { + WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name); + } + } + else if(nth_token_is(recvbuf, "disable_marker", 0) == 1) { + char *channel_slash_name = nth_token(recvbuf, 1); + char *marker_name; + char *channel_name; + struct marker_iter iter; + + result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name); + + if(marker_name == NULL) { + } + printf("%s %s\n", channel_name, marker_name); + + result = ltt_marker_disconnect(channel_name, marker_name, "default"); + if(result < 0) { + WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name); + } + } // else if(nth_token_is(recvbuf, "get_notifications", 0) == 1) { // struct ltt_trace_struct *trace; // char trace_name[] = "auto"; @@ -780,7 +857,6 @@ static void __attribute__((constructor(1000))) init() ERR("ltt_trace_start failed"); return; } - //start_consumer(); inform_consumer_daemon(); } diff --git a/libustcomm/ustcomm.c b/libustcomm/ustcomm.c index e191183..004cdb0 100644 --- a/libustcomm/ustcomm.c +++ b/libustcomm/ustcomm.c @@ -49,18 +49,20 @@ char *strdup_malloc(const char *s) return retval; } -static void signal_process(pid_t pid) +static int signal_process(pid_t pid) { int result; result = kill(pid, UST_SIGNAL); if(result == -1) { PERROR("kill"); - return; + return -1; } /* FIXME: should wait in a better way */ - sleep(1); + //sleep(1); + + return 0; } static int send_message_fd(int fd, const char *msg) @@ -113,8 +115,13 @@ static int send_message_path(const char *path, const char *msg, int signalpid) return -1; } - if(signalpid >= 0) - signal_process(signalpid); + if(signalpid >= 0) { + result = signal_process(signalpid); + if(result == -1) { + ERR("could not signal process"); + return -1; + } + } result = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); if(result == -1) { @@ -438,8 +445,13 @@ int ustcomm_connect_path(char *path, struct ustcomm_connection *conn, pid_t sign return -1; } - if(signalpid >= 0) - signal_process(signalpid); + if(signalpid >= 0) { + result = signal_process(signalpid); + if(result == -1) { + ERR("could not signal process"); + return -1; + } + } result = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); if(result == -1) { diff --git a/ust/ust.c b/ust/ust.c index 3f6bf1d..2f7a6bd 100644 --- a/ust/ust.c +++ b/ust/ust.c @@ -6,55 +6,168 @@ #include "ustcomm.h" -void parse_opts(int argc, char **argv) +struct ust_opts { + char *cmd; + pid_t *pids; + int take_reply; +}; + +int parse_opts_long(int argc, char **argv, struct ust_opts *opts) { - int flags, opt; - int nsecs, tfnd; - - nsecs = 0; - tfnd = 0; - flags = 0; - while ((opt = getopt(argc, argv, "nt:")) != -1) { - switch (opt) { - case 'n': - flags = 1; - break; - case 't': - nsecs = atoi(optarg); - tfnd = 1; - break; - default: /* '?' */ - fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n", - argv[0]); - exit(EXIT_FAILURE); + int c; + int digit_optind = 0; + + opts->cmd = NULL; + opts->pids = NULL; + opts->take_reply = 0; + + while (1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"start-trace", 0, 0, 1000}, + {"stop-trace", 0, 0, 1001}, + {"destroy-trace", 0, 0, 1002}, + {"list-markers", 0, 0, 1004}, + {"print-markers", 0, 0, 1005}, + {"pid", 1, 0, 1006}, + {"enable-marker", 1, 0, 1007}, + {"disable-marker", 1, 0, 1008}, + {"start", 0, 0, 1009}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + printf("option %s", long_options[option_index].name); + if (optarg) + printf(" with arg %s", optarg); + printf("\n"); + break; + + case 1000: + opts->cmd = strdup("trace_start"); + break; + case 1001: + opts->cmd = strdup("trace_stop"); + break; + case 1009: + opts->cmd = strdup("start"); + break; + case 1002: + opts->cmd = strdup("trace_destroy"); + break; + case 1004: + opts->cmd = strdup("list_markers"); + opts->take_reply = 1; + break; + case 1007: + asprintf(&opts->cmd, "enable_marker %s", optarg); + break; + case 1008: + asprintf(&opts->cmd, "disable_marker %s", optarg); + break; + + default: + /* unknown option or other error; error is printed by getopt, just return */ + return 1; } } - printf("flags=%d; tfnd=%d; optind=%d\n", flags, tfnd, optind); + if(argc - optind > 0) { + int i; + int pididx=0; + opts->pids = malloc((argc-optind+1) * sizeof(pid_t)); - if (optind >= argc) { - fprintf(stderr, "Expected argument after options\n"); - exit(EXIT_FAILURE); + for(i=optind; ipids[pididx++] = atoi(argv[i]); + } + opts->pids[pididx] = -1; } - printf("name argument = %s\n", argv[optind]); - - /* Other code omitted */ + return 0; +} - exit(EXIT_SUCCESS); +char *progname = NULL; +void usage(void) +{ + fprintf(stderr, "usage: %s [OPTIONS] OPERATION PID...\n", progname); + fprintf(stderr, "\nControl the tracing of a process that supports LTTng Userspace Tracing.\n\ +\n\ +Operations:\n\ +\t--start-trace\tStart tracing\n\ +\t--stop-trace\tStop tracing\n\ +\t--destroy-trace\tDestroy the trace\n\ +\t--enable-marker CHANNEL_NAME/MARKER_NAME\tEnable a marker\n\ +\t--disable-marker CHANNEL_NAME/MARKER_NAME\tDisable a marker\n\ +\t--list-markers\tList the markers of the process and their state\n\ +\n\ +"); } int main(int argc, char *argv[]) { - pid_t pid = atoi(argv[1]); + pid_t *pidit; + //char *msg = argv[2]; + struct ustcomm_connection conn; + int result; + struct ust_opts opts; - char *msg = argv[2]; + progname = argv[0]; - struct ustcomm_connection conn; + if(argc <= 1) { + fprintf(stderr, "No operation specified.\n"); + usage(); + exit(EXIT_FAILURE); + } + + result = parse_opts_long(argc, argv, &opts); + if(result) { + usage(); + exit(EXIT_FAILURE); + } + + if(opts.pids == NULL) { + fprintf(stderr, "No pid specified.\n"); + usage(); + exit(EXIT_FAILURE); + } + if(opts.cmd == NULL) { + fprintf(stderr, "No command specified.\n"); + usage(); + exit(EXIT_FAILURE); + } + + pidit = opts.pids; + + while(*pidit != -1) { + char *reply; + char **preply; + + if(opts.take_reply) + preply = &reply; + else + preply = NULL; + + result = ustcomm_connect_app(*pidit, &conn); + if(result) { + fprintf(stderr, "error connecting to process\n"); + exit(EXIT_FAILURE); + } + ustcomm_send_request(&conn, opts.cmd, preply); + + if(opts.take_reply) + printf("%s", reply); + pidit++; + } - ustcomm_connect_app(pid, &conn); - ustcomm_send_request(&conn, msg, NULL); + free(opts.pids); + free(opts.cmd); return 0; } -- 2.34.1