]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_log_backing.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #ifndef CEPH_RGW_LOGBACKING_H
5 #define CEPH_RGW_LOGBACKING_H
10 #include <string_view>
14 #include <boost/container/flat_map.hpp>
15 #include <boost/system/error_code.hpp>
17 #undef FMT_HEADER_ONLY
18 #define FMT_HEADER_ONLY 1
19 #include <fmt/format.h>
21 #include "include/rados/librados.hpp"
22 #include "include/encoding.h"
23 #include "include/expected.hpp"
24 #include "include/function2.hpp"
26 #include "cls/version/cls_version_types.h"
28 #include "common/async/yield_context.h"
29 #include "common/Formatter.h"
30 #include "common/strtol.h"
32 namespace bc
= boost::container
;
33 namespace bs
= boost::system
;
35 #include "cls_fifo_legacy.h"
37 /// Type of log backing, stored in the mark used in the quick check,
38 /// and passed to checking functions.
44 inline void encode(const log_type
& type
, ceph::buffer::list
& bl
) {
45 auto t
= static_cast<uint8_t>(type
);
49 inline void decode(log_type
& type
, bufferlist::const_iterator
& bl
) {
52 type
= static_cast<log_type
>(t
);
55 inline std::optional
<log_type
> to_log_type(std::string_view s
) {
56 if (strncasecmp(s
.data(), "omap", s
.length()) == 0) {
57 return log_type::omap
;
58 } else if (strncasecmp(s
.data(), "fifo", s
.length()) == 0) {
59 return log_type::fifo
;
64 inline std::ostream
& operator <<(std::ostream
& m
, const log_type
& t
) {
67 return m
<< "log_type::omap";
69 return m
<< "log_type::fifo";
72 return m
<< "log_type::UNKNOWN=" << static_cast<uint32_t>(t
);
75 /// Look over the shards in a log and determine the type.
76 tl::expected
<log_type
, bs::error_code
>
77 log_backing_type(const DoutPrefixProvider
*dpp
,
78 librados::IoCtx
& ioctx
,
80 int shards
, //< Total number of shards
81 /// A function taking a shard number and
83 const fu2::unique_function
<std::string(int) const>& get_oid
,
86 /// Remove all log shards and associated parts of fifos.
87 bs::error_code
log_remove(librados::IoCtx
& ioctx
,
88 int shards
, //< Total number of shards
89 /// A function taking a shard number and
91 const fu2::unique_function
<std::string(int) const>& get_oid
,
96 struct logback_generation
{
99 std::optional
<ceph::real_time
> pruned
;
101 void encode(ceph::buffer::list
& bl
) const {
102 ENCODE_START(1, 1, bl
);
109 void decode(bufferlist::const_iterator
& bl
) {
117 WRITE_CLASS_ENCODER(logback_generation
)
118 inline std::ostream
& operator <<(std::ostream
& m
, const logback_generation
& g
) {
119 return m
<< "[" << g
.gen_id
<< "," << g
.type
<< ","
120 << (g
.pruned
? "PRUNED" : "NOT PRUNED") << "]";
123 class logback_generations
: public librados::WatchCtx2
{
125 using entries_t
= bc::flat_map
<uint64_t, logback_generation
>;
128 librados::IoCtx
& ioctx
;
129 logback_generations(librados::IoCtx
& ioctx
,
131 fu2::unique_function
<std::string(
132 uint64_t, int) const>&& get_oid
,
134 : ioctx(ioctx
), oid(oid
), get_oid(std::move(get_oid
)),
137 uint64_t my_id
= ioctx
.get_instance_id();
140 const std::string oid
;
141 const fu2::unique_function
<std::string(uint64_t, int) const> get_oid
;
148 uint64_t watchcookie
= 0;
154 tl::expected
<std::pair
<entries_t
, obj_version
>, bs::error_code
>
155 read(const DoutPrefixProvider
*dpp
, optional_yield y
) noexcept
;
156 bs::error_code
write(const DoutPrefixProvider
*dpp
, entries_t
&& e
, std::unique_lock
<std::mutex
>&& l_
,
157 optional_yield y
) noexcept
;
158 bs::error_code
setup(const DoutPrefixProvider
*dpp
, log_type def
, optional_yield y
) noexcept
;
160 bs::error_code
watch() noexcept
;
162 auto lowest_nomempty(const entries_t
& es
) {
163 return std::find_if(es
.begin(), es
.end(),
165 return !e
.second
.pruned
;
171 /// For the use of watch/notify.
173 void handle_notify(uint64_t notify_id
,
175 uint64_t notifier_id
,
176 bufferlist
& bl
) override final
;
178 void handle_error(uint64_t cookie
, int err
) override final
;
182 virtual ~logback_generations();
184 template<typename T
, typename
... Args
>
185 static tl::expected
<std::unique_ptr
<T
>, bs::error_code
>
186 init(const DoutPrefixProvider
*dpp
, librados::IoCtx
& ioctx_
, std::string oid_
,
187 fu2::unique_function
<std::string(uint64_t, int) const>&& get_oid_
,
188 int shards_
, log_type def
, optional_yield y
,
189 Args
&& ...args
) noexcept
{
191 T
* lgp
= new T(ioctx_
, std::move(oid_
),
193 shards_
, std::forward
<Args
>(args
)...);
194 std::unique_ptr
<T
> lg(lgp
);
196 auto ec
= lg
->setup(dpp
, def
, y
);
198 return tl::unexpected(ec
);
199 // Obnoxiousness for C++ Compiler in Bionic Beaver
200 return tl::expected
<std::unique_ptr
<T
>, bs::error_code
>(std::move(lg
));
201 } catch (const std::bad_alloc
&) {
202 return tl::unexpected(bs::error_code(ENOMEM
, bs::system_category()));
206 bs::error_code
update(const DoutPrefixProvider
*dpp
, optional_yield y
) noexcept
;
208 entries_t
entries() const {
212 bs::error_code
new_backing(const DoutPrefixProvider
*dpp
, log_type type
, optional_yield y
) noexcept
;
214 bs::error_code
empty_to(const DoutPrefixProvider
*dpp
, uint64_t gen_id
, optional_yield y
) noexcept
;
216 bs::error_code
remove_empty(const DoutPrefixProvider
*dpp
, optional_yield y
) noexcept
;
218 // Callbacks, to be defined by descendant.
220 /// Handle initialization on startup
222 /// @param e All non-empty generations
223 virtual bs::error_code
handle_init(entries_t e
) noexcept
= 0;
225 /// Handle new generations.
227 /// @param e Map of generations added since last update
228 virtual bs::error_code
handle_new_gens(entries_t e
) noexcept
= 0;
230 /// Handle generations being marked empty
232 /// @param new_tail Lowest non-empty generation
233 virtual bs::error_code
handle_empty_to(uint64_t new_tail
) noexcept
= 0;
236 inline std::string
gencursor(uint64_t gen_id
, std::string_view cursor
) {
238 fmt::format("G{:0>20}@{}", gen_id
, cursor
) :
239 std::string(cursor
));
242 inline std::pair
<uint64_t, std::string_view
>
243 cursorgen(std::string_view cursor_
) {
244 if (cursor_
.empty()) {
247 std::string_view cursor
= cursor_
;
248 if (cursor
[0] != 'G') {
249 return { 0, cursor
};
251 cursor
.remove_prefix(1);
252 auto gen_id
= ceph::consume
<uint64_t>(cursor
);
253 if (!gen_id
|| cursor
[0] != '@') {
254 return { 0, cursor_
};
256 cursor
.remove_prefix(1);
257 return { *gen_id
, cursor
};
261 librados::IoCtx
& ioctx
;
264 std::unique_ptr
<rgw::cls::fifo::FIFO
> fifo
;
266 int lazy_init(const DoutPrefixProvider
*dpp
, optional_yield y
) {
267 std::unique_lock
l(m
);
269 auto r
= rgw::cls::fifo::FIFO::create(dpp
, ioctx
, oid
, &fifo
, y
);
278 LazyFIFO(librados::IoCtx
& ioctx
, std::string oid
)
279 : ioctx(ioctx
), oid(std::move(oid
)) {}
281 int read_meta(const DoutPrefixProvider
*dpp
, optional_yield y
) {
282 auto r
= lazy_init(dpp
, y
);
284 return fifo
->read_meta(dpp
, y
);
287 int meta(const DoutPrefixProvider
*dpp
, rados::cls::fifo::info
& info
, optional_yield y
) {
288 auto r
= lazy_init(dpp
, y
);
294 int get_part_layout_info(const DoutPrefixProvider
*dpp
,
295 std::uint32_t& part_header_size
,
296 std::uint32_t& part_entry_overhead
,
298 auto r
= lazy_init(dpp
, y
);
300 std::tie(part_header_size
, part_entry_overhead
)
301 = fifo
->get_part_layout_info();
305 int push(const DoutPrefixProvider
*dpp
,
306 const ceph::buffer::list
& bl
,
308 auto r
= lazy_init(dpp
, y
);
310 return fifo
->push(dpp
, bl
, y
);
313 int push(const DoutPrefixProvider
*dpp
,
314 ceph::buffer::list
& bl
,
315 librados::AioCompletion
* c
,
317 auto r
= lazy_init(dpp
, y
);
319 fifo
->push(dpp
, bl
, c
);
323 int push(const DoutPrefixProvider
*dpp
,
324 const std::vector
<ceph::buffer::list
>& data_bufs
,
326 auto r
= lazy_init(dpp
, y
);
328 return fifo
->push(dpp
, data_bufs
, y
);
331 int push(const DoutPrefixProvider
*dpp
,
332 const std::vector
<ceph::buffer::list
>& data_bufs
,
333 librados::AioCompletion
* c
,
335 auto r
= lazy_init(dpp
, y
);
337 fifo
->push(dpp
, data_bufs
, c
);
341 int list(const DoutPrefixProvider
*dpp
,
342 int max_entries
, std::optional
<std::string_view
> markstr
,
343 std::vector
<rgw::cls::fifo::list_entry
>* out
,
344 bool* more
, optional_yield y
) {
345 auto r
= lazy_init(dpp
, y
);
347 return fifo
->list(dpp
, max_entries
, markstr
, out
, more
, y
);
350 int list(const DoutPrefixProvider
*dpp
, int max_entries
, std::optional
<std::string_view
> markstr
,
351 std::vector
<rgw::cls::fifo::list_entry
>* out
, bool* more
,
352 librados::AioCompletion
* c
, optional_yield y
) {
353 auto r
= lazy_init(dpp
, y
);
355 fifo
->list(dpp
, max_entries
, markstr
, out
, more
, c
);
359 int trim(const DoutPrefixProvider
*dpp
, std::string_view markstr
, bool exclusive
, optional_yield y
) {
360 auto r
= lazy_init(dpp
, y
);
362 return fifo
->trim(dpp
, markstr
, exclusive
, y
);
365 int trim(const DoutPrefixProvider
*dpp
, std::string_view markstr
, bool exclusive
, librados::AioCompletion
* c
,
367 auto r
= lazy_init(dpp
, y
);
369 fifo
->trim(dpp
, markstr
, exclusive
, c
);
373 int get_part_info(const DoutPrefixProvider
*dpp
, int64_t part_num
, rados::cls::fifo::part_header
* header
,
375 auto r
= lazy_init(dpp
, y
);
377 return fifo
->get_part_info(dpp
, part_num
, header
, y
);
380 int get_part_info(const DoutPrefixProvider
*dpp
, int64_t part_num
, rados::cls::fifo::part_header
* header
,
381 librados::AioCompletion
* c
, optional_yield y
) {
382 auto r
= lazy_init(dpp
, y
);
384 fifo
->get_part_info(part_num
, header
, c
);
388 int get_head_info(const DoutPrefixProvider
*dpp
, fu2::unique_function
<
389 void(int r
, rados::cls::fifo::part_header
&&)>&& f
,
390 librados::AioCompletion
* c
,
392 auto r
= lazy_init(dpp
, y
);
394 fifo
->get_head_info(dpp
, std::move(f
), c
);