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 extern struct lttng_consumer_global_data consumer_data
;
29 * Extend the allocated size of the metadata cache. Called only from
30 * lttng_ustconsumer_write_metadata_cache.
32 * Return 0 on success, a negative value on error.
34 static int extend_metadata_cache(struct lttng_consumer_channel
*channel
,
39 unsigned int new_size
, old_size
;
42 assert(channel
->metadata_cache
);
44 old_size
= channel
->metadata_cache
->cache_alloc_size
;
45 new_size
= max_t(unsigned int, old_size
+ size
, old_size
<< 1);
46 DBG("Extending metadata cache to %u", new_size
);
47 tmp_data_ptr
= realloc(channel
->metadata_cache
->data
, new_size
);
49 ERR("Reallocating metadata cache");
50 free(channel
->metadata_cache
->data
);
54 /* Zero newly allocated memory */
55 memset(tmp_data_ptr
+ old_size
, 0, new_size
- old_size
);
56 channel
->metadata_cache
->data
= tmp_data_ptr
;
57 channel
->metadata_cache
->cache_alloc_size
= new_size
;
64 * Reset the metadata cache.
67 void metadata_cache_reset(struct consumer_metadata_cache
*cache
)
69 memset(cache
->data
, 0, cache
->cache_alloc_size
);
70 cache
->max_offset
= 0;
74 * Check if the metadata cache version changed.
75 * If it did, reset the metadata cache.
76 * The metadata cache lock MUST be held.
78 * Returns 0 on success, a negative value on error.
81 int metadata_cache_check_version(struct consumer_metadata_cache
*cache
,
86 if (cache
->version
== version
) {
90 DBG("Metadata cache version update to %" PRIu64
, version
);
91 metadata_cache_reset(cache
);
92 cache
->version
= version
;
99 * Write a character on the metadata poll pipe to wake the metadata thread.
100 * Returns 0 on success, -1 on error.
102 int consumer_metadata_wakeup_pipe(const struct lttng_consumer_channel
*channel
)
105 const char dummy
= 'c';
107 if (channel
->monitor
&& channel
->metadata_stream
) {
110 write_ret
= lttng_write(channel
->metadata_stream
->ust_metadata_poll_pipe
[1],
113 if (errno
== EWOULDBLOCK
) {
115 * This is fine, the metadata poll thread
116 * is having a hard time keeping-up, but
117 * it will eventually wake-up and consume
118 * the available data.
122 PERROR("Wake-up UST metadata pipe");
134 * Write metadata to the cache, extend the cache if necessary. We support
135 * overlapping updates, but they need to be contiguous. Send the
136 * contiguous metadata in cache to the ring buffer. The metadata cache
137 * lock MUST be acquired to write in the cache.
139 * Return 0 on success, a negative value on error.
141 int consumer_metadata_cache_write(struct lttng_consumer_channel
*channel
,
142 unsigned int offset
, unsigned int len
, uint64_t version
,
146 struct consumer_metadata_cache
*cache
;
149 assert(channel
->metadata_cache
);
151 cache
= channel
->metadata_cache
;
153 ret
= metadata_cache_check_version(cache
, version
);
158 DBG("Writing %u bytes from offset %u in metadata cache", len
, offset
);
160 if (offset
+ len
> cache
->cache_alloc_size
) {
161 ret
= extend_metadata_cache(channel
,
162 len
- cache
->cache_alloc_size
+ offset
);
164 ERR("Extending metadata cache");
169 memcpy(cache
->data
+ offset
, data
, len
);
170 if (offset
+ len
> cache
->max_offset
) {
171 cache
->max_offset
= offset
+ len
;
172 ret
= consumer_metadata_wakeup_pipe(channel
);
180 * Create the metadata cache, original allocated size: max_sb_size
182 * Return 0 on success, a negative value on error.
184 int consumer_metadata_cache_allocate(struct lttng_consumer_channel
*channel
)
190 channel
->metadata_cache
= zmalloc(
191 sizeof(struct consumer_metadata_cache
));
192 if (!channel
->metadata_cache
) {
193 PERROR("zmalloc metadata cache struct");
197 ret
= pthread_mutex_init(&channel
->metadata_cache
->lock
, NULL
);
199 PERROR("mutex init");
203 channel
->metadata_cache
->cache_alloc_size
= DEFAULT_METADATA_CACHE_SIZE
;
204 channel
->metadata_cache
->data
= zmalloc(
205 channel
->metadata_cache
->cache_alloc_size
* sizeof(char));
206 if (!channel
->metadata_cache
->data
) {
207 PERROR("zmalloc metadata cache data");
211 DBG("Allocated metadata cache of %" PRIu64
" bytes",
212 channel
->metadata_cache
->cache_alloc_size
);
218 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
220 free(channel
->metadata_cache
);
226 * Destroy and free the metadata cache
228 void consumer_metadata_cache_destroy(struct lttng_consumer_channel
*channel
)
230 if (!channel
|| !channel
->metadata_cache
) {
234 DBG("Destroying metadata cache");
236 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
237 free(channel
->metadata_cache
->data
);
238 free(channel
->metadata_cache
);
242 * Check if the cache is flushed up to the offset passed in parameter.
244 * Return 0 if everything has been flushed, 1 if there is data not flushed.
246 int consumer_metadata_cache_flushed(struct lttng_consumer_channel
*channel
,
247 uint64_t offset
, int timer
)
250 struct lttng_consumer_stream
*metadata_stream
;
253 assert(channel
->metadata_cache
);
256 * If not called from a timer handler, we have to take the
257 * channel lock to be mutually exclusive with channel teardown.
258 * Timer handler does not need to take this lock because it is
259 * already synchronized by timer stop (and, more importantly,
260 * taking this lock in a timer handler would cause a deadlock).
263 pthread_mutex_lock(&channel
->lock
);
265 pthread_mutex_lock(&channel
->timer_lock
);
266 metadata_stream
= channel
->metadata_stream
;
267 if (!metadata_stream
) {
269 * Having no metadata stream means the channel is being destroyed so there
270 * is no cache to flush anymore.
273 goto end_unlock_channel
;
276 pthread_mutex_lock(&metadata_stream
->lock
);
277 pthread_mutex_lock(&channel
->metadata_cache
->lock
);
279 if (metadata_stream
->ust_metadata_pushed
>= offset
) {
281 } else if (channel
->metadata_stream
->endpoint_status
!=
282 CONSUMER_ENDPOINT_ACTIVE
) {
283 /* An inactive endpoint means we don't have to flush anymore. */
286 /* Still not completely flushed. */
290 pthread_mutex_unlock(&channel
->metadata_cache
->lock
);
291 pthread_mutex_unlock(&metadata_stream
->lock
);
293 pthread_mutex_unlock(&channel
->timer_lock
);
295 pthread_mutex_unlock(&channel
->lock
);