2 * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
3 * David Goulet <dgoulet@efficios.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2 only,
7 * as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <sys/types.h>
29 #include <common/common.h>
30 #include <common/utils.h>
31 #include <common/sessiond-comm/sessiond-comm.h>
32 #include <common/ust-consumer/ust-consumer.h>
33 #include <common/consumer.h>
35 #include "consumer-metadata-cache.h"
37 extern struct lttng_consumer_global_data consumer_data
;
40 * Extend the allocated size of the metadata cache. Called only from
41 * lttng_ustconsumer_write_metadata_cache.
43 * Return 0 on success, a negative value on error.
45 static int extend_metadata_cache(struct lttng_consumer_channel
*channel
,
50 unsigned int new_size
, old_size
;
53 assert(channel
->metadata_cache
);
55 old_size
= channel
->metadata_cache
->cache_alloc_size
;
56 new_size
= max_t(unsigned int, old_size
+ size
, old_size
<< 1);
57 DBG("Extending metadata cache to %u", new_size
);
58 tmp_data_ptr
= realloc(channel
->metadata_cache
->data
, new_size
);
60 ERR("Reallocating metadata cache");
61 free(channel
->metadata_cache
->data
);
65 /* Zero newly allocated memory */
66 memset(tmp_data_ptr
+ old_size
, 0, new_size
- old_size
);
67 channel
->metadata_cache
->data
= tmp_data_ptr
;
68 channel
->metadata_cache
->cache_alloc_size
= new_size
;
75 * Write metadata to the cache, extend the cache if necessary. We support
76 * overlapping updates, but they need to be contiguous. Send the
77 * contiguous metadata in cache to the ring buffer. The metadata cache
78 * lock MUST be acquired to write in the cache.
80 * Return 0 on success, a negative value on error.
82 int consumer_metadata_cache_write(struct lttng_consumer_channel
*channel
,
83 unsigned int offset
, unsigned int len
, char *data
)
87 struct consumer_metadata_cache
*cache
;
90 assert(channel
->metadata_cache
);
92 cache
= channel
->metadata_cache
;
93 DBG("Writing %u bytes from offset %u in metadata cache", len
, offset
);
95 if (offset
+ len
> cache
->cache_alloc_size
) {
96 ret
= extend_metadata_cache(channel
,
97 len
- cache
->cache_alloc_size
+ offset
);
99 ERR("Extending metadata cache");
104 memcpy(cache
->data
+ offset
, data
, len
);
105 if (offset
+ len
> cache
->max_offset
) {
108 cache
->max_offset
= offset
+ len
;
109 if (channel
->monitor
) {
110 size_ret
= lttng_write(channel
->metadata_stream
->ust_metadata_poll_pipe
[1],
113 ERR("Wakeup UST metadata pipe");
125 * Create the metadata cache, original allocated size: max_sb_size
127 * Return 0 on success, a negative value on error.
129 int consumer_metadata_cache_allocate(struct lttng_consumer_channel
*channel
)
135 channel
->metadata_cache
= zmalloc(
136 sizeof(struct consumer_metadata_cache
));
137 if (!channel
->metadata_cache
) {
138 PERROR("zmalloc metadata cache struct");
142 ret
= pthread_mutex_init(&channel
->metadata_cache
->lock
, NULL
);
144 PERROR("mutex init");
148 channel
->metadata_cache
->cache_alloc_size
= DEFAULT_METADATA_CACHE_SIZE
;
149 channel
->metadata_cache
->data
= zmalloc(
150 channel
->metadata_cache
->cache_alloc_size
* sizeof(char));
151 if (!channel
->metadata_cache
->data
) {
152 PERROR("zmalloc metadata cache data");
156 DBG("Allocated metadata cache of %" PRIu64
" bytes",
157 channel
->metadata_cache
->cache_alloc_size
);
163 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
165 free(channel
->metadata_cache
);
171 * Destroy and free the metadata cache
173 void consumer_metadata_cache_destroy(struct lttng_consumer_channel
*channel
)
175 if (!channel
|| !channel
->metadata_cache
) {
179 DBG("Destroying metadata cache");
181 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
182 free(channel
->metadata_cache
->data
);
183 free(channel
->metadata_cache
);
187 * Check if the cache is flushed up to the offset passed in parameter.
189 * Return 0 if everything has been flushed, 1 if there is data not flushed.
191 int consumer_metadata_cache_flushed(struct lttng_consumer_channel
*channel
,
192 uint64_t offset
, int timer
)
195 struct lttng_consumer_stream
*metadata_stream
;
198 assert(channel
->metadata_cache
);
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 pthread_mutex_lock(&channel
->metadata_cache
->lock
);
213 metadata_stream
= channel
->metadata_stream
;
215 if (!metadata_stream
) {
217 * Having no metadata stream means the channel is being destroyed so there
218 * is no cache to flush anymore.
221 } else if (metadata_stream
->ust_metadata_pushed
>= offset
) {
223 } else if (channel
->metadata_stream
->endpoint_status
!=
224 CONSUMER_ENDPOINT_ACTIVE
) {
225 /* An inactive endpoint means we don't have to flush anymore. */
228 /* Still not completely flushed. */
232 pthread_mutex_unlock(&channel
->metadata_cache
->lock
);
233 pthread_mutex_unlock(&channel
->timer_lock
);
235 pthread_mutex_unlock(&channel
->lock
);