Fix: define _LGPL_SOURCE in C files
[lttng-tools.git] / src / common / consumer-metadata-cache.c
index 888d82f3accae8e5644c7bb42c4b39747d597e2e..9cd99e5bf4d29f090baeb0c8326ce10ba880f2c7 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <assert.h>
 #include <pthread.h>
 #include <stdlib.h>
@@ -33,6 +34,8 @@
 
 #include "consumer-metadata-cache.h"
 
+extern struct lttng_consumer_global_data consumer_data;
+
 /*
  * Extend the allocated size of the metadata cache. Called only from
  * lttng_ustconsumer_write_metadata_cache.
@@ -44,14 +47,13 @@ static int extend_metadata_cache(struct lttng_consumer_channel *channel,
 {
        int ret = 0;
        char *tmp_data_ptr;
-       unsigned int new_size;
+       unsigned int new_size, old_size;
 
        assert(channel);
        assert(channel->metadata_cache);
 
-       new_size = max_t(unsigned int,
-                       channel->metadata_cache->cache_alloc_size + size,
-                       channel->metadata_cache->cache_alloc_size << 1);
+       old_size = channel->metadata_cache->cache_alloc_size;
+       new_size = max_t(unsigned int, old_size + size, old_size << 1);
        DBG("Extending metadata cache to %u", new_size);
        tmp_data_ptr = realloc(channel->metadata_cache->data, new_size);
        if (!tmp_data_ptr) {
@@ -60,6 +62,8 @@ static int extend_metadata_cache(struct lttng_consumer_channel *channel,
                ret = -1;
                goto end;
        }
+       /* Zero newly allocated memory */
+       memset(tmp_data_ptr + old_size, 0, new_size - old_size);
        channel->metadata_cache->data = tmp_data_ptr;
        channel->metadata_cache->cache_alloc_size = new_size;
 
@@ -79,6 +83,7 @@ int consumer_metadata_cache_write(struct lttng_consumer_channel *channel,
                unsigned int offset, unsigned int len, char *data)
 {
        int ret = 0;
+       int size_ret;
        struct consumer_metadata_cache *cache;
 
        assert(channel);
@@ -103,15 +108,18 @@ int consumer_metadata_cache_write(struct lttng_consumer_channel *channel,
        }
 
        if (cache->max_offset == cache->total_bytes_written) {
-               offset = cache->rb_pushed;
-               len = cache->total_bytes_written - cache->rb_pushed;
-               ret = lttng_ustconsumer_push_metadata(channel, cache->data, offset,
-                               len);
-               if (ret < 0) {
-                       ERR("Pushing metadata");
-                       goto end;
+               char dummy = 'c';
+
+               cache->contiguous = cache->max_offset;
+               if (channel->monitor) {
+                       size_ret = lttng_write(channel->metadata_stream->ust_metadata_poll_pipe[1],
+                                       &dummy, 1);
+                       if (size_ret < 1) {
+                               ERR("Wakeup UST metadata pipe");
+                               ret = -1;
+                               goto end;
+                       }
                }
-               cache->rb_pushed += len;
        }
 
 end:
@@ -175,11 +183,6 @@ void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel)
 
        DBG("Destroying metadata cache");
 
-       if (channel->metadata_cache->max_offset >
-                       channel->metadata_cache->rb_pushed) {
-               ERR("Destroying a cache not entirely commited");
-       }
-
        pthread_mutex_destroy(&channel->metadata_cache->lock);
        free(channel->metadata_cache->data);
        free(channel->metadata_cache);
@@ -191,23 +194,51 @@ void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel)
  * Return 0 if everything has been flushed, 1 if there is data not flushed.
  */
 int consumer_metadata_cache_flushed(struct lttng_consumer_channel *channel,
-               uint64_t offset)
+               uint64_t offset, int timer)
 {
-       int ret;
-       struct consumer_metadata_cache *cache;
+       int ret = 0;
+       struct lttng_consumer_stream *metadata_stream;
 
        assert(channel);
        assert(channel->metadata_cache);
 
-       cache = channel->metadata_cache;
-
+       /*
+        * If not called from a timer handler, we have to take the
+        * channel lock to be mutually exclusive with channel teardown.
+        * Timer handler does not need to take this lock because it is
+        * already synchronized by timer stop (and, more importantly,
+        * taking this lock in a timer handler would cause a deadlock).
+        */
+       if (!timer) {
+               pthread_mutex_lock(&channel->lock);
+       }
+       pthread_mutex_lock(&channel->timer_lock);
        pthread_mutex_lock(&channel->metadata_cache->lock);
-       if (cache->rb_pushed >= offset) {
+
+       metadata_stream = channel->metadata_stream;
+
+       if (!metadata_stream) {
+               /*
+                * Having no metadata stream means the channel is being destroyed so there
+                * is no cache to flush anymore.
+                */
+               ret = 0;
+       } else if (metadata_stream->ust_metadata_pushed >= offset) {
+               ret = 0;
+       } else if (channel->metadata_stream->endpoint_status !=
+                       CONSUMER_ENDPOINT_ACTIVE) {
+               /* An inactive endpoint means we don't have to flush anymore. */
                ret = 0;
        } else {
+               /* Still not completely flushed. */
                ret = 1;
        }
+
        pthread_mutex_unlock(&channel->metadata_cache->lock);
+       pthread_mutex_unlock(&channel->timer_lock);
+       if (!timer) {
+               pthread_mutex_unlock(&channel->lock);
+       }
 
        return ret;
 }
This page took 0.024188 seconds and 4 git commands to generate.