struct list_head list;
};
-static void print_markers(void)
+static void print_markers(FILE *fp)
{
struct marker_iter iter;
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();
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");
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";
ERR("ltt_trace_start failed");
return;
}
- //start_consumer();
inform_consumer_daemon();
}
#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; i<argc; i++) {
+ opts->pids[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;
}