Use compiler-agnostic defines to silence warning
[lttng-tools.git] / src / common / consumer / consumer-metadata-cache.cpp
CommitLineData
331744e3 1/*
ab5be9fa
MJ
2 * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
3 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
331744e3 4 *
ab5be9fa 5 * SPDX-License-Identifier: GPL-2.0-only
331744e3 6 *
331744e3
JD
7 */
8
6c1c0768 9#define _LGPL_SOURCE
28ab034a 10#include "consumer-metadata-cache.hpp"
331744e3 11
c9e313bc 12#include <common/common.hpp>
28ab034a 13#include <common/consumer/consumer.hpp>
c9e313bc
SM
14#include <common/sessiond-comm/sessiond-comm.hpp>
15#include <common/ust-consumer/ust-consumer.hpp>
28ab034a 16#include <common/utils.hpp>
331744e3 17
28ab034a
JG
18#include <inttypes.h>
19#include <pthread.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/types.h>
23#include <unistd.h>
331744e3 24
b1316da1
JG
25enum metadata_cache_update_version_status {
26 METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED,
27 METADATA_CACHE_UPDATE_STATUS_VERSION_NOT_UPDATED,
28};
29
fa29bfbf 30extern struct lttng_consumer_global_data the_consumer_data;
fe81e5c9 31
93ec662e
JD
32/*
33 * Reset the metadata cache.
34 */
28ab034a 35static void metadata_cache_reset(struct consumer_metadata_cache *cache)
93ec662e 36{
9eac9828
JG
37 const int ret = lttng_dynamic_buffer_set_size(&cache->contents, 0);
38
a0377dfe 39 LTTNG_ASSERT(ret == 0);
93ec662e
JD
40}
41
42/*
43 * Check if the metadata cache version changed.
44 * If it did, reset the metadata cache.
45 * The metadata cache lock MUST be held.
93ec662e 46 */
28ab034a
JG
47static enum metadata_cache_update_version_status
48metadata_cache_update_version(struct consumer_metadata_cache *cache, uint64_t version)
93ec662e 49{
b1316da1 50 enum metadata_cache_update_version_status status;
93ec662e
JD
51
52 if (cache->version == version) {
b1316da1 53 status = METADATA_CACHE_UPDATE_STATUS_VERSION_NOT_UPDATED;
93ec662e
JD
54 goto end;
55 }
56
57 DBG("Metadata cache version update to %" PRIu64, version);
93ec662e 58 cache->version = version;
b1316da1 59 status = METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED;
93ec662e
JD
60
61end:
b1316da1 62 return status;
5b8eb761
JD
63}
64
331744e3
JD
65/*
66 * Write metadata to the cache, extend the cache if necessary. We support
c585821b
MD
67 * overlapping updates, but they need to be contiguous. Send the
68 * contiguous metadata in cache to the ring buffer. The metadata cache
331744e3
JD
69 * lock MUST be acquired to write in the cache.
70 *
b1316da1
JG
71 * See `enum consumer_metadata_cache_write_status` for the meaning of the
72 * various returned status codes.
331744e3 73 */
b1316da1 74enum consumer_metadata_cache_write_status
a25d34bc 75consumer_metadata_cache_write(struct consumer_metadata_cache *cache,
28ab034a
JG
76 unsigned int offset,
77 unsigned int len,
78 uint64_t version,
79 const char *data)
331744e3
JD
80{
81 int ret = 0;
b1316da1
JG
82 enum consumer_metadata_cache_write_status status;
83 bool cache_is_invalidated = false;
9eac9828 84 uint64_t original_size;
331744e3 85
a0377dfe 86 LTTNG_ASSERT(cache);
b1316da1 87 ASSERT_LOCKED(cache->lock);
9eac9828 88 original_size = cache->contents.size;
93ec662e 89
b1316da1 90 if (metadata_cache_update_version(cache, version) ==
28ab034a 91 METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED) {
b1316da1
JG
92 metadata_cache_reset(cache);
93 cache_is_invalidated = true;
93ec662e
JD
94 }
95
331744e3 96 DBG("Writing %u bytes from offset %u in metadata cache", len, offset);
9eac9828 97 if (offset + len > cache->contents.size) {
28ab034a 98 ret = lttng_dynamic_buffer_set_size(&cache->contents, offset + len);
9eac9828 99 if (ret) {
331744e3 100 ERR("Extending metadata cache");
b1316da1 101 status = CONSUMER_METADATA_CACHE_WRITE_STATUS_ERROR;
331744e3
JD
102 goto end;
103 }
104 }
105
9eac9828 106 memcpy(cache->contents.data + offset, data, len);
b1316da1
JG
107
108 if (cache_is_invalidated) {
109 status = CONSUMER_METADATA_CACHE_WRITE_STATUS_INVALIDATED;
9eac9828 110 } else if (cache->contents.size > original_size) {
b1316da1
JG
111 status = CONSUMER_METADATA_CACHE_WRITE_STATUS_APPENDED_CONTENT;
112 } else {
113 status = CONSUMER_METADATA_CACHE_WRITE_STATUS_NO_CHANGE;
a0377dfe 114 LTTNG_ASSERT(cache->contents.size == original_size);
331744e3
JD
115 }
116
117end:
b1316da1 118 return status;
331744e3
JD
119}
120
121/*
122 * Create the metadata cache, original allocated size: max_sb_size
123 *
124 * Return 0 on success, a negative value on error.
125 */
126int consumer_metadata_cache_allocate(struct lttng_consumer_channel *channel)
127{
128 int ret;
129
a0377dfe 130 LTTNG_ASSERT(channel);
7134be82 131 LTTNG_ASSERT(!channel->is_deleted);
331744e3 132
64803277 133 channel->metadata_cache = zmalloc<consumer_metadata_cache>();
331744e3
JD
134 if (!channel->metadata_cache) {
135 PERROR("zmalloc metadata cache struct");
136 ret = -1;
137 goto end;
138 }
cd9adb8b 139 ret = pthread_mutex_init(&channel->metadata_cache->lock, nullptr);
331744e3
JD
140 if (ret != 0) {
141 PERROR("mutex init");
142 goto end_free_cache;
143 }
144
9eac9828 145 lttng_dynamic_buffer_init(&channel->metadata_cache->contents);
28ab034a
JG
146 ret = lttng_dynamic_buffer_set_capacity(&channel->metadata_cache->contents,
147 DEFAULT_METADATA_CACHE_SIZE);
9eac9828
JG
148 if (ret) {
149 PERROR("Failed to pre-allocate metadata cache storage of %d bytes on creation",
28ab034a 150 DEFAULT_METADATA_CACHE_SIZE);
331744e3
JD
151 ret = -1;
152 goto end_free_mutex;
153 }
9eac9828
JG
154
155 DBG("Allocated metadata cache: current capacity = %zu",
28ab034a 156 lttng_dynamic_buffer_get_capacity_left(&channel->metadata_cache->contents));
331744e3
JD
157
158 ret = 0;
159 goto end;
160
161end_free_mutex:
162 pthread_mutex_destroy(&channel->metadata_cache->lock);
163end_free_cache:
164 free(channel->metadata_cache);
165end:
166 return ret;
167}
168
169/*
170 * Destroy and free the metadata cache
171 */
172void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel)
173{
174 if (!channel || !channel->metadata_cache) {
175 return;
176 }
177
178 DBG("Destroying metadata cache");
179
331744e3 180 pthread_mutex_destroy(&channel->metadata_cache->lock);
9eac9828 181 lttng_dynamic_buffer_reset(&channel->metadata_cache->contents);
331744e3
JD
182 free(channel->metadata_cache);
183}
184
185/*
186 * Check if the cache is flushed up to the offset passed in parameter.
187 *
f40b76ae 188 * Return true if everything has been flushed, false if there is data not flushed.
331744e3 189 */
f40b76ae
JG
190namespace {
191bool consumer_metadata_cache_is_flushed(struct lttng_consumer_channel *channel,
192 uint64_t offset,
193 int timer)
331744e3 194{
f40b76ae 195 bool done_flushing = false;
04ef1097 196 struct lttng_consumer_stream *metadata_stream;
331744e3 197
7f725ec5 198 /*
5e41ebe1
MD
199 * If not called from a timer handler, we have to take the
200 * channel lock to be mutually exclusive with channel teardown.
201 * Timer handler does not need to take this lock because it is
202 * already synchronized by timer stop (and, more importantly,
203 * taking this lock in a timer handler would cause a deadlock).
7f725ec5 204 */
5e41ebe1
MD
205 if (!timer) {
206 pthread_mutex_lock(&channel->lock);
207 }
ec6ea7d0 208 pthread_mutex_lock(&channel->timer_lock);
04ef1097 209 metadata_stream = channel->metadata_stream;
04ef1097 210 if (!metadata_stream) {
fe81e5c9
DG
211 /*
212 * Having no metadata stream means the channel is being destroyed so there
213 * is no cache to flush anymore.
214 */
f40b76ae 215 done_flushing = true;
e524139e
JG
216 goto end_unlock_channel;
217 }
218
219 pthread_mutex_lock(&metadata_stream->lock);
220 pthread_mutex_lock(&channel->metadata_cache->lock);
221
222 if (metadata_stream->ust_metadata_pushed >= offset) {
f40b76ae 223 done_flushing = true;
28ab034a 224 } else if (channel->metadata_stream->endpoint_status != CONSUMER_ENDPOINT_ACTIVE) {
fe81e5c9 225 /* An inactive endpoint means we don't have to flush anymore. */
f40b76ae 226 done_flushing = true;
331744e3 227 } else {
fe81e5c9 228 /* Still not completely flushed. */
f40b76ae 229 done_flushing = false;
331744e3 230 }
fe81e5c9 231
331744e3 232 pthread_mutex_unlock(&channel->metadata_cache->lock);
8e1ef46e 233 pthread_mutex_unlock(&metadata_stream->lock);
f40b76ae 234
e524139e 235end_unlock_channel:
ec6ea7d0 236 pthread_mutex_unlock(&channel->timer_lock);
5e41ebe1
MD
237 if (!timer) {
238 pthread_mutex_unlock(&channel->lock);
239 }
331744e3 240
f40b76ae
JG
241 return done_flushing;
242}
243} /* namespace */
244
245/*
246 * Wait until the cache is flushed up to the offset passed in parameter or the
247 * metadata stream has been destroyed.
248 */
249void consumer_wait_metadata_cache_flushed(struct lttng_consumer_channel *channel,
250 uint64_t offset,
251 bool invoked_by_timer)
252{
253 assert(channel);
7134be82 254 assert(!channel->is_deleted);
f40b76ae
JG
255 assert(channel->metadata_cache);
256
257 if (consumer_metadata_cache_is_flushed(channel, offset, invoked_by_timer)) {
258 return;
259 }
260
261 /* Metadata cache is not currently flushed, wait on wait queue. */
262 for (;;) {
32670d71 263 lttng::synchro::waiter waiter;
f40b76ae 264
32670d71 265 channel->metadata_pushed_wait_queue.add(waiter);
f40b76ae
JG
266 if (consumer_metadata_cache_is_flushed(channel, offset, invoked_by_timer)) {
267 /* Wake up all waiters, ourself included. */
32670d71 268 channel->metadata_pushed_wait_queue.wake_all();
f40b76ae 269 /* Ensure proper teardown of waiter. */
32670d71 270 waiter.wait();
f40b76ae
JG
271 break;
272 }
273
32670d71 274 waiter.wait();
f40b76ae 275 }
331744e3 276}
This page took 0.098485 seconds and 4 git commands to generate.