2 * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
3 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
5 * SPDX-License-Identifier: GPL-2.0-only
14 #include <sys/types.h>
18 #include <common/common.h>
19 #include <common/utils.h>
20 #include <common/sessiond-comm/sessiond-comm.h>
21 #include <common/ust-consumer/ust-consumer.h>
22 #include <common/consumer/consumer.h>
24 #include "consumer-metadata-cache.h"
26 enum metadata_cache_update_version_status
{
27 METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED
,
28 METADATA_CACHE_UPDATE_STATUS_VERSION_NOT_UPDATED
,
31 extern struct lttng_consumer_global_data the_consumer_data
;
34 * Reset the metadata cache.
37 void metadata_cache_reset(struct consumer_metadata_cache
*cache
)
39 const int ret
= lttng_dynamic_buffer_set_size(&cache
->contents
, 0);
45 * Check if the metadata cache version changed.
46 * If it did, reset the metadata cache.
47 * The metadata cache lock MUST be held.
49 static enum metadata_cache_update_version_status
metadata_cache_update_version(
50 struct consumer_metadata_cache
*cache
, uint64_t version
)
52 enum metadata_cache_update_version_status status
;
54 if (cache
->version
== version
) {
55 status
= METADATA_CACHE_UPDATE_STATUS_VERSION_NOT_UPDATED
;
59 DBG("Metadata cache version update to %" PRIu64
, version
);
60 cache
->version
= version
;
61 status
= METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED
;
68 * Write metadata to the cache, extend the cache if necessary. We support
69 * overlapping updates, but they need to be contiguous. Send the
70 * contiguous metadata in cache to the ring buffer. The metadata cache
71 * lock MUST be acquired to write in the cache.
73 * See `enum consumer_metadata_cache_write_status` for the meaning of the
74 * various returned status codes.
76 enum consumer_metadata_cache_write_status
77 consumer_metadata_cache_write(struct consumer_metadata_cache
*cache
,
78 unsigned int offset
, unsigned int len
, uint64_t version
,
82 enum consumer_metadata_cache_write_status status
;
83 bool cache_is_invalidated
= false;
84 uint64_t original_size
;
87 ASSERT_LOCKED(cache
->lock
);
88 original_size
= cache
->contents
.size
;
90 if (metadata_cache_update_version(cache
, version
) ==
91 METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED
) {
92 metadata_cache_reset(cache
);
93 cache_is_invalidated
= true;
96 DBG("Writing %u bytes from offset %u in metadata cache", len
, offset
);
97 if (offset
+ len
> cache
->contents
.size
) {
98 ret
= lttng_dynamic_buffer_set_size(
99 &cache
->contents
, offset
+ len
);
101 ERR("Extending metadata cache");
102 status
= CONSUMER_METADATA_CACHE_WRITE_STATUS_ERROR
;
107 memcpy(cache
->contents
.data
+ offset
, data
, len
);
109 if (cache_is_invalidated
) {
110 status
= CONSUMER_METADATA_CACHE_WRITE_STATUS_INVALIDATED
;
111 } else if (cache
->contents
.size
> original_size
) {
112 status
= CONSUMER_METADATA_CACHE_WRITE_STATUS_APPENDED_CONTENT
;
114 status
= CONSUMER_METADATA_CACHE_WRITE_STATUS_NO_CHANGE
;
115 assert(cache
->contents
.size
== original_size
);
123 * Create the metadata cache, original allocated size: max_sb_size
125 * Return 0 on success, a negative value on error.
127 int consumer_metadata_cache_allocate(struct lttng_consumer_channel
*channel
)
133 channel
->metadata_cache
= zmalloc(
134 sizeof(struct consumer_metadata_cache
));
135 if (!channel
->metadata_cache
) {
136 PERROR("zmalloc metadata cache struct");
140 ret
= pthread_mutex_init(&channel
->metadata_cache
->lock
, NULL
);
142 PERROR("mutex init");
146 lttng_dynamic_buffer_init(&channel
->metadata_cache
->contents
);
147 ret
= lttng_dynamic_buffer_set_capacity(
148 &channel
->metadata_cache
->contents
,
149 DEFAULT_METADATA_CACHE_SIZE
);
151 PERROR("Failed to pre-allocate metadata cache storage of %d bytes on creation",
152 DEFAULT_METADATA_CACHE_SIZE
);
157 DBG("Allocated metadata cache: current capacity = %zu",
158 lttng_dynamic_buffer_get_capacity_left(
159 &channel
->metadata_cache
->contents
));
165 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
167 free(channel
->metadata_cache
);
173 * Destroy and free the metadata cache
175 void consumer_metadata_cache_destroy(struct lttng_consumer_channel
*channel
)
177 if (!channel
|| !channel
->metadata_cache
) {
181 DBG("Destroying metadata cache");
183 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
184 lttng_dynamic_buffer_reset(&channel
->metadata_cache
->contents
);
185 free(channel
->metadata_cache
);
189 * Check if the cache is flushed up to the offset passed in parameter.
191 * Return true if everything has been flushed, false if there is data not flushed.
194 bool consumer_metadata_cache_is_flushed(struct lttng_consumer_channel
*channel
,
195 uint64_t offset
, int timer
)
197 bool done_flushing
= false;
198 struct lttng_consumer_stream
*metadata_stream
;
201 * If not called from a timer handler, we have to take the
202 * channel lock to be mutually exclusive with channel teardown.
203 * Timer handler does not need to take this lock because it is
204 * already synchronized by timer stop (and, more importantly,
205 * taking this lock in a timer handler would cause a deadlock).
208 pthread_mutex_lock(&channel
->lock
);
210 pthread_mutex_lock(&channel
->timer_lock
);
211 metadata_stream
= channel
->metadata_stream
;
212 if (!metadata_stream
) {
214 * Having no metadata stream means the channel is being destroyed so there
215 * is no cache to flush anymore.
217 done_flushing
= true;
218 goto end_unlock_channel
;
221 pthread_mutex_lock(&metadata_stream
->lock
);
222 pthread_mutex_lock(&channel
->metadata_cache
->lock
);
224 if (metadata_stream
->ust_metadata_pushed
>= offset
) {
225 done_flushing
= true;
226 } else if (channel
->metadata_stream
->endpoint_status
!=
227 CONSUMER_ENDPOINT_ACTIVE
) {
228 /* An inactive endpoint means we don't have to flush anymore. */
229 done_flushing
= true;
231 /* Still not completely flushed. */
232 done_flushing
= false;
235 pthread_mutex_unlock(&channel
->metadata_cache
->lock
);
236 pthread_mutex_unlock(&metadata_stream
->lock
);
239 pthread_mutex_unlock(&channel
->timer_lock
);
241 pthread_mutex_unlock(&channel
->lock
);
244 return done_flushing
;
248 * Wait until the cache is flushed up to the offset passed in parameter or the
249 * metadata stream has been destroyed.
251 void consumer_wait_metadata_cache_flushed(struct lttng_consumer_channel
*channel
,
252 uint64_t offset
, bool invoked_by_timer
)
255 assert(channel
->metadata_cache
);
257 if (consumer_metadata_cache_is_flushed(channel
, offset
, invoked_by_timer
)) {
261 /* Metadata cache is not currently flushed, wait on wait queue. */
263 struct lttng_waiter waiter
;
265 lttng_waiter_init(&waiter
);
266 lttng_wait_queue_add(&channel
->metadata_pushed_wait_queue
, &waiter
);
267 if (consumer_metadata_cache_is_flushed(channel
, offset
, invoked_by_timer
)) {
268 /* Wake up all waiters, ourself included. */
269 lttng_wait_queue_wake_all(&channel
->metadata_pushed_wait_queue
);
270 /* Ensure proper teardown of waiter. */
271 lttng_waiter_wait(&waiter
);
275 lttng_waiter_wait(&waiter
);