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.
24 #include <sys/types.h>
28 #include <common/common.h>
29 #include <common/utils.h>
30 #include <common/sessiond-comm/sessiond-comm.h>
31 #include <common/ust-consumer/ust-consumer.h>
32 #include <common/consumer.h>
34 #include "consumer-metadata-cache.h"
37 * Extend the allocated size of the metadata cache. Called only from
38 * lttng_ustconsumer_write_metadata_cache.
40 * Return 0 on success, a negative value on error.
42 static int extend_metadata_cache(struct lttng_consumer_channel
*channel
,
47 unsigned int new_size
;
50 assert(channel
->metadata_cache
);
52 new_size
= max_t(unsigned int,
53 channel
->metadata_cache
->cache_alloc_size
+ size
,
54 channel
->metadata_cache
->cache_alloc_size
<< 1);
55 DBG("Extending metadata cache to %u", new_size
);
56 tmp_data_ptr
= realloc(channel
->metadata_cache
->data
, new_size
);
58 ERR("Reallocating metadata cache");
59 free(channel
->metadata_cache
->data
);
63 channel
->metadata_cache
->data
= tmp_data_ptr
;
64 channel
->metadata_cache
->cache_alloc_size
= new_size
;
71 * Write metadata to the cache, extend the cache if necessary. We support
72 * non-contiguous updates but not overlapping ones. If there is contiguous
73 * metadata in the cache, we send it to the ring buffer. The metadata cache
74 * lock MUST be acquired to write in the cache.
76 * Return 0 on success, a negative value on error.
78 int consumer_metadata_cache_write(struct lttng_consumer_channel
*channel
,
79 unsigned int offset
, unsigned int len
, char *data
)
82 struct consumer_metadata_cache
*cache
;
85 assert(channel
->metadata_cache
);
87 cache
= channel
->metadata_cache
;
88 DBG("Writing %u bytes from offset %u in metadata cache", len
, offset
);
90 if (offset
+ len
> cache
->cache_alloc_size
) {
91 ret
= extend_metadata_cache(channel
,
92 len
- cache
->cache_alloc_size
+ offset
);
94 ERR("Extending metadata cache");
99 memcpy(cache
->data
+ offset
, data
, len
);
100 cache
->total_bytes_written
+= len
;
101 if (offset
+ len
> cache
->max_offset
) {
102 cache
->max_offset
= offset
+ len
;
105 if (cache
->max_offset
== cache
->total_bytes_written
) {
106 offset
= cache
->rb_pushed
;
107 len
= cache
->total_bytes_written
- cache
->rb_pushed
;
108 ret
= lttng_ustconsumer_push_metadata(channel
, cache
->data
, offset
,
111 ERR("Pushing metadata");
114 cache
->rb_pushed
+= len
;
122 * Create the metadata cache, original allocated size: max_sb_size
124 * Return 0 on success, a negative value on error.
126 int consumer_metadata_cache_allocate(struct lttng_consumer_channel
*channel
)
132 channel
->metadata_cache
= zmalloc(
133 sizeof(struct consumer_metadata_cache
));
134 if (!channel
->metadata_cache
) {
135 PERROR("zmalloc metadata cache struct");
139 ret
= pthread_mutex_init(&channel
->metadata_cache
->lock
, NULL
);
141 PERROR("mutex init");
145 channel
->metadata_cache
->cache_alloc_size
= DEFAULT_METADATA_CACHE_SIZE
;
146 channel
->metadata_cache
->data
= zmalloc(
147 channel
->metadata_cache
->cache_alloc_size
* sizeof(char));
148 if (!channel
->metadata_cache
->data
) {
149 PERROR("zmalloc metadata cache data");
153 DBG("Allocated metadata cache of %" PRIu64
" bytes",
154 channel
->metadata_cache
->cache_alloc_size
);
160 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
162 free(channel
->metadata_cache
);
168 * Destroy and free the metadata cache
170 void consumer_metadata_cache_destroy(struct lttng_consumer_channel
*channel
)
172 if (!channel
|| !channel
->metadata_cache
) {
176 DBG("Destroying metadata cache");
178 if (channel
->metadata_cache
->max_offset
>
179 channel
->metadata_cache
->rb_pushed
) {
180 ERR("Destroying a cache not entirely commited");
183 pthread_mutex_destroy(&channel
->metadata_cache
->lock
);
184 free(channel
->metadata_cache
->data
);
185 free(channel
->metadata_cache
);
189 * Check if the cache is flushed up to the offset passed in parameter.
191 * Return 0 if everything has been flushed, 1 if there is data not flushed.
193 int consumer_metadata_cache_flushed(struct lttng_consumer_channel
*channel
,
197 struct consumer_metadata_cache
*cache
;
200 assert(channel
->metadata_cache
);
202 cache
= channel
->metadata_cache
;
204 pthread_mutex_lock(&channel
->metadata_cache
->lock
);
205 if (cache
->rb_pushed
>= offset
) {
210 pthread_mutex_unlock(&channel
->metadata_cache
->lock
);