UST periodical metadata flush
[lttng-tools.git] / src / common / ust-consumer / ust-consumer.c
index 442925754c634ec4d067382b5cdd7ed8f35b385e..431b94626736d042d92db89db0774e7e941cc3e7 100644 (file)
 #include <inttypes.h>
 #include <unistd.h>
 #include <urcu/list.h>
+#include <signal.h>
 
 #include <common/common.h>
 #include <common/sessiond-comm/sessiond-comm.h>
 #include <common/relayd/relayd.h>
 #include <common/compat/fcntl.h>
+#include <common/consumer-metadata-cache.h>
+#include <common/consumer-timer.h>
 
 #include "ust-consumer.h"
 
@@ -88,17 +91,17 @@ static int add_channel(struct lttng_consumer_channel *channel,
        if (ctx->on_recv_channel != NULL) {
                ret = ctx->on_recv_channel(channel);
                if (ret == 0) {
-                       ret = consumer_add_channel(channel);
+                       ret = consumer_add_channel(channel, ctx);
                } else if (ret < 0) {
                        /* Most likely an ENOMEM. */
                        lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR);
                        goto error;
                }
        } else {
-               ret = consumer_add_channel(channel);
+               ret = consumer_add_channel(channel, ctx);
        }
 
-       DBG("UST consumer channel added (key: %u)", channel->key);
+       DBG("UST consumer channel added (key: %" PRIu64 ")", channel->key);
 
 error:
        return ret;
@@ -109,7 +112,7 @@ error:
  */
 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, unsigned long key, enum lttng_event_output output)
+               int relayd_id, uint64_t key, enum lttng_event_output output)
 {
        assert(pathname);
        assert(name);
@@ -223,8 +226,8 @@ static int send_stream_to_relayd(struct lttng_consumer_stream *stream)
                if (ret < 0) {
                        goto error;
                }
-       } else if (stream->net_seq_idx != -1) {
-               ERR("Network sequence index %d unknown. Not adding stream.",
+       } else if (stream->net_seq_idx != (uint64_t) -1ULL) {
+               ERR("Network sequence index %" PRIu64 " unknown. Not adding stream.",
                                stream->net_seq_idx);
                ret = -1;
                goto error;
@@ -234,6 +237,11 @@ error:
        return ret;
 }
 
+/*
+ * Create streams for the given channel using liblttng-ust-ctl.
+ *
+ * Return 0 on success else a negative value.
+ */
 static int create_ust_streams(struct lttng_consumer_channel *channel,
                struct lttng_consumer_local_data *ctx)
 {
@@ -251,7 +259,7 @@ static int create_ust_streams(struct lttng_consumer_channel *channel,
        while ((ustream = ustctl_create_stream(channel->uchan, cpu))) {
                int wait_fd;
 
-               wait_fd = ustctl_get_wait_fd(ustream);
+               wait_fd = ustctl_stream_get_wait_fd(ustream);
 
                /* Allocate consumer stream object. */
                stream = allocate_stream(cpu, wait_fd, channel, ctx, &ret);
@@ -288,11 +296,16 @@ static int create_ust_streams(struct lttng_consumer_channel *channel,
                        }
                }
 
-               DBG("UST consumer add stream %s (key: %d) with relayd id %" PRIu64,
+               DBG("UST consumer add stream %s (key: %" PRIu64 ") with relayd id %" PRIu64,
                                stream->name, stream->key, stream->relayd_stream_id);
 
                /* Set next CPU stream. */
                channel->streams.count = ++cpu;
+
+               /* Keep stream reference when creating metadata. */
+               if (channel->type == CONSUMER_CHANNEL_TYPE_METADATA) {
+                       channel->metadata_stream = stream;
+               }
        }
 
        return 0;
@@ -338,6 +351,11 @@ error_create:
        return ret;
 }
 
+/*
+ * Send a single given stream to the session daemon using the sock.
+ *
+ * Return 0 on success else a negative value.
+ */
 static int send_sessiond_stream(int sock, struct lttng_consumer_stream *stream)
 {
        int ret;
@@ -345,7 +363,7 @@ static int send_sessiond_stream(int sock, struct lttng_consumer_stream *stream)
        assert(stream);
        assert(sock >= 0);
 
-       DBG2("UST consumer sending stream %d to sessiond", stream->key);
+       DBG2("UST consumer sending stream %" PRIu64 " to sessiond", stream->key);
 
        /* Send stream to session daemon. */
        ret = ustctl_send_stream_to_sessiond(sock, stream->ustream);
@@ -353,11 +371,6 @@ static int send_sessiond_stream(int sock, struct lttng_consumer_stream *stream)
                goto error;
        }
 
-       ret = ustctl_stream_close_wakeup_fd(stream->ustream);
-       if (ret < 0) {
-               goto error;
-       }
-
 error:
        return ret;
 }
@@ -365,8 +378,7 @@ error:
 /*
  * Send channel to sessiond.
  *
- * Return 0 on success or else a negative value. On error, the channel is
- * destroy using ustctl.
+ * Return 0 on success or else a negative value.
  */
 static int send_sessiond_channel(int sock,
                struct lttng_consumer_channel *channel,
@@ -387,6 +399,11 @@ static int send_sessiond_channel(int sock,
                goto error;
        }
 
+       ret = ustctl_channel_close_wakeup_fd(channel->uchan);
+       if (ret < 0) {
+               goto error;
+       }
+
        /* The channel was sent successfully to the sessiond at this point. */
        cds_list_for_each_entry(stream, &channel->streams.head, send_node) {
                /* Try to send the stream to the relayd if one is available. */
@@ -462,6 +479,12 @@ static int ask_channel(struct lttng_consumer_local_data *ctx, int sock,
                goto error;
        }
 
+       channel->wait_fd = ustctl_channel_get_wait_fd(channel->uchan);
+
+       if (ret < 0) {
+               goto error;
+       }
+
        /* Open all streams for this channel. */
        ret = create_ust_streams(channel, ctx);
        if (ret < 0) {
@@ -472,6 +495,244 @@ error:
        return ret;
 }
 
+/*
+ * Send all stream of a channel to the right thread handling it.
+ *
+ * On error, return a negative value else 0 on success.
+ */
+static int send_streams_to_thread(struct lttng_consumer_channel *channel,
+               struct lttng_consumer_local_data *ctx)
+{
+       int ret = 0;
+       struct lttng_consumer_stream *stream, *stmp;
+
+       assert(channel);
+       assert(ctx);
+
+       /* Send streams to the corresponding thread. */
+       cds_list_for_each_entry_safe(stream, stmp, &channel->streams.head,
+                       send_node) {
+               /* Sending the stream to the thread. */
+               ret = send_stream_to_thread(stream, ctx);
+               if (ret < 0) {
+                       /*
+                        * If we are unable to send the stream to the thread, there is
+                        * a big problem so just stop everything.
+                        */
+                       goto error;
+               }
+
+               /* Remove node from the channel stream list. */
+               cds_list_del(&stream->send_node);
+       }
+
+error:
+       return ret;
+}
+
+/*
+ * Write metadata to the given channel using ustctl to convert the string to
+ * the ringbuffer.
+ * Called only from consumer_metadata_cache_write.
+ * The metadata cache lock MUST be acquired to write in the cache.
+ *
+ * Return 0 on success else a negative value.
+ */
+int lttng_ustconsumer_push_metadata(struct lttng_consumer_channel *metadata,
+               const char *metadata_str, uint64_t target_offset, uint64_t len)
+{
+       int ret;
+
+       assert(metadata);
+       assert(metadata_str);
+
+       DBG("UST consumer writing metadata to channel %s", metadata->name);
+
+       assert(target_offset <= metadata->metadata_cache->max_offset);
+       ret = ustctl_write_metadata_to_channel(metadata->uchan,
+                       metadata_str + target_offset, len);
+       if (ret < 0) {
+               ERR("ustctl write metadata fail with ret %d, len %ld", ret, len);
+               goto error;
+       }
+
+       ustctl_flush_buffer(metadata->metadata_stream->ustream, 1);
+
+error:
+       return ret;
+}
+
+/*
+ * Flush channel's streams using the given key to retrieve the channel.
+ *
+ * Return 0 on success else an LTTng error code.
+ */
+static int flush_channel(uint64_t chan_key)
+{
+       int ret = 0;
+       struct lttng_consumer_channel *channel;
+       struct lttng_consumer_stream *stream;
+       struct lttng_ht *ht;
+       struct lttng_ht_iter iter;
+
+       DBG("UST consumer flush channel key %lu", chan_key);
+
+       channel = consumer_find_channel(chan_key);
+       if (!channel) {
+               ERR("UST consumer flush channel %lu not found", chan_key);
+               ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
+               goto error;
+       }
+
+       ht = consumer_data.stream_per_chan_id_ht;
+
+       /* For each stream of the channel id, flush it. */
+       rcu_read_lock();
+       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);
+       }
+       rcu_read_unlock();
+
+error:
+       return ret;
+}
+
+/*
+ * Close metadata stream wakeup_fd using the given key to retrieve the channel.
+ *
+ * Return 0 on success else an LTTng error code.
+ */
+static int close_metadata(uint64_t chan_key)
+{
+       int ret;
+       struct lttng_consumer_channel *channel;
+
+       DBG("UST consumer close metadata key %lu", chan_key);
+
+       channel = consumer_find_channel(chan_key);
+       if (!channel) {
+               ERR("UST consumer close metadata %lu not found", chan_key);
+               ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
+               goto error;
+       }
+
+       ret = ustctl_stream_close_wakeup_fd(channel->metadata_stream->ustream);
+       if (ret < 0) {
+               ERR("UST consumer unable to close fd of metadata (ret: %d)", ret);
+               ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
+               goto error;
+       }
+       if (channel->switch_timer_enabled == 1) {
+               DBG("Deleting timer on metadata channel");
+               consumer_timer_switch_stop(channel);
+       }
+       consumer_metadata_cache_destroy(channel);
+
+error:
+       return ret;
+}
+
+/*
+ * RCU read side lock MUST be acquired before calling this function.
+ *
+ * Return 0 on success else an LTTng error code.
+ */
+static int setup_metadata(struct lttng_consumer_local_data *ctx, uint64_t key)
+{
+       int ret;
+       struct lttng_consumer_channel *metadata;
+
+       DBG("UST consumer setup metadata key %lu", key);
+
+       metadata = consumer_find_channel(key);
+       if (!metadata) {
+               ERR("UST consumer push metadata %" PRIu64 " not found", key);
+               ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
+               goto error;
+       }
+
+       /*
+        * Send metadata stream to relayd if one available. Availability is
+        * known if the stream is still in the list of the channel.
+        */
+       if (cds_list_empty(&metadata->streams.head)) {
+               ERR("Metadata channel key %" PRIu64 ", no stream available.", key);
+               ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
+               goto error;
+       }
+
+       /* Send metadata stream to relayd if needed. */
+       ret = send_stream_to_relayd(metadata->metadata_stream);
+       if (ret < 0) {
+               ret = LTTCOMM_CONSUMERD_ERROR_METADATA;
+               goto error;
+       }
+
+       ret = send_streams_to_thread(metadata, ctx);
+       if (ret < 0) {
+               /*
+                * If we are unable to send the stream to the thread, there is
+                * a big problem so just stop everything.
+                */
+               ret = LTTCOMM_CONSUMERD_FATAL;
+               goto error;
+       }
+       /* List MUST be empty after or else it could be reused. */
+       assert(cds_list_empty(&metadata->streams.head));
+
+       ret = 0;
+
+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)
+{
+       int ret, ret_code = LTTNG_OK;
+       char *metadata_str;
+
+       DBG("UST consumer push metadata key %lu of len %lu", key, len);
+
+       metadata_str = zmalloc(len * sizeof(char));
+       if (!metadata_str) {
+               PERROR("zmalloc metadata string");
+               ret_code = LTTCOMM_CONSUMERD_ENOMEM;
+               goto end;
+       }
+
+       /* Receive metadata string. */
+       ret = lttcomm_recv_unix_sock(sock, metadata_str, len);
+       if (ret < 0) {
+               /* Session daemon is dead so return gracefully. */
+               ret_code = ret;
+               goto end_free;
+       }
+
+       pthread_mutex_lock(&channel->metadata_cache->lock);
+       ret = consumer_metadata_cache_write(channel, offset, len, metadata_str);
+       if (ret < 0) {
+               /* Unable to handle metadata. Notify session daemon. */
+               ret_code = LTTCOMM_CONSUMERD_ERROR_METADATA;
+       }
+       pthread_mutex_unlock(&channel->metadata_cache->lock);
+
+       while (consumer_metadata_cache_flushed(channel, offset + len)) {
+               DBG("Waiting for metadata to be flushed");
+               usleep(DEFAULT_METADATA_AVAILABILITY_WAIT_TIME);
+       }
+
+end_free:
+       free(metadata_str);
+end:
+       return ret_code;
+}
+
 /*
  * Receive command from session daemon and process it.
  *
@@ -548,13 +809,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                        consumer_flag_relayd_for_destroy(relayd);
                }
 
-               ret = consumer_send_status_msg(sock, ret_code);
-               if (ret < 0) {
-                       /* Somehow, the session daemon is not responding anymore. */
-                       goto end_nosignal;
-               }
-
-               goto end_nosignal;
+               goto end_msg_sessiond;
        }
        case LTTNG_CONSUMER_UPDATE_STREAM:
        {
@@ -604,6 +859,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                attr.overwrite = msg.u.ask_channel.overwrite;
                attr.switch_timer_interval = msg.u.ask_channel.switch_timer_interval;
                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));
 
                /* Translate the event output type to UST. */
@@ -646,6 +902,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                        goto end_channel_error;
                }
 
+
                /*
                 * Channel and streams are now created. Inform the session daemon that
                 * everything went well and should wait to receive the channel and
@@ -660,14 +917,23 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                        goto end_nosignal;
                }
 
+               if (msg.u.ask_channel.type == LTTNG_UST_CHAN_METADATA) {
+                       ret = consumer_metadata_cache_allocate(channel);
+                       if (ret < 0) {
+                               ERR("Allocating metadata cache");
+                               goto end_channel_error;
+                       }
+                       consumer_timer_switch_start(channel, attr.switch_timer_interval);
+                       attr.switch_timer_interval = 0;
+               }
+
                break;
        }
        case LTTNG_CONSUMER_GET_CHANNEL:
        {
                int ret, relayd_err = 0;
-               unsigned long key = msg.u.get_channel.key;
+               uint64_t key = msg.u.get_channel.key;
                struct lttng_consumer_channel *channel;
-               struct lttng_consumer_stream *stream, *stmp;
 
                channel = consumer_find_channel(key);
                if (!channel) {
@@ -702,58 +968,104 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                        goto error_fatal;
                }
 
-               /* Send streams to the corresponding thread. */
-               cds_list_for_each_entry_safe(stream, stmp, &channel->streams.head,
-                               send_node) {
-                       /* Sending the stream to the thread. */
-                       ret = send_stream_to_thread(stream, ctx);
-                       if (ret < 0) {
-                               /*
-                                * If we are unable to send the stream to the thread, there is
-                                * a big problem so just stop everything.
-                                */
-                               goto error_fatal;
-                       }
-
-                       /* Remove node from the channel stream list. */
-                       cds_list_del(&stream->send_node);
+               ret = send_streams_to_thread(channel, ctx);
+               if (ret < 0) {
+                       /*
+                        * If we are unable to send the stream to the thread, there is
+                        * a big problem so just stop everything.
+                        */
+                       goto error_fatal;
                }
-
                /* List MUST be empty after or else it could be reused. */
                assert(cds_list_empty(&channel->streams.head));
 
-               /* Inform sessiond that everything is done and OK on our side. */
-               ret = consumer_send_status_msg(sock, LTTNG_OK);
-               if (ret < 0) {
-                       /* Somehow, the session daemon is not responding anymore. */
-                       goto end_nosignal;
+               goto end_msg_sessiond;
+       }
+       case LTTNG_CONSUMER_DESTROY_CHANNEL:
+       {
+               uint64_t key = msg.u.destroy_channel.key;
+               struct lttng_consumer_channel *channel;
+
+               channel = consumer_find_channel(key);
+               if (!channel) {
+                       ERR("UST consumer get channel key %lu not found", key);
+                       ret_code = LTTNG_ERR_UST_CHAN_NOT_FOUND;
+                       goto end_msg_sessiond;
                }
 
-               break;
+               destroy_channel(channel);
+
+               goto end_msg_sessiond;
        }
-       case LTTNG_CONSUMER_DESTROY_CHANNEL:
+       case LTTNG_CONSUMER_CLOSE_METADATA:
        {
                int ret;
-               unsigned long key = msg.u.destroy_channel.key;
+
+               ret = close_metadata(msg.u.close_metadata.key);
+               if (ret != 0) {
+                       ret_code = ret;
+               }
+
+               goto end_msg_sessiond;
+       }
+       case LTTNG_CONSUMER_FLUSH_CHANNEL:
+       {
+               int ret;
+
+               ret = flush_channel(msg.u.flush_channel.key);
+               if (ret != 0) {
+                       ret_code = ret;
+               }
+
+               goto end_msg_sessiond;
+       }
+       case LTTNG_CONSUMER_PUSH_METADATA:
+       {
+               int ret;
+               uint64_t len = msg.u.push_metadata.len;
+               uint64_t key = msg.u.push_metadata.key;
+               uint64_t offset = msg.u.push_metadata.target_offset;
                struct lttng_consumer_channel *channel;
 
-               DBG("UST consumer destroy channel key %lu", key);
+               DBG("UST consumer push metadata key %lu of len %lu", key, len);
 
                channel = consumer_find_channel(key);
                if (!channel) {
-                       ERR("UST consumer destroy channel %lu not found", key);
+                       ERR("UST consumer push metadata %lu not found", key);
                        ret_code = LTTNG_ERR_UST_CHAN_NOT_FOUND;
-               } else {
-                       /* Protocol error if the stream list is NOT empty. */
-                       assert(!cds_list_empty(&channel->streams.head));
-                       consumer_del_channel(channel);
                }
 
+               /* Tell session daemon we are ready to receive the metadata. */
                ret = consumer_send_status_msg(sock, LTTNG_OK);
                if (ret < 0) {
                        /* Somehow, the session daemon is not responding anymore. */
+                       goto error_fatal;
+               }
+
+               /* Wait for more data. */
+               if (lttng_consumer_poll_socket(consumer_sockpoll) < 0) {
+                       goto end_nosignal;
+               }
+
+               ret = lttng_ustconsumer_recv_metadata(sock, key, offset,
+                               len, channel);
+               if (ret < 0) {
+                       /* error receiving from sessiond */
                        goto end_nosignal;
+               } else {
+                       ret_code = ret;
+                       goto end_msg_sessiond;
+               }
+       }
+       case LTTNG_CONSUMER_SETUP_METADATA:
+       {
+               int ret;
+
+               ret = setup_metadata(ctx, msg.u.setup_metadata.key);
+               if (ret) {
+                       ret_code = ret;
                }
+               goto end_msg_sessiond;
        }
        default:
                break;
@@ -945,8 +1257,8 @@ int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
         * The mmap operation should write subbuf_size amount of data when network
         * streaming or the full padding (len) size when we are _not_ streaming.
         */
-       if ((ret != subbuf_size && stream->net_seq_idx != -1) ||
-                       (ret != len && stream->net_seq_idx == -1)) {
+       if ((ret != subbuf_size && stream->net_seq_idx != (uint64_t) -1ULL) ||
+                       (ret != len && stream->net_seq_idx == (uint64_t) -1ULL)) {
                /*
                 * Display the error but continue processing to try to release the
                 * subbuffer. This is a DBG statement since any unexpected kill or
@@ -961,6 +1273,7 @@ int lttng_ustconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
        }
        err = ustctl_put_next_subbuf(ustream);
        assert(err == 0);
+
 end:
        return ret;
 }
@@ -974,7 +1287,7 @@ int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream)
        char full_path[PATH_MAX];
 
        /* Opening the tracefile in write mode */
-       if (stream->net_seq_idx != -1) {
+       if (stream->net_seq_idx != (uint64_t) -1ULL) {
                goto end;
        }
 
@@ -1033,3 +1346,144 @@ int lttng_ustconsumer_data_pending(struct lttng_consumer_stream *stream)
 end:
        return ret;
 }
+
+/*
+ * Close every metadata stream wait fd of the metadata hash table. This
+ * function MUST be used very carefully so not to run into a race between the
+ * metadata thread handling streams and this function closing their wait fd.
+ *
+ * For UST, this is used when the session daemon hangs up. Its the metadata
+ * producer so calling this is safe because we are assured that no state change
+ * can occur in the metadata thread for the streams in the hash table.
+ */
+void lttng_ustconsumer_close_metadata(struct lttng_ht *metadata_ht)
+{
+       int ret;
+       struct lttng_ht_iter iter;
+       struct lttng_consumer_stream *stream;
+
+       assert(metadata_ht);
+       assert(metadata_ht->ht);
+
+       DBG("UST consumer closing all metadata streams");
+
+       rcu_read_lock();
+       cds_lfht_for_each_entry(metadata_ht->ht, &iter.iter, stream,
+                       node.node) {
+               int fd = stream->wait_fd;
+
+               /*
+                * Whatever happens here we have to continue to try to close every
+                * streams. Let's report at least the error on failure.
+                */
+               ret = ustctl_stream_close_wakeup_fd(stream->ustream);
+               if (ret) {
+                       ERR("Unable to close metadata stream fd %d ret %d", fd, ret);
+               }
+               DBG("Metadata wait fd %d closed", fd);
+       }
+       rcu_read_unlock();
+}
+
+void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream)
+{
+       int ret;
+
+       ret = ustctl_stream_close_wakeup_fd(stream->ustream);
+       if (ret < 0) {
+               ERR("Unable to close wakeup fd");
+       }
+}
+
+int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
+               struct lttng_consumer_channel *channel)
+{
+       struct lttcomm_metadata_request_msg request;
+       struct lttcomm_consumer_msg msg;
+       enum lttng_error_code ret_code = LTTNG_OK;
+       uint64_t len, key, offset;
+       int ret;
+
+       assert(channel);
+       assert(channel->metadata_cache);
+
+       /* send the metadata request to sessiond */
+       switch (consumer_data.type) {
+       case LTTNG_CONSUMER64_UST:
+               request.bits_per_long = 64;
+               break;
+       case LTTNG_CONSUMER32_UST:
+               request.bits_per_long = 32;
+               break;
+       default:
+               request.bits_per_long = 0;
+               break;
+       }
+
+       request.session_id = channel->session_id;
+       request.uid = channel->uid;
+       request.key = channel->key;
+       DBG("Sending metadata request to sessiond, session %" PRIu64,
+                       channel->session_id);
+
+       ret = lttcomm_send_unix_sock(ctx->consumer_metadata_socket, &request,
+                       sizeof(request));
+       if (ret < 0) {
+               ERR("Asking metadata to sessiond");
+               goto end;
+       }
+
+       /* Receive the metadata from sessiond */
+       ret = lttcomm_recv_unix_sock(ctx->consumer_metadata_socket, &msg,
+                       sizeof(msg));
+       if (ret != sizeof(msg)) {
+               DBG("Consumer received unexpected message size %d (expects %lu)",
+                       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.
+                */
+               goto end;
+       }
+
+       if (msg.cmd_type == LTTNG_ERR_UND) {
+               /* No registry found */
+               (void) consumer_send_status_msg(ctx->consumer_metadata_socket,
+                               ret_code);
+               ret = 0;
+               goto end;
+       } else if (msg.cmd_type != LTTNG_CONSUMER_PUSH_METADATA) {
+               ERR("Unexpected cmd_type received %d", msg.cmd_type);
+               ret = -1;
+               goto end;
+       }
+
+       len = msg.u.push_metadata.len;
+       key = msg.u.push_metadata.key;
+       offset = msg.u.push_metadata.target_offset;
+
+       assert(key == channel->key);
+       if (len == 0) {
+               DBG("No new metadata to receive for key %" PRIu64, key);
+       }
+
+       /* Tell session daemon we are ready to receive the metadata. */
+       ret = consumer_send_status_msg(ctx->consumer_metadata_socket,
+                       LTTNG_OK);
+       if (ret < 0 || len == 0) {
+               /*
+                * Somehow, the session daemon is not responding anymore or there is
+                * nothing to receive.
+                */
+               goto end;
+       }
+
+       ret_code = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
+                       key, offset, len, channel);
+       (void) consumer_send_status_msg(ctx->consumer_metadata_socket, ret_code);
+       ret = 0;
+
+end:
+       return ret;
+}
This page took 0.034319 seconds and 5 git commands to generate.