X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsave.c;h=5a70fe609204a1ad1e1b3bffdf091aee40cd90b4;hb=c19092cd4d6af49c38322fc55ca91f17f03f32ac;hp=2e3e3d68451db189ae7af0d8eba650ebb28a2233;hpb=911d15607d55b7e374ff6750bddf7e4b4f763593;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index 2e3e3d684..5a70fe609 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -15,7 +15,6 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include @@ -25,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -33,8 +32,9 @@ #include "kernel.h" #include "save.h" #include "session.h" -#include "syscall.h" +#include "lttng-syscall.h" #include "trace-ust.h" +#include "agent.h" static int save_kernel_channel_attributes(struct config_writer *writer, @@ -104,6 +104,26 @@ int save_kernel_channel_attributes(struct config_writer *writer, if (ret) { goto end; } + + if (attr->extended.ptr) { + struct lttng_channel_extended *ext = NULL; + + ext = (struct lttng_channel_extended *) attr->extended.ptr; + ret = config_writer_write_element_unsigned_int(writer, + config_element_monitor_timer_interval, + ext->monitor_timer_interval); + if (ret) { + goto end; + } + + ret = config_writer_write_element_signed_int(writer, + config_element_blocking_timeout, + ext->blocking_timeout); + if (ret) { + goto end; + } + } + end: return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0; } @@ -113,6 +133,7 @@ int save_ust_channel_attributes(struct config_writer *writer, struct lttng_ust_channel_attr *attr) { int ret; + struct ltt_ust_channel *channel = NULL; ret = config_writer_write_element_string(writer, config_element_overwrite_mode, @@ -156,6 +177,26 @@ int save_ust_channel_attributes(struct config_writer *writer, if (ret) { goto end; } + + ret = config_writer_write_element_signed_int(writer, + config_element_blocking_timeout, + attr->u.s.blocking_timeout); + if (ret) { + goto end; + } + + /* + * Fetch the monitor timer which is located in the parent of + * lttng_ust_channel_attr + */ + channel = caa_container_of(attr, struct ltt_ust_channel, attr); + ret = config_writer_write_element_unsigned_int(writer, + config_element_monitor_timer_interval, + channel->monitor_timer_interval); + if (ret) { + goto end; + } + end: return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0; } @@ -232,6 +273,24 @@ const char *get_kernel_context_type_string( case LTTNG_KERNEL_CONTEXT_HOSTNAME: context_type_string = config_event_context_hostname; break; + case LTTNG_KERNEL_CONTEXT_INTERRUPTIBLE: + context_type_string = config_event_context_interruptible; + break; + case LTTNG_KERNEL_CONTEXT_PREEMPTIBLE: + context_type_string = config_event_context_preemptible; + break; + case LTTNG_KERNEL_CONTEXT_NEED_RESCHEDULE: + context_type_string = config_event_context_need_reschedule; + break; + case LTTNG_KERNEL_CONTEXT_MIGRATABLE: + context_type_string = config_event_context_migratable; + break; + case LTTNG_KERNEL_CONTEXT_CALLSTACK_USER: + context_type_string = config_event_context_callstack_user; + break; + case LTTNG_KERNEL_CONTEXT_CALLSTACK_KERNEL: + context_type_string = config_event_context_callstack_kernel; + break; default: context_type_string = NULL; } @@ -261,6 +320,9 @@ const char *get_ust_context_type_string( case LTTNG_UST_CONTEXT_PTHREAD_ID: context_type_string = config_event_context_pthread_id; break; + case LTTNG_UST_CONTEXT_APP_CONTEXT: + context_type_string = config_event_context_app; + break; case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER: /* * Error, should not be stored in the XML, perf contexts @@ -499,57 +561,6 @@ end: return ret; } -static -int save_kernel_syscall(struct config_writer *writer, - struct ltt_kernel_channel *kchan) -{ - int ret, i; - ssize_t count; - struct lttng_event *events = NULL; - - assert(writer); - assert(kchan); - - count = syscall_list_channel(kchan, &events, 0); - if (!count) { - /* No syscalls, just gracefully return. */ - ret = 0; - goto end; - } - - for (i = 0; i < count; i++) { - struct ltt_kernel_event *kevent; - - /* Create a temporary kevent in order to save it. */ - /* - * TODO: struct lttng_event does not really work for a filter, - * but unfortunately, it is exposed as external API (and used as - * internal representation. Using NULL meanwhile. - */ - kevent = trace_kernel_create_event(&events[i], - NULL, NULL); - if (!kevent) { - ret = -ENOMEM; - goto end; - } - /* Init list in order so the destroy call can del the node. */ - CDS_INIT_LIST_HEAD(&kevent->list); - - ret = save_kernel_event(writer, kevent); - trace_kernel_destroy_event(kevent); - if (ret) { - goto end; - } - } - - /* Everything went well */ - ret = 0; - -end: - free(events); - return ret; -} - static int save_kernel_events(struct config_writer *writer, struct ltt_kernel_channel *kchan) @@ -570,12 +581,6 @@ int save_kernel_events(struct config_writer *writer, } } - /* Save syscalls if any. */ - ret = save_kernel_syscall(writer, kchan); - if (ret) { - goto end; - } - /* /events */ ret = config_writer_close_element(writer); if (ret) { @@ -642,11 +647,14 @@ int save_ust_event(struct config_writer *writer, goto end; } - ret = config_writer_write_element_signed_int(writer, - config_element_loglevel, event->attr.loglevel); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; + /* The log level is irrelevant if no "filtering" is enabled */ + if (event->attr.loglevel_type != LTTNG_UST_LOGLEVEL_ALL) { + ret = config_writer_write_element_signed_int(writer, + config_element_loglevel, event->attr.loglevel); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } } if (event->filter_expression) { @@ -671,7 +679,8 @@ int save_ust_event(struct config_writer *writer, for (i = 0; i < event->exclusion->count; i++) { ret = config_writer_write_element_string(writer, config_element_exclusion, - &event->exclusion->names[0][i]); + LTTNG_EVENT_EXCLUSION_NAME_AT( + event->exclusion, i)); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -737,6 +746,96 @@ end: return ret; } +static +int init_ust_event_from_agent_event(struct ltt_ust_event *ust_event, + struct agent_event *agent_event) +{ + int ret = 0; + enum lttng_ust_loglevel_type ust_loglevel_type; + + ust_event->enabled = agent_event->enabled; + ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT; + if (lttng_strncpy(ust_event->attr.name, agent_event->name, + LTTNG_SYMBOL_NAME_LEN)) { + ret = -1; + goto end; + } + switch (agent_event->loglevel_type) { + case LTTNG_EVENT_LOGLEVEL_ALL: + ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL; + break; + case LTTNG_EVENT_LOGLEVEL_SINGLE: + ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE; + break; + case LTTNG_EVENT_LOGLEVEL_RANGE: + ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE; + break; + default: + ERR("Invalid agent_event loglevel_type."); + ret = -1; + goto end; + } + + ust_event->attr.loglevel_type = ust_loglevel_type; + ust_event->attr.loglevel = agent_event->loglevel_value; + ust_event->filter_expression = agent_event->filter_expression; + ust_event->exclusion = agent_event->exclusion; +end: + return ret; +} + +static +int save_agent_events(struct config_writer *writer, + struct agent *agent) +{ + int ret; + struct lttng_ht_iter iter; + struct lttng_ht_node_str *node; + + ret = config_writer_open_element(writer, config_element_events); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + rcu_read_lock(); + cds_lfht_for_each_entry(agent->events->ht, &iter.iter, node, node) { + int ret; + struct agent_event *agent_event; + struct ltt_ust_event fake_event; + + memset(&fake_event, 0, sizeof(fake_event)); + agent_event = caa_container_of(node, struct agent_event, node); + + /* + * Initialize a fake ust event to reuse the same serialization + * function since UST and agent events contain the same info + * (and one could wonder why they don't reuse the same + * structures...). + */ + ret = init_ust_event_from_agent_event(&fake_event, agent_event); + if (ret) { + rcu_read_unlock(); + goto end; + } + ret = save_ust_event(writer, &fake_event); + if (ret) { + rcu_read_unlock(); + goto end; + } + } + rcu_read_unlock(); + + /* /events */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } +end: + return ret; +} + static int save_kernel_context(struct config_writer *writer, struct lttng_kernel_context *ctx) @@ -754,7 +853,8 @@ int save_kernel_context(struct config_writer *writer, } if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) { - ret = config_writer_open_element(writer, config_element_perf); + ret = config_writer_open_element(writer, + config_element_context_perf); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -852,98 +952,43 @@ end: } static -int save_ust_context(struct config_writer *writer, - struct cds_list_head *ctx_list) +int save_ust_context_perf_thread_counter(struct config_writer *writer, + struct ltt_ust_context *ctx) { int ret; - struct ltt_ust_context *ctx; assert(writer); - assert(ctx_list); + assert(ctx); - ret = config_writer_open_element(writer, config_element_contexts); + /* Perf contexts are saved as event_perf_context_type */ + ret = config_writer_open_element(writer, config_element_context_perf); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - cds_list_for_each_entry(ctx, ctx_list, list) { - const char *context_type_string; - - - ret = config_writer_open_element(writer, - config_element_context); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) { - /* Perf contexts are saved as event_perf_context_type */ - ret = config_writer_open_element(writer, - config_element_perf); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - ret = config_writer_write_element_unsigned_int(writer, - config_element_type, - ctx->ctx.u.perf_counter.type); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - ret = config_writer_write_element_unsigned_int(writer, - config_element_config, - ctx->ctx.u.perf_counter.config); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - ret = config_writer_write_element_string(writer, - config_element_name, - ctx->ctx.u.perf_counter.name); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - /* /perf */ - ret = config_writer_close_element(writer); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - } else { - /* Save context as event_context_type_type */ - context_type_string = get_ust_context_type_string( - ctx->ctx.ctx); - if (!context_type_string) { - ERR("Unsupported UST context type.") - ret = LTTNG_ERR_INVALID; - goto end; - } + ret = config_writer_write_element_unsigned_int(writer, + config_element_type, ctx->ctx.u.perf_counter.type); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } - ret = config_writer_write_element_string(writer, - config_element_type, context_type_string); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - } + ret = config_writer_write_element_unsigned_int(writer, + config_element_config, ctx->ctx.u.perf_counter.config); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } - /* /context */ - ret = config_writer_close_element(writer); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } + ret = config_writer_write_element_string(writer, config_element_name, + ctx->ctx.u.perf_counter.name); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; } - /* /contexts */ + /* /perf */ ret = config_writer_close_element(writer); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -954,50 +999,38 @@ end: } static -int save_kernel_channel(struct config_writer *writer, - struct ltt_kernel_channel *kchan) +int save_ust_context_app_ctx(struct config_writer *writer, + struct ltt_ust_context *ctx) { int ret; assert(writer); - assert(kchan); + assert(ctx); - ret = config_writer_open_element(writer, config_element_channel); + /* Application contexts are saved as application_context_type */ + ret = config_writer_open_element(writer, config_element_context_app); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_write_element_string(writer, config_element_name, - kchan->channel->name); + ret = config_writer_write_element_string(writer, + config_element_context_app_provider_name, + ctx->ctx.u.app_ctx.provider_name); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_write_element_bool(writer, config_element_enabled, - kchan->channel->enabled); + ret = config_writer_write_element_string(writer, + config_element_context_app_ctx_name, + ctx->ctx.u.app_ctx.ctx_name); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_kernel_channel_attributes(writer, &kchan->channel->attr); - if (ret) { - goto end; - } - - ret = save_kernel_events(writer, kchan); - if (ret) { - goto end; - } - - ret = save_kernel_contexts(writer, kchan); - if (ret) { - goto end; - } - - /* /channel */ + /* /app */ ret = config_writer_close_element(writer); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -1008,70 +1041,131 @@ end: } static -int save_ust_channel(struct config_writer *writer, - struct ltt_ust_channel *ust_chan, - struct ltt_ust_session *session) +int save_ust_context_generic(struct config_writer *writer, + struct ltt_ust_context *ctx) { int ret; + const char *context_type_string; assert(writer); - assert(ust_chan); - assert(session); + assert(ctx); - ret = config_writer_open_element(writer, config_element_channel); - if (ret) { + /* Save context as event_context_type_type */ + context_type_string = get_ust_context_type_string( + ctx->ctx.ctx); + if (!context_type_string) { + ERR("Unsupported UST context type."); ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_write_element_string(writer, config_element_name, - ust_chan->name); + ret = config_writer_write_element_string(writer, + config_element_type, context_type_string); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } +end: + return ret; +} - ret = config_writer_write_element_bool(writer, config_element_enabled, - ust_chan->enabled); +static +int save_ust_context(struct config_writer *writer, + struct cds_list_head *ctx_list) +{ + int ret; + struct ltt_ust_context *ctx; + + assert(writer); + assert(ctx_list); + + ret = config_writer_open_element(writer, config_element_contexts); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_ust_channel_attributes(writer, &ust_chan->attr); + cds_list_for_each_entry(ctx, ctx_list, list) { + ret = config_writer_open_element(writer, + config_element_context); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + switch (ctx->ctx.ctx) { + case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER: + ret = save_ust_context_perf_thread_counter(writer, ctx); + break; + case LTTNG_UST_CONTEXT_APP_CONTEXT: + ret = save_ust_context_app_ctx(writer, ctx); + break; + default: + /* Save generic context. */ + ret = save_ust_context_generic(writer, ctx); + } + if (ret) { + goto end; + } + + /* /context */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } + + /* /contexts */ + ret = config_writer_close_element(writer); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } +end: + return ret; +} - ret = config_writer_write_element_unsigned_int(writer, - config_element_tracefile_size, ust_chan->tracefile_size); +static +int save_kernel_channel(struct config_writer *writer, + struct ltt_kernel_channel *kchan) +{ + int ret; + + assert(writer); + assert(kchan); + + ret = config_writer_open_element(writer, config_element_channel); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_write_element_unsigned_int(writer, - config_element_tracefile_count, ust_chan->tracefile_count); + ret = config_writer_write_element_string(writer, config_element_name, + kchan->channel->name); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_write_element_unsigned_int(writer, - config_element_live_timer_interval, - session->live_timer_interval); + ret = config_writer_write_element_bool(writer, config_element_enabled, + kchan->channel->enabled); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_ust_events(writer, ust_chan->events); + ret = save_kernel_channel_attributes(writer, &kchan->channel->attr); if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_ust_context(writer, &ust_chan->ctx_list); + ret = save_kernel_events(writer, kchan); + if (ret) { + goto end; + } + + ret = save_kernel_contexts(writer, kchan); if (ret) { goto end; } @@ -1087,45 +1181,96 @@ end: } static -int save_kernel_session(struct config_writer *writer, - struct ltt_session *session) +int save_ust_channel(struct config_writer *writer, + struct ltt_ust_channel *ust_chan, + struct ltt_ust_session *session) { int ret; - struct ltt_kernel_channel *kchan; assert(writer); + assert(ust_chan); assert(session); - ret = config_writer_write_element_string(writer, config_element_type, - config_domain_type_kernel); + ret = config_writer_open_element(writer, config_element_channel); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_write_element_string(writer, - config_element_buffer_type, config_buffer_type_global); + ret = config_writer_write_element_string(writer, config_element_name, + ust_chan->name); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_open_element(writer, - config_element_channels); + ret = config_writer_write_element_bool(writer, config_element_enabled, + ust_chan->enabled); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head, - list) { - ret = save_kernel_channel(writer, kchan); + ret = save_ust_channel_attributes(writer, &ust_chan->attr); + if (ret) { + goto end; + } + + ret = config_writer_write_element_unsigned_int(writer, + config_element_tracefile_size, ust_chan->tracefile_size); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_unsigned_int(writer, + config_element_tracefile_count, ust_chan->tracefile_count); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_unsigned_int(writer, + config_element_live_timer_interval, + session->live_timer_interval); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + if (ust_chan->domain == LTTNG_DOMAIN_UST) { + ret = save_ust_events(writer, ust_chan->events); + if (ret) { + goto end; + } + } else { + struct agent *agent = NULL; + + agent = trace_ust_find_agent(session, ust_chan->domain); + if (!agent) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + ERR("Could not find agent associated to UST subdomain"); + goto end; + } + + /* + * Channels associated with a UST sub-domain (such as JUL, Log4j + * or Python) don't have any non-internal events. We retrieve + * the "agent" events associated with this channel and serialize + * them. + */ + ret = save_agent_events(writer, agent); if (ret) { goto end; } } - /* /channels */ + ret = save_ust_context(writer, &ust_chan->ctx_list); + if (ret) { + goto end; + } + + /* /channel */ ret = config_writer_close_element(writer); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -1136,64 +1281,43 @@ end: } static -int save_ust_session(struct config_writer *writer, - struct ltt_session *session, int save_agent) +int save_kernel_session(struct config_writer *writer, + struct ltt_session *session) { int ret; - struct ltt_ust_channel *ust_chan; - const char *buffer_type_string; - struct lttng_ht_node_str *node; - struct lttng_ht_iter iter; + struct ltt_kernel_channel *kchan; assert(writer); assert(session); ret = config_writer_write_element_string(writer, config_element_type, - save_agent ? config_domain_type_jul : config_domain_type_ust); + config_domain_type_kernel); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - buffer_type_string = get_buffer_type_string( - session->ust_session->buffer_type); - if (!buffer_type_string) { - ERR("Unsupported buffer type."); - ret = LTTNG_ERR_INVALID; - goto end; - } - ret = config_writer_write_element_string(writer, - config_element_buffer_type, buffer_type_string); + config_element_buffer_type, config_buffer_type_global); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_open_element(writer, config_element_channels); + ret = config_writer_open_element(writer, + config_element_channels); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - rcu_read_lock(); - cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, - &iter.iter, node, node) { - int agent_channel; - - ust_chan = caa_container_of(node, struct ltt_ust_channel, node); - agent_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name) || - !strcmp(DEFAULT_LOG4J_CHANNEL_NAME, ust_chan->name) || - !strcmp(DEFAULT_PYTHON_CHANNEL_NAME, ust_chan->name); - if (!(save_agent ^ agent_channel)) { - ret = save_ust_channel(writer, ust_chan, session->ust_session); - if (ret) { - rcu_read_unlock(); - goto end; - } + cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head, + list) { + ret = save_kernel_channel(writer, kchan); + if (ret) { + goto end; } } - rcu_read_unlock(); /* /channels */ ret = config_writer_close_element(writer); @@ -1205,6 +1329,34 @@ end: return ret; } +static +const char *get_config_domain_str(enum lttng_domain_type domain) +{ + const char *str_dom; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + str_dom = config_domain_type_kernel; + break; + case LTTNG_DOMAIN_UST: + str_dom = config_domain_type_ust; + break; + case LTTNG_DOMAIN_JUL: + str_dom = config_domain_type_jul; + break; + case LTTNG_DOMAIN_LOG4J: + str_dom = config_domain_type_log4j; + break; + case LTTNG_DOMAIN_PYTHON: + str_dom = config_domain_type_python; + break; + default: + assert(0); + } + + return str_dom; +} + static int save_pid_tracker(struct config_writer *writer, struct ltt_session *sess, int domain) @@ -1299,45 +1451,90 @@ end: } static -int save_domains(struct config_writer *writer, struct ltt_session *session) +int save_ust_domain(struct config_writer *writer, + struct ltt_session *session, enum lttng_domain_type domain) { - int ret = 0; + int ret; + struct ltt_ust_channel *ust_chan; + const char *buffer_type_string; + struct lttng_ht_node_str *node; + struct lttng_ht_iter iter; + const char *config_domain_name; assert(writer); assert(session); - if (!session->kernel_session && !session->ust_session) { + ret = config_writer_open_element(writer, + config_element_domain); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_open_element(writer, config_element_domains); + config_domain_name = get_config_domain_str(domain); + if (!config_domain_name) { + ret = LTTNG_ERR_INVALID; + goto end; + } + + ret = config_writer_write_element_string(writer, + config_element_type, config_domain_name); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + buffer_type_string = get_buffer_type_string( + session->ust_session->buffer_type); + if (!buffer_type_string) { + ERR("Unsupported buffer type."); + ret = LTTNG_ERR_INVALID; + goto end; + } - if (session->kernel_session) { - ret = config_writer_open_element(writer, - config_element_domain); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } + ret = config_writer_write_element_string(writer, + config_element_buffer_type, buffer_type_string); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } - ret = save_kernel_session(writer, session); - if (ret) { - goto end; + ret = config_writer_open_element(writer, config_element_channels); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + rcu_read_lock(); + cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, + &iter.iter, node, node) { + ust_chan = caa_container_of(node, struct ltt_ust_channel, node); + if (domain == ust_chan->domain) { + ret = save_ust_channel(writer, ust_chan, session->ust_session); + if (ret) { + rcu_read_unlock(); + goto end; + } } + } + rcu_read_unlock(); + + /* /channels */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + if (domain == LTTNG_DOMAIN_UST) { ret = config_writer_open_element(writer, - config_element_trackers); + config_element_trackers); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL); + ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST); if (ret) { goto end; } @@ -1345,20 +1542,41 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) /* /trackers */ ret = config_writer_close_element(writer); if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - /* /domain */ - ret = config_writer_close_element(writer); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } } - if (session->ust_session) { - unsigned long agent_count; + /* /domain */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + +end: + return ret; +} + +static +int save_domains(struct config_writer *writer, struct ltt_session *session) +{ + int ret = 0; + + assert(writer); + assert(session); + + if (!session->kernel_session && !session->ust_session) { + goto end; + } + + ret = config_writer_open_element(writer, config_element_domains); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + if (session->kernel_session) { ret = config_writer_open_element(writer, config_element_domain); if (ret) { @@ -1366,7 +1584,7 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } - ret = save_ust_session(writer, session, 0); + ret = save_kernel_session(writer, session); if (ret) { goto end; } @@ -1378,7 +1596,7 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } - ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST); + ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL); if (ret) { goto end; } @@ -1395,27 +1613,27 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + } - agent_count = lttng_ht_get_count(session->ust_session->agents); - if (agent_count > 0) { - ret = config_writer_open_element(writer, - config_element_domain); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } + if (session->ust_session) { + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST); + if (ret) { + goto end; + } - ret = save_ust_session(writer, session, 1); - if (ret) { - goto end; - } + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL); + if (ret) { + goto end; + } - /* /domain */ - ret = config_writer_close_element(writer); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J); + if (ret) { + goto end; + } + + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON); + if (ret) { + goto end; } } @@ -1460,7 +1678,7 @@ int save_consumer_output(struct config_writer *writer, switch (output->type) { case CONSUMER_DST_LOCAL: ret = config_writer_write_element_string(writer, - config_element_path, output->dst.trace_path); + config_element_path, output->dst.session_root_path); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -1668,6 +1886,83 @@ end: return ret; } +static +int save_session_rotation_schedule(struct config_writer *writer, + enum lttng_rotation_schedule_type type, uint64_t value) +{ + int ret = 0; + const char *element_name; + const char *value_name; + + switch (type) { + case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC: + element_name = config_element_rotation_schedule_periodic; + value_name = config_element_rotation_schedule_periodic_time_us; + break; + case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD: + element_name = config_element_rotation_schedule_size_threshold; + value_name = config_element_rotation_schedule_size_threshold_bytes; + break; + default: + ret = -1; + goto end; + } + + ret = config_writer_open_element(writer, element_name); + if (ret) { + goto end; + } + + ret = config_writer_write_element_unsigned_int(writer, + value_name, value); + if (ret) { + goto end; + } + + /* Close schedule descriptor element. */ + ret = config_writer_close_element(writer); + if (ret) { + goto end; + } +end: + return ret; +} + +static +int save_session_rotation_schedules(struct config_writer *writer, + struct ltt_session *session) +{ + int ret; + + ret = config_writer_open_element(writer, + config_element_rotation_schedules); + if (session->rotate_timer_period) { + ret = save_session_rotation_schedule(writer, + LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC, + session->rotate_timer_period); + if (ret) { + goto close_schedules; + } + } + if (session->rotate_size) { + ret = save_session_rotation_schedule(writer, + LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD, + session->rotate_size); + if (ret) { + goto close_schedules; + } + } + +close_schedules: + /* Close rotation schedules element. */ + ret = config_writer_close_element(writer); + if (ret) { + goto end; + } +end: + return ret; +} + /* * Save the given session. * @@ -1820,7 +2115,8 @@ int save_session(struct ltt_session *session, goto end; } - if (session->snapshot_mode || session->live_timer) { + if (session->snapshot_mode || session->live_timer || + session->rotate_timer_period || session->rotate_size) { ret = config_writer_open_element(writer, config_element_attributes); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -1834,7 +2130,7 @@ int save_session(struct ltt_session *session, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - } else { + } else if (session->live_timer) { ret = config_writer_write_element_unsigned_int(writer, config_element_live_timer_interval, session->live_timer); if (ret) { @@ -1842,6 +2138,14 @@ int save_session(struct ltt_session *session, goto end; } } + if (session->rotate_timer_period || session->rotate_size) { + ret = save_session_rotation_schedules(writer, + session); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } /* /attributes */ ret = config_writer_close_element(writer); @@ -1881,6 +2185,13 @@ end: } } + if (file_opened) { + ret = close(fd); + if (ret) { + PERROR("Closing XML session configuration"); + } + } + return ret; }