common: compile libconsumer, libust-consumer, libkernel-consumer as C++
[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
331744e3
JD
10#include <pthread.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/types.h>
14#include <unistd.h>
15#include <inttypes.h>
16
17#include <common/common.h>
18#include <common/utils.h>
19#include <common/sessiond-comm/sessiond-comm.h>
20#include <common/ust-consumer/ust-consumer.h>
c8fea79c 21#include <common/consumer/consumer.h>
331744e3
JD
22
23#include "consumer-metadata-cache.h"
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 */
35static
36void metadata_cache_reset(struct consumer_metadata_cache *cache)
37{
9eac9828
JG
38 const int ret = lttng_dynamic_buffer_set_size(&cache->contents, 0);
39
a0377dfe 40 LTTNG_ASSERT(ret == 0);
93ec662e
JD
41}
42
43/*
44 * Check if the metadata cache version changed.
45 * If it did, reset the metadata cache.
46 * The metadata cache lock MUST be held.
93ec662e 47 */
b1316da1
JG
48static enum metadata_cache_update_version_status metadata_cache_update_version(
49 struct consumer_metadata_cache *cache, uint64_t version)
93ec662e 50{
b1316da1 51 enum metadata_cache_update_version_status status;
93ec662e
JD
52
53 if (cache->version == version) {
b1316da1 54 status = METADATA_CACHE_UPDATE_STATUS_VERSION_NOT_UPDATED;
93ec662e
JD
55 goto end;
56 }
57
58 DBG("Metadata cache version update to %" PRIu64, version);
93ec662e 59 cache->version = version;
b1316da1 60 status = METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED;
93ec662e
JD
61
62end:
b1316da1 63 return status;
5b8eb761
JD
64}
65
331744e3
JD
66/*
67 * Write metadata to the cache, extend the cache if necessary. We support
c585821b
MD
68 * overlapping updates, but they need to be contiguous. Send the
69 * contiguous metadata in cache to the ring buffer. The metadata cache
331744e3
JD
70 * lock MUST be acquired to write in the cache.
71 *
b1316da1
JG
72 * See `enum consumer_metadata_cache_write_status` for the meaning of the
73 * various returned status codes.
331744e3 74 */
b1316da1 75enum consumer_metadata_cache_write_status
a25d34bc 76consumer_metadata_cache_write(struct consumer_metadata_cache *cache,
93ec662e 77 unsigned int offset, unsigned int len, uint64_t version,
d44f9a18 78 const char *data)
331744e3
JD
79{
80 int ret = 0;
b1316da1
JG
81 enum consumer_metadata_cache_write_status status;
82 bool cache_is_invalidated = false;
9eac9828 83 uint64_t original_size;
331744e3 84
a0377dfe 85 LTTNG_ASSERT(cache);
b1316da1 86 ASSERT_LOCKED(cache->lock);
9eac9828 87 original_size = cache->contents.size;
93ec662e 88
b1316da1
JG
89 if (metadata_cache_update_version(cache, version) ==
90 METADATA_CACHE_UPDATE_STATUS_VERSION_UPDATED) {
91 metadata_cache_reset(cache);
92 cache_is_invalidated = true;
93ec662e
JD
93 }
94
331744e3 95 DBG("Writing %u bytes from offset %u in metadata cache", len, offset);
9eac9828
JG
96 if (offset + len > cache->contents.size) {
97 ret = lttng_dynamic_buffer_set_size(
98 &cache->contents, offset + len);
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);
331744e3 131
97535efa 132 channel->metadata_cache = (consumer_metadata_cache *) zmalloc(
331744e3
JD
133 sizeof(struct consumer_metadata_cache));
134 if (!channel->metadata_cache) {
135 PERROR("zmalloc metadata cache struct");
136 ret = -1;
137 goto end;
138 }
139 ret = pthread_mutex_init(&channel->metadata_cache->lock, NULL);
140 if (ret != 0) {
141 PERROR("mutex init");
142 goto end_free_cache;
143 }
144
9eac9828
JG
145 lttng_dynamic_buffer_init(&channel->metadata_cache->contents);
146 ret = lttng_dynamic_buffer_set_capacity(
147 &channel->metadata_cache->contents,
148 DEFAULT_METADATA_CACHE_SIZE);
149 if (ret) {
150 PERROR("Failed to pre-allocate metadata cache storage of %d bytes on creation",
151 DEFAULT_METADATA_CACHE_SIZE);
331744e3
JD
152 ret = -1;
153 goto end_free_mutex;
154 }
9eac9828
JG
155
156 DBG("Allocated metadata cache: current capacity = %zu",
157 lttng_dynamic_buffer_get_capacity_left(
158 &channel->metadata_cache->contents));
331744e3
JD
159
160 ret = 0;
161 goto end;
162
163end_free_mutex:
164 pthread_mutex_destroy(&channel->metadata_cache->lock);
165end_free_cache:
166 free(channel->metadata_cache);
167end:
168 return ret;
169}
170
171/*
172 * Destroy and free the metadata cache
173 */
174void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel)
175{
176 if (!channel || !channel->metadata_cache) {
177 return;
178 }
179
180 DBG("Destroying metadata cache");
181
331744e3 182 pthread_mutex_destroy(&channel->metadata_cache->lock);
9eac9828 183 lttng_dynamic_buffer_reset(&channel->metadata_cache->contents);
331744e3
JD
184 free(channel->metadata_cache);
185}
186
187/*
188 * Check if the cache is flushed up to the offset passed in parameter.
189 *
190 * Return 0 if everything has been flushed, 1 if there is data not flushed.
191 */
192int consumer_metadata_cache_flushed(struct lttng_consumer_channel *channel,
5e41ebe1 193 uint64_t offset, int timer)
331744e3 194{
04ef1097
MD
195 int ret = 0;
196 struct lttng_consumer_stream *metadata_stream;
331744e3 197
a0377dfe
FD
198 LTTNG_ASSERT(channel);
199 LTTNG_ASSERT(channel->metadata_cache);
331744e3 200
7f725ec5 201 /*
5e41ebe1
MD
202 * If not called from a timer handler, we have to take the
203 * channel lock to be mutually exclusive with channel teardown.
204 * Timer handler does not need to take this lock because it is
205 * already synchronized by timer stop (and, more importantly,
206 * taking this lock in a timer handler would cause a deadlock).
7f725ec5 207 */
5e41ebe1
MD
208 if (!timer) {
209 pthread_mutex_lock(&channel->lock);
210 }
ec6ea7d0 211 pthread_mutex_lock(&channel->timer_lock);
04ef1097 212 metadata_stream = channel->metadata_stream;
04ef1097 213 if (!metadata_stream) {
fe81e5c9
DG
214 /*
215 * Having no metadata stream means the channel is being destroyed so there
216 * is no cache to flush anymore.
217 */
218 ret = 0;
e524139e
JG
219 goto end_unlock_channel;
220 }
221
222 pthread_mutex_lock(&metadata_stream->lock);
223 pthread_mutex_lock(&channel->metadata_cache->lock);
224
225 if (metadata_stream->ust_metadata_pushed >= offset) {
04ef1097 226 ret = 0;
fe81e5c9
DG
227 } else if (channel->metadata_stream->endpoint_status !=
228 CONSUMER_ENDPOINT_ACTIVE) {
229 /* An inactive endpoint means we don't have to flush anymore. */
230 ret = 0;
331744e3 231 } else {
fe81e5c9 232 /* Still not completely flushed. */
331744e3
JD
233 ret = 1;
234 }
fe81e5c9 235
331744e3 236 pthread_mutex_unlock(&channel->metadata_cache->lock);
8e1ef46e 237 pthread_mutex_unlock(&metadata_stream->lock);
e524139e 238end_unlock_channel:
ec6ea7d0 239 pthread_mutex_unlock(&channel->timer_lock);
5e41ebe1
MD
240 if (!timer) {
241 pthread_mutex_unlock(&channel->lock);
242 }
331744e3
JD
243
244 return ret;
245}
This page took 0.060899 seconds and 4 git commands to generate.