X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=src%2Fcommon%2Fust-consumer%2Fust-consumer.c;h=10b1481c0e6ac7b1ce5fdad560f1d5bb4443709f;hb=a4eb26f0f09cd6d031166329a7d5d7b5d40408a6;hp=6a561b4ca7b3be844c7ae2d306b70b473da9eebb;hpb=3a2dcb5e6b59f5985ce114f5cec631a4ec60b9eb;p=lttng-tools.git diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index 6a561b4ca..10b1481c0 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Julien Desfossez + * Copyright (C) 2011 EfficiOS Inc. * Copyright (C) 2011 Mathieu Desnoyers * Copyright (C) 2017 Jérémie Galarneau * @@ -78,6 +78,11 @@ static void destroy_channel(struct lttng_consumer_channel *channel) lttng_ustconsumer_del_channel(channel); lttng_ustconsumer_free_channel(channel); } + + if (channel->trace_chunk) { + lttng_trace_chunk_put(channel->trace_chunk); + } + free(channel); } @@ -1026,7 +1031,7 @@ static int snapshot_metadata(struct lttng_consumer_channel *metadata_channel, metadata_stream = metadata_channel->metadata_stream; assert(metadata_stream); - pthread_mutex_lock(&metadata_stream->lock); + metadata_stream->read_subbuffer_ops.lock(metadata_stream); if (relayd_id != (uint64_t) -1ULL) { metadata_stream->net_seq_idx = relayd_id; ret = consumer_send_relayd_stream(metadata_stream, path); @@ -1034,14 +1039,12 @@ static int snapshot_metadata(struct lttng_consumer_channel *metadata_channel, ret = consumer_stream_create_output_files(metadata_stream, false); } - pthread_mutex_unlock(&metadata_stream->lock); if (ret < 0) { goto error_stream; } do { health_code_update(); - ret = lttng_consumer_read_subbuffer(metadata_stream, ctx, true); if (ret < 0) { goto error_stream; @@ -1049,9 +1052,10 @@ static int snapshot_metadata(struct lttng_consumer_channel *metadata_channel, } while (ret > 0); error_stream: + metadata_stream->read_subbuffer_ops.unlock(metadata_stream); /* - * Clean up the stream completly because the next snapshot will use a new - * metadata stream. + * Clean up the stream completely because the next snapshot will use a + * new metadata stream. */ consumer_stream_destroy(metadata_stream, NULL); cds_list_del(&metadata_stream->send_node); @@ -1273,6 +1277,17 @@ error_unlock: return ret; } +static +void metadata_stream_reset_cache_consumed_position( + struct lttng_consumer_stream *stream) +{ + ASSERT_LOCKED(stream->lock); + + DBG("Reset metadata cache of session %" PRIu64, + stream->chan->session_id); + stream->ust_metadata_pushed = 0; +} + /* * Receive the metadata updates from the sessiond. Supports receiving * overlapping metadata, but is needs to always belong to a contiguous @@ -1287,6 +1302,7 @@ int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset, { int ret, ret_code = LTTCOMM_CONSUMERD_SUCCESS; char *metadata_str; + enum consumer_metadata_cache_write_status cache_write_status; DBG("UST consumer push metadata key %" PRIu64 " of len %" PRIu64, key, len); @@ -1310,9 +1326,48 @@ int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset, health_code_update(); pthread_mutex_lock(&channel->metadata_cache->lock); - ret = consumer_metadata_cache_write(channel, offset, len, version, - metadata_str); - if (ret < 0) { + cache_write_status = consumer_metadata_cache_write( + channel, offset, len, version, metadata_str); + pthread_mutex_unlock(&channel->metadata_cache->lock); + switch (cache_write_status) { + case CONSUMER_METADATA_CACHE_WRITE_STATUS_NO_CHANGE: + /* + * The write entirely overlapped with existing contents of the + * same metadata version (same content); there is nothing to do. + */ + break; + case CONSUMER_METADATA_CACHE_WRITE_STATUS_INVALIDATED: + /* + * The metadata cache was invalidated (previously pushed + * content has been overwritten). Reset the stream's consumed + * metadata position to ensure the metadata poll thread consumes + * the whole cache. + */ + + /* + * channel::metadata_stream can be null when the metadata + * channel is under a snapshot session type. No need to update + * the stream position in that scenario. + */ + if (channel->metadata_stream != NULL) { + pthread_mutex_lock(&channel->metadata_stream->lock); + metadata_stream_reset_cache_consumed_position( + channel->metadata_stream); + pthread_mutex_unlock(&channel->metadata_stream->lock); + } + /* Fall-through. */ + case CONSUMER_METADATA_CACHE_WRITE_STATUS_APPENDED_CONTENT: + /* + * In both cases, the metadata poll thread has new data to + * consume. + */ + ret = consumer_metadata_wakeup_pipe(channel); + if (ret) { + ret_code = LTTCOMM_CONSUMERD_ERROR_METADATA; + goto end_free; + } + break; + case CONSUMER_METADATA_CACHE_WRITE_STATUS_ERROR: /* Unable to handle metadata. Notify session daemon. */ ret_code = LTTCOMM_CONSUMERD_ERROR_METADATA; /* @@ -1320,10 +1375,10 @@ int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset, * not have been updated which could create an infinite loop below when * waiting for the metadata cache to be flushed. */ - pthread_mutex_unlock(&channel->metadata_cache->lock); goto end_free; + default: + abort(); } - pthread_mutex_unlock(&channel->metadata_cache->lock); if (!wait) { goto end_free; @@ -2138,7 +2193,7 @@ end_rotate_channel_nosignal: const uint64_t relayd_id = msg.u.close_trace_chunk.relayd_id.value; struct lttcomm_consumer_close_trace_chunk_reply reply; - char closed_trace_chunk_path[LTTNG_PATH_MAX]; + char closed_trace_chunk_path[LTTNG_PATH_MAX] = {}; int ret; ret_code = lttng_consumer_close_trace_chunk( @@ -2176,6 +2231,28 @@ end_rotate_channel_nosignal: msg.u.trace_chunk_exists.chunk_id); goto end_msg_sessiond; } + case LTTNG_CONSUMER_OPEN_CHANNEL_PACKETS: + { + const uint64_t key = msg.u.open_channel_packets.key; + struct lttng_consumer_channel *channel = + consumer_find_channel(key); + + if (channel) { + pthread_mutex_lock(&channel->lock); + ret_code = lttng_consumer_open_channel_packets(channel); + pthread_mutex_unlock(&channel->lock); + } else { + /* + * The channel could have disappeared in per-pid + * buffering mode. + */ + DBG("Channel %" PRIu64 " not found", key); + ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND; + } + + health_code_update(); + goto end_msg_sessiond; + } default: break; } @@ -2429,20 +2506,11 @@ int lttng_ustconsumer_close_wakeup_fd(struct lttng_consumer_stream *stream) return ustctl_stream_close_wakeup_fd(stream->ustream); } -static -void metadata_stream_reset_cache_consumed_position( - struct lttng_consumer_stream *stream) -{ - DBG("Reset metadata cache of session %" PRIu64, - stream->chan->session_id); - stream->ust_metadata_pushed = 0; -} - /* * Write up to one packet from the metadata cache to the channel. * - * Returns the number of bytes pushed in the cache, or a negative value - * on error. + * Returns the number of bytes pushed from the cache into the ring buffer, or a + * negative value on error. */ static int commit_one_metadata_packet(struct lttng_consumer_stream *stream) @@ -2526,15 +2594,13 @@ end: * awaiting on metadata to be pushed out. * * The RCU read side lock must be held by the caller. - * - * Return 0 if new metadatda is available, EAGAIN if the metadata stream - * is empty or a negative value on error. */ -int lttng_ustconsumer_sync_metadata(struct lttng_consumer_local_data *ctx, +enum sync_metadata_status lttng_ustconsumer_sync_metadata( + struct lttng_consumer_local_data *ctx, struct lttng_consumer_stream *metadata_stream) { int ret; - int retry = 0; + enum sync_metadata_status status; struct lttng_consumer_channel *metadata_channel; assert(ctx); @@ -2549,6 +2615,7 @@ int lttng_ustconsumer_sync_metadata(struct lttng_consumer_local_data *ctx, ret = lttng_ustconsumer_request_metadata(ctx, metadata_channel, 0, 0); pthread_mutex_lock(&metadata_stream->lock); if (ret < 0) { + status = SYNC_METADATA_STATUS_ERROR; goto end; } @@ -2566,38 +2633,30 @@ int lttng_ustconsumer_sync_metadata(struct lttng_consumer_local_data *ctx, if (consumer_stream_is_deleted(metadata_stream)) { DBG("Metadata stream %" PRIu64 " was deleted during the metadata synchronization", metadata_stream->key); - ret = 0; + status = SYNC_METADATA_STATUS_NO_DATA; goto end; } ret = commit_one_metadata_packet(metadata_stream); - if (ret <= 0) { + if (ret < 0) { + status = SYNC_METADATA_STATUS_ERROR; goto end; } else if (ret > 0) { - retry = 1; + status = SYNC_METADATA_STATUS_NEW_DATA; + } else /* ret == 0 */ { + status = SYNC_METADATA_STATUS_NO_DATA; + goto end; } ret = ustctl_snapshot(metadata_stream->ustream); if (ret < 0) { - if (errno != EAGAIN) { - ERR("Sync metadata, taking UST snapshot"); - goto end; - } - DBG("No new metadata when syncing them."); - /* No new metadata, exit. */ - ret = ENODATA; + ERR("Failed to take a snapshot of the metadata ring-buffer positions, ret = %d", ret); + status = SYNC_METADATA_STATUS_ERROR; goto end; } - /* - * After this flush, we still need to extract metadata. - */ - if (retry) { - ret = EAGAIN; - } - end: - return ret; + return status; } /* @@ -3024,6 +3083,7 @@ int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream) assert(stream); assert(stream->ustream); + ASSERT_LOCKED(stream->lock); DBG("UST consumer checking data pending"); @@ -3036,7 +3096,9 @@ int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream) uint64_t contiguous, pushed; /* Ease our life a bit. */ + pthread_mutex_lock(&stream->chan->metadata_cache->lock); contiguous = stream->chan->metadata_cache->max_offset; + pthread_mutex_unlock(&stream->chan->metadata_cache->lock); pushed = stream->ust_metadata_pushed; /*