X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fcommon%2Fust-consumer%2Fust-consumer.c;h=d0488dbc837851ec3a23162a2595954aa2c02a87;hb=a1ae2ea59428174575b7328b1062a6248d636b72;hp=7006e1cb435fb47a4b628e863d24aa338d1728ae;hpb=b35308203f7844f48542978fd00aab21f2057c17;p=lttng-tools.git diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index 7006e1cb4..d0488dbc8 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -51,7 +51,6 @@ extern struct lttng_consumer_global_data consumer_data; extern int consumer_poll_timeout; -extern volatile int consumer_quit; /* * Free channel object and all streams associated with it. This MUST be used @@ -207,28 +206,21 @@ static int send_stream_to_thread(struct lttng_consumer_stream *stream, /* Get the right pipe where the stream will be sent. */ if (stream->metadata_flag) { - ret = consumer_add_metadata_stream(stream); - if (ret) { - ERR("Consumer add metadata stream %" PRIu64 " failed.", - stream->key); - goto error; - } + consumer_add_metadata_stream(stream); stream_pipe = ctx->consumer_metadata_pipe; } else { - ret = consumer_add_data_stream(stream); - if (ret) { - ERR("Consumer add stream %" PRIu64 " failed.", - stream->key); - goto error; - } + consumer_add_data_stream(stream); stream_pipe = ctx->consumer_data_pipe; } /* * From this point on, the stream's ownership has been moved away from - * the channel and becomes globally visible. + * the channel and it becomes globally visible. Hence, remove it from + * the local stream list to prevent the stream from being both local and + * global. */ stream->globally_visible = 1; + cds_list_del(&stream->send_node); ret = lttng_pipe_write(stream_pipe, &stream, sizeof(stream)); if (ret < 0) { @@ -240,7 +232,9 @@ static int send_stream_to_thread(struct lttng_consumer_stream *stream, } else { consumer_del_stream_for_data(stream); } + goto error; } + error: return ret; } @@ -722,14 +716,8 @@ static int send_streams_to_thread(struct lttng_consumer_channel *channel, * If we are unable to send the stream to the thread, there is * a big problem so just stop everything. */ - /* Remove node from the channel stream list. */ - cds_list_del(&stream->send_node); goto error; } - - /* Remove node from the channel stream list. */ - cds_list_del(&stream->send_node); - } error: @@ -832,6 +820,7 @@ static int close_metadata(uint64_t chan_key) { int ret = 0; struct lttng_consumer_channel *channel; + unsigned int channel_monitor; DBG("UST consumer close metadata key %" PRIu64, chan_key); @@ -850,13 +839,48 @@ static int close_metadata(uint64_t chan_key) pthread_mutex_lock(&consumer_data.lock); pthread_mutex_lock(&channel->lock); - + channel_monitor = channel->monitor; if (cds_lfht_is_node_deleted(&channel->node.node)) { goto error_unlock; } lttng_ustconsumer_close_metadata(channel); + pthread_mutex_unlock(&channel->lock); + pthread_mutex_unlock(&consumer_data.lock); + /* + * The ownership of a metadata channel depends on the type of + * session to which it belongs. In effect, the monitor flag is checked + * to determine if this metadata channel is in "snapshot" mode or not. + * + * In the non-snapshot case, the metadata channel is created along with + * a single stream which will remain present until the metadata channel + * is destroyed (on the destruction of its session). In this case, the + * metadata stream in "monitored" by the metadata poll thread and holds + * the ownership of its channel. + * + * Closing the metadata will cause the metadata stream's "metadata poll + * pipe" to be closed. Closing this pipe will wake-up the metadata poll + * thread which will teardown the metadata stream which, in return, + * deletes the metadata channel. + * + * In the snapshot case, the metadata stream is created and destroyed + * on every snapshot record. Since the channel doesn't have an owner + * other than the session daemon, it is safe to destroy it immediately + * on reception of the CLOSE_METADATA command. + */ + if (!channel_monitor) { + /* + * The channel and consumer_data locks must be + * released before this call since consumer_del_channel + * re-acquires the channel and consumer_data locks to teardown + * the channel and queue its reclamation by the "call_rcu" + * worker thread. + */ + consumer_del_channel(channel); + } + + return ret; error_unlock: pthread_mutex_unlock(&channel->lock); pthread_mutex_unlock(&consumer_data.lock); @@ -919,6 +943,10 @@ static int setup_metadata(struct lttng_consumer_local_data *ctx, uint64_t key) } } + /* + * Ownership of metadata stream is passed along. Freeing is handled by + * the callee. + */ ret = send_streams_to_thread(metadata, ctx); if (ret < 0) { /* @@ -926,7 +954,7 @@ static int setup_metadata(struct lttng_consumer_local_data *ctx, uint64_t key) * a big problem so just stop everything. */ ret = LTTCOMM_CONSUMERD_FATAL; - goto error; + goto send_streams_error; } /* List MUST be empty after or else it could be reused. */ assert(cds_list_empty(&metadata->streams.head)); @@ -944,6 +972,7 @@ error: consumer_stream_destroy(metadata->metadata_stream, NULL); cds_list_del(&metadata->metadata_stream->send_node); metadata->metadata_stream = NULL; +send_streams_error: error_no_stream: end: return ret; @@ -1077,9 +1106,6 @@ static int snapshot_channel(uint64_t key, char *path, uint64_t relayd_id, DBG("UST consumer snapshot channel %" PRIu64, key); cds_list_for_each_entry(stream, &channel->streams.head, send_node) { - /* Are we at a position _before_ the first available packet ? */ - bool before_first_packet = true; - health_code_update(); /* Lock stream because we are about to change its state. */ @@ -1105,12 +1131,6 @@ static int snapshot_channel(uint64_t key, char *path, uint64_t relayd_id, DBG("UST consumer snapshot stream %s/%s (%" PRIu64 ")", path, stream->name, stream->key); } - if (relayd_id != -1ULL) { - ret = consumer_send_relayd_streams_sent(relayd_id); - if (ret < 0) { - goto error_unlock; - } - } /* * If tracing is active, we want to perform a "full" buffer flush. @@ -1151,7 +1171,6 @@ static int snapshot_channel(uint64_t key, char *path, uint64_t relayd_id, while (consumed_pos < produced_pos) { ssize_t read_len; unsigned long len, padded_len; - int lost_packet = 0; health_code_update(); @@ -1165,15 +1184,7 @@ static int snapshot_channel(uint64_t key, char *path, uint64_t relayd_id, } DBG("UST consumer get subbuf failed. Skipping it."); consumed_pos += stream->max_sb_size; - - /* - * Start accounting lost packets only when we - * already have extracted packets (to match the - * content of the final snapshot). - */ - if (!before_first_packet) { - lost_packet = 1; - } + stream->chan->lost_packets++; continue; } @@ -1209,16 +1220,6 @@ static int snapshot_channel(uint64_t key, char *path, uint64_t relayd_id, goto error_close_stream; } consumed_pos += stream->max_sb_size; - - /* - * Only account lost packets located between - * succesfully extracted packets (do not account before - * and after since they are not visible in the - * resulting snapshot). - */ - stream->chan->lost_packets += lost_packet; - lost_packet = 0; - before_first_packet = false; } /* Simply close the stream so we can use it on the next snapshot. */ @@ -1355,7 +1356,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, case LTTNG_CONSUMER_ADD_RELAYD_SOCKET: { /* Session daemon status message are handled in the following call. */ - ret = consumer_add_relayd_socket(msg.u.relayd_sock.net_index, + consumer_add_relayd_socket(msg.u.relayd_sock.net_index, msg.u.relayd_sock.type, ctx, sock, consumer_sockpoll, &msg.u.relayd_sock.sock, msg.u.relayd_sock.session_id, msg.u.relayd_sock.relayd_session_id); @@ -1456,6 +1457,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, attr.read_timer_interval = msg.u.ask_channel.read_timer_interval; attr.chan_id = msg.u.ask_channel.chan_id; memcpy(attr.uuid, msg.u.ask_channel.uuid, sizeof(attr.uuid)); + attr.blocking_timeout= msg.u.ask_channel.blocking_timeout; /* Match channel buffer type to the UST abi. */ switch (msg.u.ask_channel.output) { @@ -1502,8 +1504,17 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, consumer_timer_switch_start(channel, attr.switch_timer_interval); attr.switch_timer_interval = 0; } else { + int monitor_start_ret; + consumer_timer_live_start(channel, msg.u.ask_channel.live_timer_interval); + monitor_start_ret = consumer_timer_monitor_start( + channel, + msg.u.ask_channel.monitor_timer_interval); + if (monitor_start_ret < 0) { + ERR("Starting channel monitoring timer failed"); + goto end_channel_error; + } } health_code_update(); @@ -1526,6 +1537,9 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, if (channel->live_timer_enabled == 1) { consumer_timer_live_stop(channel); } + if (channel->monitor_timer_enabled == 1) { + consumer_timer_monitor_stop(channel); + } goto end_channel_error; } @@ -1903,6 +1917,29 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, } goto end_msg_sessiond; } + case LTTNG_CONSUMER_MKDIR: + { + DBG("Consumer mkdir %s in session %" PRIu64, + msg.u.mkdir.path, + msg.u.mkdir.session_id); + ret = lttng_consumer_mkdir(msg.u.mkdir.path, + msg.u.mkdir.uid, + msg.u.mkdir.gid, + msg.u.mkdir.relayd_id); + if (ret < 0) { + ERR("consumer mkdir failed"); + ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND; + } + + health_code_update(); + + ret = consumer_send_status_msg(sock, ret_code); + if (ret < 0) { + /* Somehow, the session daemon is not responding anymore. */ + goto end_nosignal; + } + break; + } default: break; } @@ -1984,7 +2021,7 @@ void *lttng_ustctl_get_mmap_base(struct lttng_consumer_stream *stream) } /* - * Take a snapshot for a specific fd + * Take a snapshot for a specific stream. * * Returns 0 on success, < 0 on error */ @@ -1996,6 +2033,20 @@ int lttng_ustconsumer_take_snapshot(struct lttng_consumer_stream *stream) return ustctl_snapshot(stream->ustream); } +/* + * Sample consumed and produced positions for a specific stream. + * + * Returns 0 on success, < 0 on error. + */ +int lttng_ustconsumer_sample_snapshot_positions( + struct lttng_consumer_stream *stream) +{ + assert(stream); + assert(stream->ustream); + + return ustctl_snapshot_sample_positions(stream->ustream); +} + /* * Get the produced position *