*/
static struct lttng_consumer_channel *allocate_channel(uint64_t session_id,
const char *pathname, const char *name, uid_t uid, gid_t gid,
- int relayd_id, uint64_t key, enum lttng_event_output output,
- uint64_t tracefile_size, uint64_t tracefile_count)
+ uint64_t relayd_id, uint64_t key, enum lttng_event_output output,
+ uint64_t tracefile_size, uint64_t tracefile_count,
+ uint64_t session_id_per_pid)
{
assert(pathname);
assert(name);
- return consumer_allocate_channel(key, session_id, pathname, name, uid, gid,
- relayd_id, output, tracefile_size, tracefile_count);
+ return consumer_allocate_channel(key, session_id, pathname, name, uid,
+ gid, relayd_id, output, tracefile_size,
+ tracefile_count, session_id_per_pid);
}
/*
/* 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;
+ }
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;
+ }
stream_pipe = ctx->consumer_data_pipe;
}
ERR("Consumer write %s stream to pipe %d",
stream->metadata_flag ? "metadata" : "data",
lttng_pipe_get_writefd(stream_pipe));
+ if (stream->metadata_flag) {
+ consumer_del_stream_for_metadata(stream);
+ } else {
+ consumer_del_stream_for_data(stream);
+ }
}
-
+error:
return ret;
}
assert(stream);
assert(sock >= 0);
- DBG2("UST consumer sending stream %" PRIu64 " to sessiond", stream->key);
+ DBG("UST consumer sending stream %" PRIu64 " to sessiond", stream->key);
/* Send stream to session daemon. */
ret = ustctl_send_stream_to_sessiond(sock, stream->ustream);
* 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;
}
cds_lfht_for_each_entry_duplicate(ht->ht,
ht->hash_fct(&channel->key, lttng_ht_seed), ht->match_fct,
&channel->key, &iter.iter, stream, node_channel_id.node) {
- ustctl_flush_buffer(stream->ustream, 1);
+ ustctl_flush_buffer(stream->ustream, 1);
}
error:
rcu_read_unlock();
}
pthread_mutex_lock(&consumer_data.lock);
+ pthread_mutex_lock(&channel->lock);
if (cds_lfht_is_node_deleted(&channel->node.node)) {
goto error_unlock;
}
error_unlock:
+ pthread_mutex_unlock(&channel->lock);
pthread_mutex_unlock(&consumer_data.lock);
error:
return ret;
* Receive the metadata updates from the sessiond.
*/
int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
- uint64_t len, struct lttng_consumer_channel *channel)
+ uint64_t len, struct lttng_consumer_channel *channel,
+ int timer)
{
int ret, ret_code = LTTNG_OK;
char *metadata_str;
goto end_free;
}
- /*
- * XXX: The consumer data lock is acquired before calling metadata cache
- * write which calls push metadata that MUST be protected by the consumer
- * lock in order to be able to check the validity of the metadata stream of
- * the channel.
- *
- * Note that this will be subject to change to better fine grained locking
- * and ultimately try to get rid of this global consumer data lock.
- */
- pthread_mutex_lock(&consumer_data.lock);
-
+ if (!timer) {
+ pthread_mutex_lock(&channel->lock);
+ }
+ pthread_mutex_lock(&channel->timer_lock);
pthread_mutex_lock(&channel->metadata_cache->lock);
ret = consumer_metadata_cache_write(channel, offset, len, metadata_str);
if (ret < 0) {
* waiting for the metadata cache to be flushed.
*/
pthread_mutex_unlock(&channel->metadata_cache->lock);
- pthread_mutex_unlock(&consumer_data.lock);
+ pthread_mutex_unlock(&channel->timer_lock);
+ if (!timer) {
+ pthread_mutex_unlock(&channel->lock);
+ }
goto end_free;
}
pthread_mutex_unlock(&channel->metadata_cache->lock);
- pthread_mutex_unlock(&consumer_data.lock);
+ pthread_mutex_unlock(&channel->timer_lock);
+ if (!timer) {
+ pthread_mutex_unlock(&channel->lock);
+ }
- while (consumer_metadata_cache_flushed(channel, offset + len)) {
+ while (consumer_metadata_cache_flushed(channel, offset + len, timer)) {
DBG("Waiting for metadata to be flushed");
usleep(DEFAULT_METADATA_AVAILABILITY_WAIT_TIME);
}
if (ret != sizeof(msg)) {
DBG("Consumer received unexpected message size %zd (expects %zu)",
ret, sizeof(msg));
- lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_ERROR_RECV_CMD);
/*
* The ret value might 0 meaning an orderly shutdown but this is ok
* since the caller handles this.
*/
if (ret > 0) {
+ lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_ERROR_RECV_CMD);
ret = -1;
}
return ret;
msg.u.ask_channel.relayd_id, msg.u.ask_channel.key,
(enum lttng_event_output) msg.u.ask_channel.output,
msg.u.ask_channel.tracefile_size,
- msg.u.ask_channel.tracefile_count);
+ msg.u.ask_channel.tracefile_count,
+ msg.u.ask_channel.session_id_per_pid);
if (!channel) {
goto end_channel_error;
}
}
ret = lttng_ustconsumer_recv_metadata(sock, key, offset,
- len, channel);
+ len, channel, 0);
if (ret < 0) {
/* error receiving from sessiond */
goto error_fatal;
assert(stream->ustream);
assert(ctx);
- DBG2("In UST read_subbuffer (wait_fd: %d, name: %s)", stream->wait_fd,
+ DBG("In UST read_subbuffer (wait_fd: %d, name: %s)", stream->wait_fd,
stream->name);
/* Ease our life for what's next. */
DBG("UST consumer checking data pending");
+ if (stream->endpoint_status != CONSUMER_ENDPOINT_ACTIVE) {
+ ret = 0;
+ goto end;
+ }
+
ret = ustctl_get_next_subbuf(stream->ustream);
if (ret == 0) {
/* There is still data so let's put back this subbuffer. */
}
}
+/*
+ * Please refer to consumer-timer.c before adding any lock within this
+ * function or any of its callees. Timers have a very strict locking
+ * semantic with respect to teardown. Failure to respect this semantic
+ * introduces deadlocks.
+ */
int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
- struct lttng_consumer_channel *channel)
+ struct lttng_consumer_channel *channel, int timer)
{
struct lttcomm_metadata_request_msg request;
struct lttcomm_consumer_msg msg;
}
request.session_id = channel->session_id;
+ request.session_id_per_pid = channel->session_id_per_pid;
request.uid = channel->uid;
request.key = channel->key;
- DBG("Sending metadata request to sessiond, session %" PRIu64,
- channel->session_id);
+ DBG("Sending metadata request to sessiond, session id %" PRIu64
+ ", per-pid %" PRIu64,
+ channel->session_id,
+ channel->session_id_per_pid);
ret = lttcomm_send_unix_sock(ctx->consumer_metadata_socket, &request,
sizeof(request));
}
ret_code = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
- key, offset, len, channel);
+ key, offset, len, channel, timer);
if (ret_code >= 0) {
/*
* Only send the status msg if the sessiond is alive meaning a positive