/*
- * Copyright (C) 2011-2012 Julien Desfossez
+ * Copyright (C) 2013 Julien Desfossez
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 2 as
#include "common.h"
#include "network-live.h"
-#include "lttng-index.h"
+#define NET_URL_PREFIX "net://"
+#define NET4_URL_PREFIX "net4://"
+#define NET6_URL_PREFIX "net6://"
#define DEFAULT_FILE_ARRAY_SIZE 1
const char *opt_input_path;
-static int opt_textdump;
-static int opt_child;
+int opt_textdump;
+int opt_child;
+int opt_begin;
int quit = 0;
unsigned long refresh_display = 1 * NSEC_PER_SEC;
unsigned long last_display_update = 0;
+unsigned long last_event_ts = 0;
/* list of FDs available for being read with snapshots */
struct bt_mmap_stream_list mmap_list;
OPT_HOSTNAME,
OPT_RELAY_HOSTNAME,
OPT_KPROBES,
+ OPT_BEGIN,
};
static struct poptOption long_options[] = {
{ "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
{ "textdump", 't', POPT_ARG_NONE, NULL, OPT_TEXTDUMP, NULL, NULL },
{ "child", 'f', POPT_ARG_NONE, NULL, OPT_CHILD, NULL, NULL },
+ { "begin", 'b', POPT_ARG_NONE, NULL, OPT_BEGIN, NULL, NULL },
{ "pid", 'p', POPT_ARG_STRING, &opt_tid, OPT_PID, NULL, NULL },
{ "hostname", 'n', POPT_ARG_STRING, &opt_hostname, OPT_HOSTNAME, NULL, NULL },
{ "relay-hostname", 'r', POPT_ARG_STRING, &opt_relay_hostname,
{ NULL, 0, 0, NULL, 0, NULL, NULL },
};
+#ifdef LTTNGTOP_MMAP_LIVE
static void handle_textdump_sigterm(int signal)
{
quit = 1;
lttng_destroy_session("test");
}
+#endif
void *refresh_thread(void *p)
{
timestamp = bt_ctf_get_timestamp(call_data);
+ /* can happen in network live when tracing is idle */
+ if (timestamp < last_event_ts)
+ goto end_stop;
+
+ last_event_ts = timestamp;
+
start = format_timestamp(timestamp);
ts_nsec_start = timestamp % NSEC_PER_SEC;
return BT_CB_OK;
error:
return BT_CB_ERROR_STOP;
+end_stop:
+ return BT_CB_OK_STOP;
}
enum bt_cb_ret handle_kprobes(struct bt_ctf_event *call_data, void *private_data)
if (timestamp == -1ULL)
goto error;
+ /* can happen in network live when tracing is idle */
+ if (timestamp < last_event_ts)
+ goto end_stop;
+
+ last_event_ts = timestamp;
+
if (last_display_update == 0)
last_display_update = timestamp;
error:
fprintf(stderr, "check_timestamp callback error\n");
return BT_CB_ERROR_STOP;
+
+end_stop:
+ return BT_CB_OK_STOP;
}
/*
void usage(FILE *fp)
{
fprintf(fp, "LTTngTop %s\n\n", VERSION);
- fprintf(fp, "Usage : lttngtop [OPTIONS] [TRACE]\n");
- fprintf(fp, " TRACE Path to the trace to analyse (no trace path for live tracing)\n");
+ fprintf(fp, "Usage : lttngtop [OPTIONS] TRACE\n");
+ fprintf(fp, " TRACE Path to the trace to analyse (-r for network live tracing, nothing for mmap live streaming)\n");
fprintf(fp, " -h, --help This help message\n");
fprintf(fp, " -t, --textdump Display live events in text-only\n");
fprintf(fp, " -p, --pid Comma-separated list of PIDs to display\n");
fprintf(fp, " -f, --child Follow threads associated with selected PIDs\n");
fprintf(fp, " -n, --hostname Comma-separated list of hostnames to display (require hostname context in trace)\n");
fprintf(fp, " -k, --kprobes Comma-separated list of kprobes to insert (same format as lttng enable-event)\n");
+ fprintf(fp, " -r, --relay-hostname Network live streaming : hostname of the lttng-relayd (default port)\n");
+ fprintf(fp, " -b, --begin Network live streaming : read the trace for the beginning of the recording\n");
}
/*
tmp_str = strtok(NULL, ",");
}
break;
+ case OPT_BEGIN:
+ /* start reading the live trace from the beginning */
+ opt_begin = 1;
+ break;
case OPT_HOSTNAME:
toggle_filter = 1;
tmp_str = strtok(opt_hostname, ",");
char * const paths[2] = { lpath, NULL };
int ret = -1;
+ if ((strncmp(path, NET4_URL_PREFIX, sizeof(NET4_URL_PREFIX) - 1)) == 0 ||
+ (strncmp(path, NET6_URL_PREFIX, sizeof(NET6_URL_PREFIX) - 1)) == 0 ||
+ (strncmp(path, NET_URL_PREFIX, sizeof(NET_URL_PREFIX) - 1)) == 0) {
+ ret = bt_context_add_trace(ctx,
+ path, format_str, packet_seek, NULL, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "[warning] [Context] cannot open trace \"%s\" "
+ "for reading.\n", path);
+ /* Allow to skip erroneous traces. */
+ ret = 1; /* partial error */
+ }
+ return ret;
+ }
/*
* Need to copy path, because fts_open can change it.
* It is the pointer array, not the strings, that are constant.
metafd = openat(dirfd, "metadata", O_RDONLY);
if (metafd < 0) {
close(dirfd);
- ret = -1;
continue;
} else {
int trace_id;
exit(EXIT_SUCCESS);
}
- if (!opt_input_path) {
+ if (!opt_input_path && !remote_live) {
+ /* mmap live */
+#ifdef LTTNGTOP_MMAP_LIVE
if (opt_textdump) {
signal(SIGTERM, handle_textdump_sigterm);
signal(SIGINT, handle_textdump_sigterm);
}
- if (remote_live) {
- ret = setup_network_live(opt_relay_hostname);
- if (ret < 0) {
- goto end;
- }
- }
+ mmap_live_loop(bt_ctx);
+ pthread_join(timer_thread, NULL);
+ quit = 1;
+ pthread_join(display_thread, NULL);
- if (!opt_textdump) {
- pthread_create(&display_thread, NULL, ncurses_display, (void *) NULL);
- pthread_create(&timer_thread, NULL, refresh_thread, (void *) NULL);
- }
+ lttng_stop_tracing("test");
+ lttng_destroy_session("test");
- ret = open_trace(&bt_ctx);
+ goto end;
+#else
+ fprintf(stderr, "[ERROR] Mmap live support not compiled, specify a "
+ "trace directory or -r <relayd hostname/IP>\n");
+ usage(stdout);
+ ret = -1;
+ goto end;
+#endif /* LTTNGTOP_MMAP_LIVE */
+ } else if (!opt_input_path && remote_live) {
+ /* network live */
+#if 0
+ ret = setup_network_live(opt_relay_hostname, opt_begin);
if (ret < 0) {
goto end;
}
- ret = check_requirements(bt_ctx);
+ ret = open_trace(&bt_ctx);
if (ret < 0) {
- fprintf(stderr, "[error] some mandatory contexts were missing, exiting.\n");
goto end;
}
-
- iter_trace(bt_ctx);
-
-#ifdef LTTNGTOP_MMAP_LIVE
- mmap_live_loop(bt_ctx);
#endif
- pthread_join(timer_thread, NULL);
- quit = 1;
- pthread_join(display_thread, NULL);
-
- lttng_stop_tracing("test");
- lttng_destroy_session("test");
-
- goto end;
+ bt_ctx = bt_context_create();
+ ret = bt_context_add_traces_recursive(bt_ctx, opt_relay_hostname,
+ "lttng-live", NULL);
+ if (ret < 0) {
+ fprintf(stderr, "[error] Opening the trace\n");
+ goto end;
+ }
} else {
//init_lttngtop();
ret = check_requirements(bt_ctx);
if (ret < 0) {
- fprintf(stderr, "[error] some mandatory contexts were missing, exiting.\n");
+ fprintf(stderr, "[error] some mandatory contexts "
+ "were missing, exiting.\n");
goto end;
}
- pthread_create(&display_thread, NULL, ncurses_display, (void *) NULL);
- pthread_create(&timer_thread, NULL, refresh_thread, (void *) NULL);
- iter_trace(bt_ctx);
+ if (!opt_textdump) {
+ pthread_create(&display_thread, NULL, ncurses_display,
+ (void *) NULL);
+ pthread_create(&timer_thread, NULL, refresh_thread,
+ (void *) NULL);
+ }
- pthread_join(display_thread, NULL);
- quit = 1;
- pthread_join(timer_thread, NULL);
+ iter_trace(bt_ctx);
}
+
+ pthread_join(display_thread, NULL);
+ quit = 1;
+ pthread_join(timer_thread, NULL);
+
+ ret = 0;
+
end:
if (bt_ctx)
bt_context_put(bt_ctx);
- return 0;
+ return ret;
}