From cf0bcb51ea857687a353d2851e572dba6cc63cb0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Thu, 4 May 2017 23:53:50 -0400 Subject: [PATCH] Expose monitor timer interval to lttngctl and client MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérémie Galarneau --- include/lttng/channel.h | 14 ++ src/bin/lttng-sessiond/cmd.c | 18 ++- src/bin/lttng/commands/enable_channels.c | 178 +++++++++++++++-------- src/bin/lttng/commands/list.c | 10 +- src/common/config/config-session-abi.h | 1 + src/common/config/session-config.c | 1 + src/common/consumer/consumer-testpoint.h | 1 + src/common/consumer/consumer.c | 5 + src/common/consumer/consumer.h | 4 + src/common/kernel-ctl/kernel-ioctl.h | 2 +- src/common/mi-lttng-3.0.xsd | 1 + src/common/mi-lttng.c | 16 +- src/lib/lttng-ctl/lttng-ctl.c | 156 +++++++++++++++++++- 13 files changed, 332 insertions(+), 75 deletions(-) diff --git a/include/lttng/channel.h b/include/lttng/channel.h index 732074c3a..e20ed4f4f 100644 --- a/include/lttng/channel.h +++ b/include/lttng/channel.h @@ -68,6 +68,14 @@ struct lttng_channel { char padding[LTTNG_CHANNEL_PADDING1]; }; +/* + */ +extern struct lttng_channel *lttng_channel_create(struct lttng_domain *domain); + +/* + */ +extern void lttng_channel_destroy(struct lttng_channel *channel); + /* * List the channel(s) of a session. * @@ -124,6 +132,12 @@ extern int lttng_channel_get_discarded_event_count(struct lttng_channel *chan, extern int lttng_channel_get_lost_packet_count(struct lttng_channel *chan, uint64_t *lost_packets); +extern int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan, + uint64_t *monitor_timer_interval); + +extern int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan, + uint64_t monitor_timer_interval); + #ifdef __cplusplus } #endif diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 5e146931e..7b9647436 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -245,7 +245,7 @@ end: */ static void list_lttng_channels(enum lttng_domain_type domain, struct ltt_session *session, struct lttng_channel *channels, - struct lttcomm_channel_extended *chan_exts) + struct lttng_channel_extended *chan_exts) { int i = 0, ret; struct ltt_kernel_channel *kchan; @@ -259,6 +259,10 @@ static void list_lttng_channels(enum lttng_domain_type domain, cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head, list) { uint64_t discarded_events, lost_packets; + struct lttng_channel_extended *extended; + + extended = (struct lttng_channel_extended *) + kchan->channel->attr.extended.ptr; ret = get_kernel_runtime_stats(session, kchan, &discarded_events, &lost_packets); @@ -271,6 +275,8 @@ static void list_lttng_channels(enum lttng_domain_type domain, chan_exts[i].discarded_events = discarded_events; chan_exts[i].lost_packets = lost_packets; + chan_exts[i].monitor_timer_interval = + extended->monitor_timer_interval; i++; } } @@ -323,6 +329,8 @@ static void list_lttng_channels(enum lttng_domain_type domain, } chan_exts[i].discarded_events = discarded_events; chan_exts[i].lost_packets = lost_packets; + chan_exts[i].monitor_timer_interval = + uchan->monitor_timer_interval; i++; } rcu_read_unlock(); @@ -1681,7 +1689,7 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain, free(attr); goto error; } - free(attr); + channel_attr_destroy(attr); chan_ust_created = 1; } @@ -2179,7 +2187,7 @@ error: free(filter_expression); free(filter); free(exclusion); - free(attr); + channel_attr_destroy(attr); rcu_read_unlock(); return ret; } @@ -2948,8 +2956,8 @@ ssize_t cmd_list_channels(enum lttng_domain_type domain, if (nb_chan > 0) { const size_t channel_size = sizeof(struct lttng_channel) + - sizeof(struct lttcomm_channel_extended); - struct lttcomm_channel_extended *channel_exts; + sizeof(struct lttng_channel_extended); + struct lttng_channel_extended *channel_exts; payload_size = nb_chan * channel_size; *channels = zmalloc(payload_size); diff --git a/src/bin/lttng/commands/enable_channels.c b/src/bin/lttng/commands/enable_channels.c index 9a990030d..fa8513e72 100644 --- a/src/bin/lttng/commands/enable_channels.c +++ b/src/bin/lttng/commands/enable_channels.c @@ -35,15 +35,19 @@ #include "../utils.h" +static struct lttng_channel chan_opts; static char *opt_channels; static int opt_kernel; static char *opt_session_name; static int opt_userspace; -static struct lttng_channel chan; static char *opt_output; static int opt_buffer_uid; static int opt_buffer_pid; static int opt_buffer_global; +static struct { + bool set; + uint32_t interval; +} opt_monitor_timer; static struct mi_writer *writer; @@ -54,6 +58,7 @@ enum { OPT_SUBBUF_SIZE, OPT_NUM_SUBBUF, OPT_SWITCH_TIMER, + OPT_MONITOR_TIMER, OPT_READ_TIMER, OPT_USERSPACE, OPT_LIST_OPTIONS, @@ -77,6 +82,7 @@ static struct poptOption long_options[] = { {"subbuf-size", 0, POPT_ARG_STRING, 0, OPT_SUBBUF_SIZE, 0, 0}, {"num-subbuf", 0, POPT_ARG_INT, 0, OPT_NUM_SUBBUF, 0, 0}, {"switch-timer", 0, POPT_ARG_INT, 0, OPT_SWITCH_TIMER, 0, 0}, + {"monitor-timer", 0, POPT_ARG_INT, 0, OPT_MONITOR_TIMER, 0, 0}, {"read-timer", 0, POPT_ARG_INT, 0, OPT_READ_TIMER, 0, 0}, {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL}, {"output", 0, POPT_ARG_STRING, &opt_output, 0, 0, 0}, @@ -99,29 +105,29 @@ static void set_default_attr(struct lttng_domain *dom) /* Set attributes */ lttng_channel_set_default_attr(dom, &default_attr); - if (chan.attr.overwrite == -1) { - chan.attr.overwrite = default_attr.overwrite; + if (chan_opts.attr.overwrite == -1) { + chan_opts.attr.overwrite = default_attr.overwrite; } - if (chan.attr.subbuf_size == -1) { - chan.attr.subbuf_size = default_attr.subbuf_size; + if (chan_opts.attr.subbuf_size == -1) { + chan_opts.attr.subbuf_size = default_attr.subbuf_size; } - if (chan.attr.num_subbuf == -1) { - chan.attr.num_subbuf = default_attr.num_subbuf; + if (chan_opts.attr.num_subbuf == -1) { + chan_opts.attr.num_subbuf = default_attr.num_subbuf; } - if (chan.attr.switch_timer_interval == -1) { - chan.attr.switch_timer_interval = default_attr.switch_timer_interval; + if (chan_opts.attr.switch_timer_interval == -1) { + chan_opts.attr.switch_timer_interval = default_attr.switch_timer_interval; } - if (chan.attr.read_timer_interval == -1) { - chan.attr.read_timer_interval = default_attr.read_timer_interval; + if (chan_opts.attr.read_timer_interval == -1) { + chan_opts.attr.read_timer_interval = default_attr.read_timer_interval; } - if ((int) chan.attr.output == -1) { - chan.attr.output = default_attr.output; + if ((int) chan_opts.attr.output == -1) { + chan_opts.attr.output = default_attr.output; } - if (chan.attr.tracefile_count == -1) { - chan.attr.tracefile_count = default_attr.tracefile_count; + if (chan_opts.attr.tracefile_count == -1) { + chan_opts.attr.tracefile_count = default_attr.tracefile_count; } - if (chan.attr.tracefile_size == -1) { - chan.attr.tracefile_size = default_attr.tracefile_size; + if (chan_opts.attr.tracefile_size == -1) { + chan_opts.attr.tracefile_size = default_attr.tracefile_size; } } @@ -130,6 +136,7 @@ static void set_default_attr(struct lttng_domain *dom) */ static int enable_channel(char *session_name) { + struct lttng_channel *channel = NULL; int ret = CMD_SUCCESS, warn = 0, error = 0, success = 0; char *channel_name; struct lttng_domain dom; @@ -164,26 +171,26 @@ static int enable_channel(char *session_name) set_default_attr(&dom); - if (chan.attr.tracefile_size == 0 && chan.attr.tracefile_count) { + if (chan_opts.attr.tracefile_size == 0 && chan_opts.attr.tracefile_count) { ERR("Missing option --tracefile-size. " "A file count without a size won't do anything."); ret = CMD_ERROR; goto error; } - if ((chan.attr.tracefile_size > 0) && - (chan.attr.tracefile_size < chan.attr.subbuf_size)) { + if ((chan_opts.attr.tracefile_size > 0) && + (chan_opts.attr.tracefile_size < chan_opts.attr.subbuf_size)) { WARN("Tracefile size rounded up from (%" PRIu64 ") to subbuffer size (%" PRIu64 ")", - chan.attr.tracefile_size, chan.attr.subbuf_size); - chan.attr.tracefile_size = chan.attr.subbuf_size; + chan_opts.attr.tracefile_size, chan_opts.attr.subbuf_size); + chan_opts.attr.tracefile_size = chan_opts.attr.subbuf_size; } /* Setting channel output */ if (opt_output) { if (!strncmp(output_mmap, opt_output, strlen(output_mmap))) { - chan.attr.output = LTTNG_EVENT_MMAP; + chan_opts.attr.output = LTTNG_EVENT_MMAP; } else if (!strncmp(output_splice, opt_output, strlen(output_splice))) { - chan.attr.output = LTTNG_EVENT_SPLICE; + chan_opts.attr.output = LTTNG_EVENT_SPLICE; } else { ERR("Unknown output type %s. Possible values are: %s, %s\n", opt_output, output_mmap, output_splice); @@ -211,20 +218,46 @@ static int enable_channel(char *session_name) /* Strip channel list (format: chan1,chan2,...) */ channel_name = strtok(opt_channels, ","); while (channel_name != NULL) { + void *extended_ptr; + /* Validate channel name's length */ if (strlen(channel_name) >= NAME_MAX) { ERR("Channel name is too long (max. %zu characters)", - sizeof(chan.name) - 1); + sizeof(chan_opts.name) - 1); error = 1; goto skip_enable; } + /* + * A dynamically-allocated channel is used in order to allow + * the configuration of extended attributes (post-2.9). + */ + channel = lttng_channel_create(&dom); + if (!channel) { + ERR("Unable to create channel object"); + error = 1; + goto error; + } + /* Copy channel name */ - strcpy(chan.name, channel_name); + strcpy(channel->name, channel_name); + channel->enabled = 1; + extended_ptr = channel->attr.extended.ptr; + memcpy(&channel->attr, &chan_opts.attr, sizeof(chan_opts.attr)); + channel->attr.extended.ptr = extended_ptr; + if (opt_monitor_timer.set) { + ret = lttng_channel_set_monitor_timer_interval(channel, + opt_monitor_timer.interval); + if (ret) { + ERR("Failed to set the channel's monitor timer interval"); + error = 1; + goto error; + } + } DBG("Enabling channel %s", channel_name); - ret = lttng_enable_channel(handle, &chan); + ret = lttng_enable_channel(handle, channel); if (ret < 0) { success = 0; switch (-ret) { @@ -256,7 +289,7 @@ static int enable_channel(char *session_name) skip_enable: if (lttng_opt_mi) { /* Mi print the channel element and leave it open */ - ret = mi_lttng_channel(writer, &chan, 1); + ret = mi_lttng_channel(writer, channel, 1); if (ret) { ret = CMD_ERROR; goto error; @@ -280,6 +313,8 @@ skip_enable: /* Next channel */ channel_name = strtok(NULL, ","); + lttng_channel_destroy(channel); + channel = NULL; } if (lttng_opt_mi) { @@ -294,6 +329,9 @@ skip_enable: ret = CMD_SUCCESS; error: + if (channel) { + lttng_channel_destroy(channel); + } /* If more important error happen bypass the warning */ if (!ret && warn) { ret = CMD_WARNING; @@ -317,8 +355,8 @@ static void init_channel_config(void) * Put -1 everywhere so we can identify those set by the command line and * those needed to be set by the default values. */ - memset(&chan.attr, -1, sizeof(chan.attr)); - chan.attr.extended.ptr = NULL; + memset(&chan_opts.attr, -1, sizeof(chan_opts.attr)); + chan_opts.attr.extended.ptr = NULL; } /* @@ -342,11 +380,11 @@ int cmd_enable_channels(int argc, const char **argv) SHOW_HELP(); goto end; case OPT_DISCARD: - chan.attr.overwrite = 0; + chan_opts.attr.overwrite = 0; DBG("Channel set to discard"); break; case OPT_OVERWRITE: - chan.attr.overwrite = 1; + chan_opts.attr.overwrite = 1; DBG("Channel set to overwrite"); break; case OPT_SUBBUF_SIZE: @@ -356,32 +394,32 @@ int cmd_enable_channels(int argc, const char **argv) /* Parse the size */ opt_arg = poptGetOptArg(pc); - if (utils_parse_size_suffix(opt_arg, &chan.attr.subbuf_size) < 0 || !chan.attr.subbuf_size) { + if (utils_parse_size_suffix(opt_arg, &chan_opts.attr.subbuf_size) < 0 || !chan_opts.attr.subbuf_size) { ERR("Wrong value in --subbuf-size parameter: %s", opt_arg); ret = CMD_ERROR; goto end; } - order = get_count_order_u64(chan.attr.subbuf_size); + order = get_count_order_u64(chan_opts.attr.subbuf_size); assert(order >= 0); rounded_size = 1ULL << order; - if (rounded_size < chan.attr.subbuf_size) { + if (rounded_size < chan_opts.attr.subbuf_size) { ERR("The subbuf size (%" PRIu64 ") is rounded and overflows!", - chan.attr.subbuf_size); + chan_opts.attr.subbuf_size); ret = CMD_ERROR; goto end; } - if (rounded_size != chan.attr.subbuf_size) { + if (rounded_size != chan_opts.attr.subbuf_size) { WARN("The subbuf size (%" PRIu64 ") is rounded to the next power of 2 (%" PRIu64 ")", - chan.attr.subbuf_size, rounded_size); - chan.attr.subbuf_size = rounded_size; + chan_opts.attr.subbuf_size, rounded_size); + chan_opts.attr.subbuf_size = rounded_size; } /* Should now be power of 2 */ - assert(!((chan.attr.subbuf_size - 1) & chan.attr.subbuf_size)); + assert(!((chan_opts.attr.subbuf_size - 1) & chan_opts.attr.subbuf_size)); - DBG("Channel subbuf size set to %" PRIu64, chan.attr.subbuf_size); + DBG("Channel subbuf size set to %" PRIu64, chan_opts.attr.subbuf_size); break; } case OPT_NUM_SUBBUF: @@ -391,33 +429,33 @@ int cmd_enable_channels(int argc, const char **argv) errno = 0; opt_arg = poptGetOptArg(pc); - chan.attr.num_subbuf = strtoull(opt_arg, NULL, 0); - if (errno != 0 || !chan.attr.num_subbuf || !isdigit(opt_arg[0])) { + chan_opts.attr.num_subbuf = strtoull(opt_arg, NULL, 0); + if (errno != 0 || !chan_opts.attr.num_subbuf || !isdigit(opt_arg[0])) { ERR("Wrong value in --num-subbuf parameter: %s", opt_arg); ret = CMD_ERROR; goto end; } - order = get_count_order_u64(chan.attr.num_subbuf); + order = get_count_order_u64(chan_opts.attr.num_subbuf); assert(order >= 0); rounded_size = 1ULL << order; - if (rounded_size < chan.attr.num_subbuf) { + if (rounded_size < chan_opts.attr.num_subbuf) { ERR("The number of subbuffers (%" PRIu64 ") is rounded and overflows!", - chan.attr.num_subbuf); + chan_opts.attr.num_subbuf); ret = CMD_ERROR; goto end; } - if (rounded_size != chan.attr.num_subbuf) { + if (rounded_size != chan_opts.attr.num_subbuf) { WARN("The number of subbuffers (%" PRIu64 ") is rounded to the next power of 2 (%" PRIu64 ")", - chan.attr.num_subbuf, rounded_size); - chan.attr.num_subbuf = rounded_size; + chan_opts.attr.num_subbuf, rounded_size); + chan_opts.attr.num_subbuf = rounded_size; } /* Should now be power of 2 */ - assert(!((chan.attr.num_subbuf - 1) & chan.attr.num_subbuf)); + assert(!((chan_opts.attr.num_subbuf - 1) & chan_opts.attr.num_subbuf)); - DBG("Channel subbuf num set to %" PRIu64, chan.attr.num_subbuf); + DBG("Channel subbuf num set to %" PRIu64, chan_opts.attr.num_subbuf); break; } case OPT_SWITCH_TIMER: @@ -437,8 +475,8 @@ int cmd_enable_channels(int argc, const char **argv) ret = CMD_ERROR; goto end; } - chan.attr.switch_timer_interval = (uint32_t) v; - DBG("Channel switch timer interval set to %d", chan.attr.switch_timer_interval); + chan_opts.attr.switch_timer_interval = (uint32_t) v; + DBG("Channel switch timer interval set to %d", chan_opts.attr.switch_timer_interval); break; } case OPT_READ_TIMER: @@ -458,8 +496,30 @@ int cmd_enable_channels(int argc, const char **argv) ret = CMD_ERROR; goto end; } - chan.attr.read_timer_interval = (uint32_t) v; - DBG("Channel read timer interval set to %d", chan.attr.read_timer_interval); + chan_opts.attr.read_timer_interval = (uint32_t) v; + DBG("Channel read timer interval set to %d", chan_opts.attr.read_timer_interval); + break; + } + case OPT_MONITOR_TIMER: + { + unsigned long v; + + errno = 0; + opt_arg = poptGetOptArg(pc); + v = strtoul(opt_arg, NULL, 0); + if (errno != 0 || !isdigit(opt_arg[0])) { + ERR("Wrong value in --monitor-timer parameter: %s", opt_arg); + ret = CMD_ERROR; + goto end; + } + if (v != (uint32_t) v) { + ERR("32-bit overflow in --monitor-timer parameter: %s", opt_arg); + ret = CMD_ERROR; + goto end; + } + opt_monitor_timer.interval = (uint32_t) v; + opt_monitor_timer.set = true; + DBG("Channel monitor timer interval set to %d", opt_monitor_timer.interval); break; } case OPT_USERSPACE: @@ -467,13 +527,13 @@ int cmd_enable_channels(int argc, const char **argv) break; case OPT_TRACEFILE_SIZE: opt_arg = poptGetOptArg(pc); - if (utils_parse_size_suffix(opt_arg, &chan.attr.tracefile_size) < 0) { + if (utils_parse_size_suffix(opt_arg, &chan_opts.attr.tracefile_size) < 0) { ERR("Wrong value in --tracefile-size parameter: %s", opt_arg); ret = CMD_ERROR; goto end; } DBG("Maximum tracefile size set to %" PRIu64, - chan.attr.tracefile_size); + chan_opts.attr.tracefile_size); break; case OPT_TRACEFILE_COUNT: { @@ -492,9 +552,9 @@ int cmd_enable_channels(int argc, const char **argv) ret = CMD_ERROR; goto end; } - chan.attr.tracefile_count = (uint32_t) v; + chan_opts.attr.tracefile_count = (uint32_t) v; DBG("Maximum tracefile count set to %" PRIu64, - chan.attr.tracefile_count); + chan_opts.attr.tracefile_count); break; } case OPT_LIST_OPTIONS: diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index 9aa28b57a..c1f91d135 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -1166,7 +1166,7 @@ error: static void print_channel(struct lttng_channel *channel) { int ret; - uint64_t discarded_events, lost_packets; + uint64_t discarded_events, lost_packets, monitor_timer_interval; ret = lttng_channel_get_discarded_event_count(channel, &discarded_events); @@ -1182,6 +1182,13 @@ static void print_channel(struct lttng_channel *channel) return; } + ret = lttng_channel_get_monitor_timer_interval(channel, + &monitor_timer_interval); + if (ret) { + ERR("Failed to retrieve monitor interval of channel"); + return; + } + MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled)); MSG("%sAttributes:", indent4); @@ -1190,6 +1197,7 @@ static void print_channel(struct lttng_channel *channel) MSG("%snumber of subbuffers: %" PRIu64, indent6, channel->attr.num_subbuf); MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval); MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval); + MSG("%smonitor timer interval: %" PRIu64, indent6, monitor_timer_interval); MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count); MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size); MSG("%sdiscarded events: %" PRIu64, indent6, discarded_events); diff --git a/src/common/config/config-session-abi.h b/src/common/config/config-session-abi.h index 66d9cca73..2faa354a0 100644 --- a/src/common/config/config-session-abi.h +++ b/src/common/config/config-session-abi.h @@ -41,6 +41,7 @@ extern const char * const config_element_subbuf_size; extern const char * const config_element_num_subbuf; extern const char * const config_element_switch_timer_interval; extern const char * const config_element_read_timer_interval; +extern const char * const config_element_monitor_timer_interval; extern const char * const config_element_output; extern const char * const config_element_output_type; extern const char * const config_element_tracefile_size; diff --git a/src/common/config/session-config.c b/src/common/config/session-config.c index b2d7a6b5b..69b62d752 100644 --- a/src/common/config/session-config.c +++ b/src/common/config/session-config.c @@ -91,6 +91,7 @@ const char * const config_element_subbuf_size = "subbuffer_size"; const char * const config_element_num_subbuf = "subbuffer_count"; const char * const config_element_switch_timer_interval = "switch_timer_interval"; const char * const config_element_read_timer_interval = "read_timer_interval"; +const char * const config_element_monitor_timer_interval = "monitor_timer_interval"; const char * const config_element_output = "output"; const char * const config_element_output_type = "output_type"; const char * const config_element_tracefile_size = "tracefile_size"; diff --git a/src/common/consumer/consumer-testpoint.h b/src/common/consumer/consumer-testpoint.h index e94ce57a2..cb2634cd7 100644 --- a/src/common/consumer/consumer-testpoint.h +++ b/src/common/consumer/consumer-testpoint.h @@ -25,6 +25,7 @@ TESTPOINT_DECL(consumerd_thread_channel); TESTPOINT_DECL(consumerd_thread_metadata); TESTPOINT_DECL(consumerd_thread_data); +TESTPOINT_DECL(consumerd_thread_data_poll); TESTPOINT_DECL(consumerd_thread_sessiond); TESTPOINT_DECL(consumerd_thread_metadata_timer); diff --git a/src/common/consumer/consumer.c b/src/common/consumer/consumer.c index 3b857dec3..b2feb3945 100644 --- a/src/common/consumer/consumer.c +++ b/src/common/consumer/consumer.c @@ -67,6 +67,8 @@ struct consumer_channel_msg { uint64_t key; /* del */ }; +int data_consumption_paused; + /* * Flag to inform the polling thread to quit when all fd hung up. Updated by * the consumer_thread_receive_fds when it notices that all fds has hung up. @@ -2530,6 +2532,9 @@ void *consumer_thread_data_poll(void *data) /* poll on the array of fds */ restart: DBG("polling on %d fd", nb_fd + 2); + if (testpoint(consumerd_thread_data_poll)) { + goto end; + } health_poll_entry(); num_rdy = poll(pollfd, nb_fd + 2, -1); health_poll_exit(); diff --git a/src/common/consumer/consumer.h b/src/common/consumer/consumer.h index 527331298..6a38e50e5 100644 --- a/src/common/consumer/consumer.h +++ b/src/common/consumer/consumer.h @@ -161,6 +161,7 @@ struct lttng_consumer_channel { /* Metadata cache is metadata channel */ struct consumer_metadata_cache *metadata_cache; + /* For UST metadata periodical flush */ int switch_timer_enabled; timer_t switch_timer; @@ -601,6 +602,9 @@ struct lttng_consumer_global_data { struct lttng_ht *stream_per_chan_id_ht; }; +/* Flag used to temporarily pause data consumption from testpoints. */ +extern int data_consumption_paused; + /* * Init consumer data structures. */ diff --git a/src/common/kernel-ctl/kernel-ioctl.h b/src/common/kernel-ctl/kernel-ioctl.h index 396c28681..cb2362053 100644 --- a/src/common/kernel-ctl/kernel-ioctl.h +++ b/src/common/kernel-ctl/kernel-ioctl.h @@ -20,7 +20,7 @@ #define _LTT_KERNEL_IOCTL_H #define LTTNG_MODULES_ABI_MAJOR_VERSION 2 -#define LTTNG_MODULES_ABI_MINOR_VERSION 2 +#define LTTNG_MODULES_ABI_MINOR_VERSION 3 /* Get a snapshot of the current ring buffer producer and consumer positions */ #define RING_BUFFER_SNAPSHOT _IO(0xF6, 0x00) diff --git a/src/common/mi-lttng-3.0.xsd b/src/common/mi-lttng-3.0.xsd index 33d24ebf0..56b65a364 100644 --- a/src/common/mi-lttng-3.0.xsd +++ b/src/common/mi-lttng-3.0.xsd @@ -362,6 +362,7 @@ THE SOFTWARE. + diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index e87e767c5..197add2d4 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -862,7 +862,7 @@ int mi_lttng_channel_attr(struct mi_writer *writer, int ret = 0; struct lttng_channel *chan = caa_container_of(attr, struct lttng_channel, attr); - uint64_t discarded_events, lost_packets; + uint64_t discarded_events, lost_packets, monitor_timer_interval; assert(attr); @@ -876,6 +876,12 @@ int mi_lttng_channel_attr(struct mi_writer *writer, goto end; } + ret = lttng_channel_get_monitor_timer_interval(chan, + &monitor_timer_interval); + if (ret) { + goto end; + } + /* Opening Attributes */ ret = mi_lttng_writer_open_element(writer, config_element_attributes); if (ret) { @@ -922,6 +928,14 @@ int mi_lttng_channel_attr(struct mi_writer *writer, goto end; } + /* Monitor timer interval in usec */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + config_element_monitor_timer_interval, + monitor_timer_interval); + if (ret) { + goto end; + } + /* Event output */ ret = mi_lttng_writer_write_element_string(writer, config_element_output_type, diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 4e1665f40..0f9378c2c 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1320,26 +1320,111 @@ int lttng_disable_event(struct lttng_handle *handle, const char *name, return lttng_disable_event_ext(handle, &ev, channel_name, NULL); } +struct lttng_channel *lttng_channel_create(struct lttng_domain *domain) +{ + struct lttng_channel *channel = NULL; + struct lttng_channel_extended *extended = NULL; + + if (!domain) { + goto error; + } + + /* Validate domain. */ + switch (domain->type) { + case LTTNG_DOMAIN_UST: + switch (domain->buf_type) { + case LTTNG_BUFFER_PER_UID: + case LTTNG_BUFFER_PER_PID: + break; + default: + goto error; + } + break; + case LTTNG_DOMAIN_KERNEL: + if (domain->buf_type != LTTNG_BUFFER_GLOBAL) { + goto error; + } + break; + default: + goto error; + } + + channel = zmalloc(sizeof(*channel)); + if (!channel) { + goto error; + } + + extended = zmalloc(sizeof(*extended)); + if (!extended) { + goto error; + } + + channel->attr.extended.ptr = extended; + + lttng_channel_set_default_attr(domain, &channel->attr); + return channel; +error: + free(channel); + free(extended); + return NULL; +} + +void lttng_channel_destroy(struct lttng_channel *channel) +{ + if (!channel) { + return; + } + + if (channel->attr.extended.ptr) { + free(channel->attr.extended.ptr); + } + free(channel); +} + /* * Enable channel per domain * Returns size of returned session payload data or a negative error code. */ int lttng_enable_channel(struct lttng_handle *handle, - struct lttng_channel *chan) + struct lttng_channel *in_chan) { struct lttcomm_session_msg lsm; /* NULL arguments are forbidden. No default values. */ - if (handle == NULL || chan == NULL) { + if (handle == NULL || in_chan == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); + memcpy(&lsm.u.channel.chan, in_chan, sizeof(lsm.u.channel.chan)); + lsm.u.channel.chan.attr.extended.ptr = NULL; - memcpy(&lsm.u.channel.chan, chan, sizeof(lsm.u.channel.chan)); + if (!in_chan->attr.extended.ptr) { + struct lttng_channel *channel; + struct lttng_channel_extended *extended; - lsm.cmd_type = LTTNG_ENABLE_CHANNEL; + channel = lttng_channel_create(&handle->domain); + if (!channel) { + return -LTTNG_ERR_NOMEM; + } + + /* + * Create a new channel in order to use default extended + * attribute values. + */ + extended = (struct lttng_channel_extended *) + channel->attr.extended.ptr; + memcpy(&lsm.u.channel.extended, extended, sizeof(*extended)); + lttng_channel_destroy(channel); + } else { + struct lttng_channel_extended *extended; + + extended = (struct lttng_channel_extended *) + in_chan->attr.extended.ptr; + memcpy(&lsm.u.channel.extended, extended, sizeof(*extended)); + } + lsm.cmd_type = LTTNG_ENABLE_CHANNEL; lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); lttng_ctl_copy_string(lsm.session.name, handle->session_name, @@ -1705,7 +1790,7 @@ int lttng_list_channels(struct lttng_handle *handle, int ret; size_t channel_count, i; const size_t channel_size = sizeof(struct lttng_channel) + - sizeof(struct lttcomm_channel_extended); + sizeof(struct lttng_channel_extended); struct lttcomm_session_msg lsm; void *extended_at; @@ -1741,7 +1826,7 @@ int lttng_list_channels(struct lttng_handle *handle, struct lttng_channel *chan = &(*channels)[i]; chan->attr.extended.ptr = extended_at; - extended_at += sizeof(struct lttcomm_channel_extended); + extended_at += sizeof(struct lttng_channel_extended); } ret = (int) channel_count; @@ -1946,6 +2031,9 @@ int lttng_calibrate(struct lttng_handle *handle, void lttng_channel_set_default_attr(struct lttng_domain *domain, struct lttng_channel_attr *attr) { + struct lttng_channel_extended *extended = + (struct lttng_channel_extended *) attr->extended.ptr; + /* Safety check */ if (attr == NULL || domain == NULL) { return; @@ -1966,6 +2054,10 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, attr->subbuf_size = default_get_kernel_channel_subbuf_size(); attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM; attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT; + if (extended) { + extended->monitor_timer_interval = + DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER; + } break; case LTTNG_DOMAIN_UST: switch (domain->buf_type) { @@ -1977,6 +2069,10 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER; attr->read_timer_interval = DEFAULT_UST_UID_CHANNEL_READ_TIMER; + if (extended) { + extended->monitor_timer_interval = + DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER; + } break; case LTTNG_BUFFER_PER_PID: default: @@ -1987,19 +2083,25 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER; attr->read_timer_interval = DEFAULT_UST_PID_CHANNEL_READ_TIMER; + if (extended) { + extended->monitor_timer_interval = + DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER; + } break; } default: /* Default behavior: leave set to 0. */ break; } + + attr->extended.ptr = extended; } int lttng_channel_get_discarded_event_count(struct lttng_channel *channel, uint64_t *discarded_events) { int ret = 0; - struct lttcomm_channel_extended *chan_ext; + struct lttng_channel_extended *chan_ext; if (!channel || !discarded_events) { ret = -LTTNG_ERR_INVALID; @@ -2025,7 +2127,7 @@ int lttng_channel_get_lost_packet_count(struct lttng_channel *channel, uint64_t *lost_packets) { int ret = 0; - struct lttcomm_channel_extended *chan_ext; + struct lttng_channel_extended *chan_ext; if (!channel || !lost_packets) { ret = -LTTNG_ERR_INVALID; @@ -2047,6 +2149,44 @@ end: return ret; } +int lttng_channel_get_monitor_timer_interval(struct lttng_channel *chan, + uint64_t *monitor_timer_interval) +{ + int ret = 0; + + if (!chan || !monitor_timer_interval) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (!chan->attr.extended.ptr) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + *monitor_timer_interval = ((struct lttng_channel_extended *) + chan->attr.extended.ptr)->monitor_timer_interval; +end: + return ret; +} + +int lttng_channel_set_monitor_timer_interval(struct lttng_channel *chan, + uint64_t monitor_timer_interval) +{ + int ret = 0; + + if (!chan || !chan->attr.extended.ptr) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + ((struct lttng_channel_extended *) + chan->attr.extended.ptr)->monitor_timer_interval = + monitor_timer_interval; +end: + return ret; +} + /* * Check if session daemon is alive. * -- 2.34.1