2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
8 #include "metadata-bucket.hpp"
10 #include <common/buffer-view.hpp>
11 #include <common/consumer/consumer.hpp>
12 #include <common/dynamic-buffer.hpp>
13 #include <common/error.hpp>
14 #include <common/macros.hpp>
16 struct metadata_bucket
{
17 struct lttng_dynamic_buffer content
;
19 metadata_bucket_flush_cb fn
;
22 unsigned int buffer_count
;
25 struct metadata_bucket
*metadata_bucket_create(metadata_bucket_flush_cb flush
, void *data
)
27 metadata_bucket
*bucket
= zmalloc
<metadata_bucket
>();
29 PERROR("Failed to allocate buffer bucket");
33 bucket
->flush
.fn
= flush
;
34 bucket
->flush
.data
= data
;
35 lttng_dynamic_buffer_init(&bucket
->content
);
40 void metadata_bucket_destroy(struct metadata_bucket
*bucket
)
46 if (bucket
->content
.size
> 0) {
47 WARN("Stream metadata bucket destroyed with remaining data: size = %zu, buffer count = %u",
49 bucket
->buffer_count
);
52 lttng_dynamic_buffer_reset(&bucket
->content
);
56 void metadata_bucket_reset(struct metadata_bucket
*bucket
)
58 lttng_dynamic_buffer_reset(&bucket
->content
);
59 lttng_dynamic_buffer_init(&bucket
->content
);
60 bucket
->buffer_count
= 0;
63 enum metadata_bucket_status
metadata_bucket_fill(struct metadata_bucket
*bucket
,
64 const struct stream_subbuffer
*buffer
)
67 struct lttng_buffer_view flushed_view
;
68 struct stream_subbuffer flushed_subbuffer
;
69 enum metadata_bucket_status status
;
70 const bool should_flush
= LTTNG_OPTIONAL_GET(buffer
->info
.metadata
.coherent
);
71 const size_t padding_this_buffer
=
72 buffer
->info
.metadata
.padded_subbuf_size
- buffer
->info
.metadata
.subbuf_size
;
75 DBG("Metadata bucket filled with %zu bytes buffer view, sub-buffer size: %lu, padded sub-buffer size: %lu, coherent: %s",
76 buffer
->buffer
.buffer
.size
,
77 buffer
->info
.metadata
.subbuf_size
,
78 buffer
->info
.metadata
.padded_subbuf_size
,
79 buffer
->info
.metadata
.coherent
.value
? "true" : "false");
81 * If no metadata was accumulated and this buffer should be
82 * flushed, don't copy it unecessarily; just flush it directly.
84 if (!should_flush
|| bucket
->buffer_count
!= 0) {
86 * Append the _padded_ subbuffer since they are combined
87 * into a single "virtual" subbuffer that will be
90 * This means that some padding will be sent over the
91 * network, but should not represent a large amount
92 * of data as incoherent subbuffers are typically
95 * The padding of the last subbuffer (coherent) added to
96 * the bucket is not sent, which is what really matters
97 * from an efficiency point of view.
99 ret
= lttng_dynamic_buffer_append_view(&bucket
->content
, &buffer
->buffer
.buffer
);
101 status
= METADATA_BUCKET_STATUS_ERROR
;
106 bucket
->buffer_count
++;
108 status
= METADATA_BUCKET_STATUS_OK
;
112 flushed_view
= bucket
->content
.size
!= 0 ?
113 lttng_buffer_view_from_dynamic_buffer(&bucket
->content
, 0, -1) :
114 lttng_buffer_view_from_view(&buffer
->buffer
.buffer
, 0, -1);
117 * The flush is done with the size of all padded sub-buffers, except
118 * for the last one which we can safely "trim". The padding of the last
119 * packet will be reconstructed by the relay daemon.
121 flush_size
= flushed_view
.size
- padding_this_buffer
;
123 flushed_subbuffer
= (typeof(flushed_subbuffer
)) {
125 .buffer
= flushed_view
,
129 .subbuf_size
= flush_size
,
130 .padded_subbuf_size
= flushed_view
.size
,
131 .version
= buffer
->info
.metadata
.version
,
132 .coherent
= buffer
->info
.metadata
.coherent
,
137 DBG("Metadata bucket flushing %zu bytes (%u sub-buffer%s)",
139 bucket
->buffer_count
,
140 bucket
->buffer_count
> 1 ? "s" : "");
141 ret
= bucket
->flush
.fn(&flushed_subbuffer
, bucket
->flush
.data
);
143 status
= METADATA_BUCKET_STATUS_OK
;
145 status
= METADATA_BUCKET_STATUS_ERROR
;
148 metadata_bucket_reset(bucket
);