X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Fcommon%2Fconsumer%2Fconsumer.cpp;h=c1abb58df616f036e3f76a9a13959c74d217883b;hb=d119bd017a99d56ad36901ce8f2175a8ea3b5e5e;hp=9393e6cc29af21a8c3b8072ffd42eb6a0ae14b3e;hpb=64803277bbdbe0a943360d918298a48157d9da55;p=lttng-tools.git diff --git a/src/common/consumer/consumer.cpp b/src/common/consumer/consumer.cpp index 9393e6cc2..c1abb58df 100644 --- a/src/common/consumer/consumer.cpp +++ b/src/common/consumer/consumer.cpp @@ -52,12 +52,22 @@ enum consumer_channel_action { CONSUMER_CHANNEL_QUIT, }; +namespace { struct consumer_channel_msg { enum consumer_channel_action action; struct lttng_consumer_channel *chan; /* add */ uint64_t key; /* del */ }; +/* + * Global hash table containing respectively metadata and data streams. The + * stream element in this ht should only be updated by the metadata poll thread + * for the metadata and the data poll thread for the data. + */ +struct lttng_ht *metadata_ht; +struct lttng_ht *data_ht; +} /* namespace */ + /* Flag used to temporarily pause data consumption from testpoints. */ int data_consumption_paused; @@ -69,14 +79,6 @@ int data_consumption_paused; */ int consumer_quit; -/* - * Global hash table containing respectively metadata and data streams. The - * stream element in this ht should only be updated by the metadata poll thread - * for the metadata and the data poll thread for the data. - */ -static struct lttng_ht *metadata_ht; -static struct lttng_ht *data_ht; - static const char *get_consumer_domain(void) { switch (the_consumer_data.type) { @@ -207,7 +209,7 @@ static struct lttng_consumer_stream *find_stream(uint64_t key, lttng_ht_lookup(ht, &key, &iter); node = lttng_ht_iter_get_node_u64(&iter); if (node != NULL) { - stream = caa_container_of(node, struct lttng_consumer_stream, node); + stream = lttng::utils::container_of(node, <tng_consumer_stream::node); } rcu_read_unlock(); @@ -255,7 +257,7 @@ struct lttng_consumer_channel *consumer_find_channel(uint64_t key) lttng_ht_lookup(the_consumer_data.channel_ht, &key, &iter); node = lttng_ht_iter_get_node_u64(&iter); if (node != NULL) { - channel = caa_container_of(node, struct lttng_consumer_channel, node); + channel = lttng::utils::container_of(node, <tng_consumer_channel::node); } return channel; @@ -290,9 +292,9 @@ static void steal_channel_key(uint64_t key) static void free_channel_rcu(struct rcu_head *head) { struct lttng_ht_node_u64 *node = - caa_container_of(head, struct lttng_ht_node_u64, head); + lttng::utils::container_of(head, <tng_ht_node_u64::head); struct lttng_consumer_channel *channel = - caa_container_of(node, struct lttng_consumer_channel, node); + lttng::utils::container_of(node, <tng_consumer_channel::node); switch (the_consumer_data.type) { case LTTNG_CONSUMER_KERNEL: @@ -314,9 +316,9 @@ static void free_channel_rcu(struct rcu_head *head) static void free_relayd_rcu(struct rcu_head *head) { struct lttng_ht_node_u64 *node = - caa_container_of(head, struct lttng_ht_node_u64, head); + lttng::utils::container_of(head, <tng_ht_node_u64::head); struct consumer_relayd_sock_pair *relayd = - caa_container_of(node, struct consumer_relayd_sock_pair, node); + lttng::utils::container_of(node, &consumer_relayd_sock_pair::node); /* * Close all sockets. This is done in the call RCU since we don't want the @@ -381,6 +383,12 @@ void consumer_del_channel(struct lttng_consumer_channel *channel) consumer_timer_monitor_stop(channel); } + /* + * Send a last buffer statistics sample to the session daemon + * to ensure it tracks the amount of data consumed by this channel. + */ + sample_and_send_channel_buffer_stats(channel); + switch (the_consumer_data.type) { case LTTNG_CONSUMER_KERNEL: break; @@ -703,7 +711,7 @@ struct consumer_relayd_sock_pair *consumer_find_relayd(uint64_t key) lttng_ht_lookup(the_consumer_data.relayd_ht, &key, &iter); node = lttng_ht_iter_get_node_u64(&iter); if (node != NULL) { - relayd = caa_container_of(node, struct consumer_relayd_sock_pair, node); + relayd = lttng::utils::container_of(node, &consumer_relayd_sock_pair::node); } error: @@ -2159,7 +2167,7 @@ void consumer_del_metadata_stream(struct lttng_consumer_stream *stream, consumer_stream_delete(stream, ht); /* Close down everything including the relayd if one. */ - consumer_stream_close(stream); + consumer_stream_close_output(stream); /* Destroy tracer buffers of the stream. */ consumer_stream_destroy_buffers(stream); @@ -2711,7 +2719,7 @@ void *consumer_thread_data_poll(void *data) consumer_del_stream(local_stream[i], data_ht); local_stream[i] = NULL; } else if (len > 0) { - local_stream[i]->data_read = 1; + local_stream[i]->has_data_left_to_be_read_before_teardown = 1; } } } @@ -2742,7 +2750,7 @@ void *consumer_thread_data_poll(void *data) consumer_del_stream(local_stream[i], data_ht); local_stream[i] = NULL; } else if (len > 0) { - local_stream[i]->data_read = 1; + local_stream[i]->has_data_left_to_be_read_before_teardown = 1; } } } @@ -2762,37 +2770,45 @@ void *consumer_thread_data_poll(void *data) pollfd[i].fd); lttng_ustconsumer_on_stream_hangup(local_stream[i]); /* Attempt read again, for the data we just flushed. */ - local_stream[i]->data_read = 1; + local_stream[i]->has_data_left_to_be_read_before_teardown = 1; } /* + * When a stream's pipe dies (hup/err/nval), an "inactive producer" flush is + * performed. This type of flush ensures that a new packet is produced no + * matter the consumed/produced positions are. + * + * This, in turn, causes the next pass to see that data available for the + * stream. When we come back here, we can be assured that all available + * data has been consumed and we can finally destroy the stream. + * * If the poll flag is HUP/ERR/NVAL and we have * read no data in this pass, we can remove the * stream from its hash table. */ if ((pollfd[i].revents & POLLHUP)) { DBG("Polling fd %d tells it has hung up.", pollfd[i].fd); - if (!local_stream[i]->data_read) { + if (!local_stream[i]->has_data_left_to_be_read_before_teardown) { consumer_del_stream(local_stream[i], data_ht); local_stream[i] = NULL; num_hup++; } } else if (pollfd[i].revents & POLLERR) { ERR("Error returned in polling fd %d.", pollfd[i].fd); - if (!local_stream[i]->data_read) { + if (!local_stream[i]->has_data_left_to_be_read_before_teardown) { consumer_del_stream(local_stream[i], data_ht); local_stream[i] = NULL; num_hup++; } } else if (pollfd[i].revents & POLLNVAL) { ERR("Polling fd %d tells fd is not open.", pollfd[i].fd); - if (!local_stream[i]->data_read) { + if (!local_stream[i]->has_data_left_to_be_read_before_teardown) { consumer_del_stream(local_stream[i], data_ht); local_stream[i] = NULL; num_hup++; } } if (local_stream[i] != NULL) { - local_stream[i]->data_read = 0; + local_stream[i]->has_data_left_to_be_read_before_teardown = 0; } } } @@ -4695,7 +4711,7 @@ end: enum lttcomm_return_code lttng_consumer_init_command( struct lttng_consumer_local_data *ctx, - const lttng_uuid sessiond_uuid) + const lttng_uuid& sessiond_uuid) { enum lttcomm_return_code ret; char uuid_str[LTTNG_UUID_STR_LEN]; @@ -4706,7 +4722,7 @@ enum lttcomm_return_code lttng_consumer_init_command( } ctx->sessiond_uuid.is_set = true; - memcpy(ctx->sessiond_uuid.value, sessiond_uuid, sizeof(lttng_uuid)); + ctx->sessiond_uuid.value = sessiond_uuid; ret = LTTCOMM_CONSUMERD_SUCCESS; lttng_uuid_to_str(sessiond_uuid, uuid_str); DBG("Received session daemon UUID: %s", uuid_str);