]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2018 Red Hat <contact@redhat.com> | |
7 | * Author: Adam C. Emerson | |
8 | * | |
9 | * This is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License version 2.1, as published by the Free Software | |
12 | * Foundation. See file COPYING. | |
13 | * | |
14 | */ | |
15 | ||
16 | #ifndef NEORADOS_RADOS_HPP | |
17 | #define NEORADOS_RADOS_HPP | |
18 | ||
19 | #include <cstddef> | |
20 | #include <memory> | |
21 | #include <tuple> | |
22 | #include <string> | |
23 | #include <string_view> | |
24 | #include <type_traits> | |
25 | #include <variant> | |
26 | ||
27 | #include <boost/asio.hpp> | |
28 | ||
29 | #include <boost/container/flat_map.hpp> | |
30 | #include <boost/container/flat_set.hpp> | |
31 | #include <boost/uuid/uuid.hpp> | |
32 | ||
33 | #include <boost/system/error_code.hpp> | |
34 | ||
35 | // Will be in C++20! | |
36 | ||
37 | #include "include/expected.hpp" | |
38 | ||
39 | // Had better be in C++20. Why is this not in Boost? | |
40 | ||
41 | #include "include/function2.hpp" | |
42 | ||
43 | // Things broken out so we can decode them in Objecter. | |
44 | ||
45 | #include "include/neorados/RADOS_Decodable.hpp" | |
46 | ||
47 | // Needed for type erasure and template support. We can't really avoid | |
48 | // it. | |
49 | ||
50 | #include "common/async/completion.h" | |
51 | ||
52 | // These are needed for RGW, but in general as a 'shiny new interface' | |
53 | // we should try to use forward declarations and provide standard alternatives. | |
54 | ||
55 | #include "include/common_fwd.h" | |
56 | ||
57 | #include "include/buffer.h" | |
58 | #include "include/rados/librados_fwd.hpp" | |
59 | ||
60 | #include "common/ceph_time.h" | |
61 | ||
62 | namespace neorados { | |
f67539c2 TL |
63 | class Object; |
64 | class IOContext; | |
65 | } | |
66 | namespace std { | |
67 | template<> | |
68 | struct hash<neorados::Object>; | |
69 | template<> | |
70 | struct hash<neorados::IOContext>; | |
71 | } | |
72 | ||
73 | namespace neorados { | |
74 | namespace detail { | |
75 | class Client; | |
76 | } | |
77 | ||
78 | class RADOS; | |
79 | ||
80 | // Exists mostly so that repeated operations on the same object don't | |
81 | // have to pay for the string copy to construct an object_t. | |
82 | ||
83 | class Object final { | |
84 | friend RADOS; | |
85 | friend std::hash<Object>; | |
86 | ||
87 | public: | |
88 | Object(); | |
89 | Object(const char* s); | |
90 | Object(std::string_view s); | |
91 | Object(std::string&& s); | |
92 | Object(const std::string& s); | |
93 | ~Object(); | |
94 | ||
95 | Object(const Object& o); | |
96 | Object& operator =(const Object& o); | |
97 | ||
98 | Object(Object&& o); | |
99 | Object& operator =(Object&& o); | |
100 | ||
101 | operator std::string_view() const; | |
102 | ||
103 | friend std::ostream& operator <<(std::ostream& m, const Object& o); | |
104 | friend bool operator <(const Object& lhs, const Object& rhs); | |
105 | friend bool operator <=(const Object& lhs, const Object& rhs); | |
106 | friend bool operator >=(const Object& lhs, const Object& rhs); | |
107 | friend bool operator >(const Object& lhs, const Object& rhs); | |
108 | ||
109 | friend bool operator ==(const Object& lhs, const Object& rhs); | |
110 | friend bool operator !=(const Object& lhs, const Object& rhs); | |
111 | ||
112 | private: | |
113 | ||
114 | static constexpr std::size_t impl_size = 4 * 8; | |
115 | std::aligned_storage_t<impl_size> impl; | |
116 | }; | |
117 | ||
118 | // Not the same as the librados::IoCtx, but it does gather together | |
119 | // some of the same metadata. Since we're likely to do multiple | |
120 | // operations in the same pool or namespace, it doesn't make sense to | |
121 | // redo a bunch of lookups and string copies. | |
122 | ||
123 | class IOContext final { | |
124 | friend RADOS; | |
125 | friend std::hash<IOContext>; | |
126 | ||
127 | public: | |
128 | ||
129 | IOContext(); | |
130 | explicit IOContext(std::int64_t pool); | |
131 | IOContext(std::int64_t _pool, std::string_view _ns); | |
132 | IOContext(std::int64_t _pool, std::string&& _ns); | |
133 | ~IOContext(); | |
134 | ||
135 | IOContext(const IOContext& rhs); | |
136 | IOContext& operator =(const IOContext& rhs); | |
137 | ||
138 | IOContext(IOContext&& rhs); | |
139 | IOContext& operator =(IOContext&& rhs); | |
140 | ||
141 | std::int64_t pool() const; | |
142 | void pool(std::int64_t _pool); | |
143 | ||
144 | std::string_view ns() const; | |
145 | void ns(std::string_view _ns); | |
146 | void ns(std::string&& _ns); | |
147 | ||
148 | std::optional<std::string_view> key() const; | |
149 | void key(std::string_view _key); | |
150 | void key(std::string&& _key); | |
151 | void clear_key(); | |
152 | ||
153 | std::optional<std::int64_t> hash() const; | |
154 | void hash(std::int64_t _hash); | |
155 | void clear_hash(); | |
156 | ||
157 | std::optional<std::uint64_t> read_snap() const; | |
158 | void read_snap(std::optional<std::uint64_t> _snapid); | |
159 | ||
160 | // I can't actually move-construct here since snapid_t is its own | |
161 | // separate class type, not an alias. | |
162 | std::optional< | |
163 | std::pair<std::uint64_t, | |
164 | std::vector<std::uint64_t>>> write_snap_context() const; | |
165 | void write_snap_context(std::optional< | |
166 | std::pair<std::uint64_t, | |
167 | std::vector<std::uint64_t>>> snapc); | |
168 | ||
20effc67 TL |
169 | bool full_try() const; |
170 | void full_try(bool _full_try); | |
171 | ||
f67539c2 TL |
172 | friend std::ostream& operator <<(std::ostream& m, const IOContext& o); |
173 | friend bool operator <(const IOContext& lhs, const IOContext& rhs); | |
174 | friend bool operator <=(const IOContext& lhs, const IOContext& rhs); | |
175 | friend bool operator >=(const IOContext& lhs, const IOContext& rhs); | |
176 | friend bool operator >(const IOContext& lhs, const IOContext& rhs); | |
177 | ||
178 | friend bool operator ==(const IOContext& lhs, const IOContext& rhs); | |
179 | friend bool operator !=(const IOContext& lhs, const IOContext& rhs); | |
180 | ||
181 | private: | |
182 | ||
183 | static constexpr std::size_t impl_size = 16 * 8; | |
184 | std::aligned_storage_t<impl_size> impl; | |
185 | }; | |
186 | ||
1e59de90 | 187 | inline constexpr std::string_view all_nspaces("\001"); |
f67539c2 TL |
188 | |
189 | enum class cmpxattr_op : std::uint8_t { | |
190 | eq = 1, | |
191 | ne = 2, | |
192 | gt = 3, | |
193 | gte = 4, | |
194 | lt = 5, | |
195 | lte = 6 | |
196 | }; | |
197 | ||
198 | namespace alloc_hint { | |
199 | enum alloc_hint_t { | |
200 | sequential_write = 1, | |
201 | random_write = 2, | |
202 | sequential_read = 4, | |
203 | random_read = 8, | |
204 | append_only = 16, | |
205 | immutable = 32, | |
206 | shortlived = 64, | |
207 | longlived = 128, | |
208 | compressible = 256, | |
209 | incompressible = 512 | |
210 | }; | |
211 | } | |
212 | ||
213 | class Op { | |
214 | friend RADOS; | |
215 | ||
216 | public: | |
217 | ||
218 | Op(const Op&) = delete; | |
219 | Op& operator =(const Op&) = delete; | |
220 | Op(Op&&); | |
221 | Op& operator =(Op&&); | |
222 | ~Op(); | |
223 | ||
224 | void set_excl(); | |
225 | void set_failok(); | |
226 | void set_fadvise_random(); | |
227 | void set_fadvise_sequential(); | |
228 | void set_fadvise_willneed(); | |
229 | void set_fadvise_dontneed(); | |
230 | void set_fadvise_nocache(); | |
231 | ||
232 | void cmpext(uint64_t off, ceph::buffer::list&& cmp_bl, std::size_t* s); | |
233 | void cmpxattr(std::string_view name, cmpxattr_op op, | |
234 | const ceph::buffer::list& val); | |
235 | void cmpxattr(std::string_view name, cmpxattr_op op, std::uint64_t val); | |
236 | void assert_version(uint64_t ver); | |
237 | void assert_exists(); | |
238 | void cmp_omap(const boost::container::flat_map< | |
239 | std::string, | |
240 | std::pair<ceph::buffer::list, int>>& assertions); | |
241 | ||
242 | void exec(std::string_view cls, std::string_view method, | |
243 | const ceph::buffer::list& inbl, | |
244 | ceph::buffer::list* out, | |
245 | boost::system::error_code* ec = nullptr); | |
246 | void exec(std::string_view cls, std::string_view method, | |
247 | const ceph::buffer::list& inbl, | |
248 | fu2::unique_function<void(boost::system::error_code, | |
249 | const ceph::buffer::list&) &&> f); | |
250 | void exec(std::string_view cls, std::string_view method, | |
251 | const ceph::buffer::list& inbl, | |
252 | fu2::unique_function<void(boost::system::error_code, int, | |
253 | const ceph::buffer::list&) &&> f); | |
254 | void exec(std::string_view cls, std::string_view method, | |
255 | const ceph::buffer::list& inbl, | |
256 | boost::system::error_code* ec = nullptr); | |
257 | ||
258 | ||
259 | // Flags that apply to all ops in the operation vector | |
260 | void balance_reads(); | |
261 | void localize_reads(); | |
262 | void order_reads_writes(); | |
263 | void ignore_cache(); | |
264 | void skiprwlocks(); | |
265 | void ignore_overlay(); | |
266 | void full_try(); | |
267 | void full_force(); | |
268 | void ignore_redirect(); | |
269 | void ordersnap(); | |
270 | void returnvec(); | |
271 | ||
272 | std::size_t size() const; | |
273 | using Signature = void(boost::system::error_code); | |
274 | using Completion = ceph::async::Completion<Signature>; | |
275 | ||
276 | friend std::ostream& operator <<(std::ostream& m, const Op& o); | |
277 | protected: | |
278 | Op(); | |
279 | static constexpr std::size_t impl_size = 85 * 8; | |
280 | std::aligned_storage_t<impl_size> impl; | |
281 | }; | |
282 | ||
283 | // This class is /not/ thread-safe. If you want you can wrap it in | |
284 | // something that locks it. | |
285 | ||
286 | class ReadOp final : public Op { | |
287 | friend RADOS; | |
288 | ||
289 | public: | |
290 | ||
291 | ReadOp() = default; | |
292 | ReadOp(const ReadOp&) = delete; | |
293 | ReadOp(ReadOp&&) = default; | |
294 | ||
295 | ReadOp& operator =(const ReadOp&) = delete; | |
296 | ReadOp& operator =(ReadOp&&) = default; | |
297 | ||
298 | void read(size_t off, uint64_t len, ceph::buffer::list* out, | |
299 | boost::system::error_code* ec = nullptr); | |
300 | void get_xattr(std::string_view name, ceph::buffer::list* out, | |
301 | boost::system::error_code* ec = nullptr); | |
302 | void get_omap_header(ceph::buffer::list*, | |
303 | boost::system::error_code* ec = nullptr); | |
304 | ||
305 | void sparse_read(uint64_t off, uint64_t len, | |
306 | ceph::buffer::list* out, | |
307 | std::vector<std::pair<std::uint64_t, std::uint64_t>>* extents, | |
308 | boost::system::error_code* ec = nullptr); | |
309 | ||
310 | void stat(std::uint64_t* size, ceph::real_time* mtime, | |
311 | boost::system::error_code* ec = nullptr); | |
312 | ||
313 | void get_omap_keys(std::optional<std::string_view> start_after, | |
314 | std::uint64_t max_return, | |
315 | boost::container::flat_set<std::string>* keys, | |
316 | bool* truncated, | |
317 | boost::system::error_code* ec = nullptr); | |
318 | ||
319 | ||
320 | void get_xattrs(boost::container::flat_map<std::string, | |
321 | ceph::buffer::list>* kv, | |
322 | boost::system::error_code* ec = nullptr); | |
323 | ||
324 | void get_omap_vals(std::optional<std::string_view> start_after, | |
325 | std::optional<std::string_view> filter_prefix, | |
326 | uint64_t max_return, | |
327 | boost::container::flat_map<std::string, | |
328 | ceph::buffer::list>* kv, | |
329 | bool* truncated, | |
330 | boost::system::error_code* ec = nullptr); | |
331 | ||
332 | ||
333 | void get_omap_vals_by_keys(const boost::container::flat_set<std::string>& keys, | |
334 | boost::container::flat_map<std::string, | |
335 | ceph::buffer::list>* kv, | |
336 | boost::system::error_code* ec = nullptr); | |
337 | ||
338 | void list_watchers(std::vector<struct ObjWatcher>* watchers, | |
339 | boost::system::error_code* ec = nullptr); | |
340 | ||
341 | void list_snaps(struct SnapSet* snaps, | |
342 | boost::system::error_code* ec = nullptr); | |
343 | }; | |
344 | ||
345 | class WriteOp final : public Op { | |
346 | friend RADOS; | |
347 | public: | |
348 | ||
349 | WriteOp() = default; | |
350 | WriteOp(const WriteOp&) = delete; | |
351 | WriteOp(WriteOp&&) = default; | |
352 | ||
353 | WriteOp& operator =(const WriteOp&) = delete; | |
354 | WriteOp& operator =(WriteOp&&) = default; | |
355 | ||
356 | void set_mtime(ceph::real_time t); | |
357 | void create(bool exclusive); | |
358 | void write(uint64_t off, ceph::buffer::list&& bl); | |
359 | void write_full(ceph::buffer::list&& bl); | |
360 | void writesame(std::uint64_t off, std::uint64_t write_len, | |
361 | ceph::buffer::list&& bl); | |
362 | void append(ceph::buffer::list&& bl); | |
363 | void remove(); | |
364 | void truncate(uint64_t off); | |
365 | void zero(uint64_t off, uint64_t len); | |
366 | void rmxattr(std::string_view name); | |
367 | void setxattr(std::string_view name, | |
368 | ceph::buffer::list&& bl); | |
369 | void rollback(uint64_t snapid); | |
370 | void set_omap(const boost::container::flat_map<std::string, | |
371 | ceph::buffer::list>& map); | |
372 | void set_omap_header(ceph::buffer::list&& bl); | |
373 | void clear_omap(); | |
374 | void rm_omap_keys(const boost::container::flat_set<std::string>& to_rm); | |
375 | void set_alloc_hint(uint64_t expected_object_size, | |
376 | uint64_t expected_write_size, | |
377 | alloc_hint::alloc_hint_t flags); | |
378 | }; | |
379 | ||
380 | ||
381 | struct FSStats { | |
382 | uint64_t kb; | |
383 | uint64_t kb_used; | |
384 | uint64_t kb_avail; | |
385 | uint64_t num_objects; | |
386 | }; | |
387 | ||
388 | // From librados.h, maybe move into a common file. But I want to see | |
389 | // if we need/want to amend/add/remove anything first. | |
390 | struct PoolStats { | |
391 | /// space used in bytes | |
392 | uint64_t num_bytes; | |
393 | /// space used in KB | |
394 | uint64_t num_kb; | |
395 | /// number of objects in the pool | |
396 | uint64_t num_objects; | |
397 | /// number of clones of objects | |
398 | uint64_t num_object_clones; | |
399 | /// num_objects * num_replicas | |
400 | uint64_t num_object_copies; | |
401 | /// number of objects missing on primary | |
402 | uint64_t num_objects_missing_on_primary; | |
403 | /// number of objects found on no OSDs | |
404 | uint64_t num_objects_unfound; | |
405 | /// number of objects replicated fewer times than they should be | |
406 | /// (but found on at least one OSD) | |
407 | uint64_t num_objects_degraded; | |
408 | /// number of objects read | |
409 | uint64_t num_rd; | |
410 | /// objects read in KB | |
411 | uint64_t num_rd_kb; | |
412 | /// number of objects written | |
413 | uint64_t num_wr; | |
414 | /// objects written in KB | |
415 | uint64_t num_wr_kb; | |
416 | /// bytes originally provided by user | |
417 | uint64_t num_user_bytes; | |
418 | /// bytes passed compression | |
419 | uint64_t compressed_bytes_orig; | |
420 | /// bytes resulted after compression | |
421 | uint64_t compressed_bytes; | |
422 | /// bytes allocated at storage | |
423 | uint64_t compressed_bytes_alloc; | |
424 | }; | |
425 | ||
426 | // Placement group, for PG commands | |
427 | struct PG { | |
428 | uint64_t pool; | |
429 | uint32_t seed; | |
430 | }; | |
431 | ||
432 | class Cursor final { | |
433 | public: | |
434 | static Cursor begin(); | |
435 | static Cursor end(); | |
436 | ||
437 | Cursor(); | |
438 | Cursor(const Cursor&); | |
439 | Cursor& operator =(const Cursor&); | |
440 | Cursor(Cursor&&); | |
441 | Cursor& operator =(Cursor&&); | |
442 | ~Cursor(); | |
443 | ||
444 | friend bool operator ==(const Cursor& lhs, | |
445 | const Cursor& rhs); | |
446 | friend bool operator !=(const Cursor& lhs, | |
447 | const Cursor& rhs); | |
448 | friend bool operator <(const Cursor& lhs, | |
449 | const Cursor& rhs); | |
450 | friend bool operator <=(const Cursor& lhs, | |
451 | const Cursor& rhs); | |
452 | friend bool operator >=(const Cursor& lhs, | |
453 | const Cursor& rhs); | |
454 | friend bool operator >(const Cursor& lhs, | |
455 | const Cursor& rhs); | |
456 | ||
457 | std::string to_str() const; | |
458 | static std::optional<Cursor> from_str(const std::string& s); | |
459 | ||
460 | private: | |
461 | struct end_magic_t {}; | |
462 | Cursor(end_magic_t); | |
463 | Cursor(void*); | |
464 | friend RADOS; | |
465 | static constexpr std::size_t impl_size = 16 * 8; | |
466 | std::aligned_storage_t<impl_size> impl; | |
467 | }; | |
468 | ||
469 | class RADOS final | |
470 | { | |
471 | public: | |
472 | static constexpr std::tuple<uint32_t, uint32_t, uint32_t> version() { | |
473 | return {0, 0, 1}; | |
474 | } | |
475 | ||
476 | using BuildSig = void(boost::system::error_code, RADOS); | |
477 | using BuildComp = ceph::async::Completion<BuildSig>; | |
478 | class Builder { | |
479 | std::optional<std::string> conf_files; | |
480 | std::optional<std::string> cluster; | |
481 | std::optional<std::string> name; | |
482 | std::vector<std::pair<std::string, std::string>> configs; | |
483 | bool no_default_conf = false; | |
484 | bool no_mon_conf = false; | |
485 | ||
486 | public: | |
487 | Builder() = default; | |
488 | Builder& add_conf_file(std::string_view v); | |
489 | Builder& set_cluster(std::string_view c) { | |
490 | cluster = std::string(c); | |
491 | return *this; | |
492 | } | |
493 | Builder& set_name(std::string_view n) { | |
494 | name = std::string(n); | |
495 | return *this; | |
496 | } | |
497 | Builder& set_no_default_conf() { | |
498 | no_default_conf = true; | |
499 | return *this; | |
500 | } | |
501 | Builder& set_no_mon_conf() { | |
502 | no_mon_conf = true; | |
503 | return *this; | |
504 | } | |
505 | Builder& set_conf_option(std::string_view opt, std::string_view val) { | |
506 | configs.emplace_back(std::string(opt), std::string(val)); | |
507 | return *this; | |
508 | } | |
509 | ||
510 | template<typename CompletionToken> | |
511 | auto build(boost::asio::io_context& ioctx, CompletionToken&& token) { | |
512 | boost::asio::async_completion<CompletionToken, BuildSig> init(token); | |
513 | build(ioctx, | |
514 | BuildComp::create(ioctx.get_executor(), | |
515 | std::move(init.completion_handler))); | |
516 | return init.result.get(); | |
517 | } | |
518 | ||
519 | private: | |
520 | void build(boost::asio::io_context& ioctx, | |
521 | std::unique_ptr<BuildComp> c); | |
522 | }; | |
523 | ||
524 | ||
525 | template<typename CompletionToken> | |
526 | static auto make_with_cct(CephContext* cct, | |
527 | boost::asio::io_context& ioctx, | |
528 | CompletionToken&& token) { | |
529 | boost::asio::async_completion<CompletionToken, BuildSig> init(token); | |
530 | make_with_cct(cct, ioctx, | |
531 | BuildComp::create(ioctx.get_executor(), | |
532 | std::move(init.completion_handler))); | |
533 | return init.result.get(); | |
534 | } | |
535 | ||
536 | static RADOS make_with_librados(librados::Rados& rados); | |
537 | ||
538 | RADOS(const RADOS&) = delete; | |
539 | RADOS& operator =(const RADOS&) = delete; | |
540 | ||
541 | RADOS(RADOS&&); | |
542 | RADOS& operator =(RADOS&&); | |
543 | ||
544 | ~RADOS(); | |
545 | ||
546 | CephContext* cct(); | |
547 | ||
548 | using executor_type = boost::asio::io_context::executor_type; | |
549 | executor_type get_executor() const; | |
550 | boost::asio::io_context& get_io_context(); | |
551 | ||
552 | template<typename CompletionToken> | |
553 | auto execute(const Object& o, const IOContext& ioc, ReadOp&& op, | |
554 | ceph::buffer::list* bl, | |
555 | CompletionToken&& token, uint64_t* objver = nullptr, | |
556 | const blkin_trace_info* trace_info = nullptr) { | |
557 | boost::asio::async_completion<CompletionToken, Op::Signature> init(token); | |
558 | execute(o, ioc, std::move(op), bl, | |
559 | ReadOp::Completion::create(get_executor(), | |
560 | std::move(init.completion_handler)), | |
561 | objver, trace_info); | |
562 | return init.result.get(); | |
563 | } | |
564 | ||
565 | template<typename CompletionToken> | |
566 | auto execute(const Object& o, const IOContext& ioc, WriteOp&& op, | |
567 | CompletionToken&& token, uint64_t* objver = nullptr, | |
568 | const blkin_trace_info* trace_info = nullptr) { | |
569 | boost::asio::async_completion<CompletionToken, Op::Signature> init(token); | |
570 | execute(o, ioc, std::move(op), | |
571 | Op::Completion::create(get_executor(), | |
572 | std::move(init.completion_handler)), | |
573 | objver, trace_info); | |
574 | return init.result.get(); | |
575 | } | |
576 | ||
577 | template<typename CompletionToken> | |
578 | auto execute(const Object& o, std::int64_t pool, | |
579 | ReadOp&& op, | |
580 | ceph::buffer::list* bl, | |
581 | CompletionToken&& token, | |
582 | std::optional<std::string_view> ns = {}, | |
583 | std::optional<std::string_view> key = {}, | |
584 | uint64_t* objver = nullptr) { | |
585 | boost::asio::async_completion<CompletionToken, Op::Signature> init(token); | |
586 | execute(o, pool, std::move(op), bl, | |
587 | ReadOp::Completion::create(get_executor(), | |
588 | std::move(init.completion_handler)), | |
589 | ns, key, objver); | |
590 | return init.result.get(); | |
591 | } | |
592 | ||
593 | template<typename CompletionToken> | |
594 | auto execute(const Object& o, std::int64_t pool, WriteOp&& op, | |
595 | CompletionToken&& token, | |
596 | std::optional<std::string_view> ns = {}, | |
597 | std::optional<std::string_view> key = {}, | |
598 | uint64_t* objver = nullptr) { | |
599 | boost::asio::async_completion<CompletionToken, Op::Signature> init(token); | |
600 | execute(o, pool, std::move(op), | |
601 | Op::Completion::create(get_executor(), | |
602 | std::move(init.completion_handler)), | |
603 | ns, key, objver); | |
604 | return init.result.get(); | |
605 | } | |
606 | ||
607 | boost::uuids::uuid get_fsid() const noexcept; | |
608 | ||
609 | using LookupPoolSig = void(boost::system::error_code, | |
610 | std::int64_t); | |
611 | using LookupPoolComp = ceph::async::Completion<LookupPoolSig>; | |
612 | template<typename CompletionToken> | |
613 | auto lookup_pool(std::string_view name, | |
614 | CompletionToken&& token) { | |
615 | boost::asio::async_completion<CompletionToken, LookupPoolSig> init(token); | |
616 | lookup_pool(name, | |
617 | LookupPoolComp::create(get_executor(), | |
618 | std::move(init.completion_handler))); | |
619 | return init.result.get(); | |
620 | } | |
621 | ||
622 | std::optional<uint64_t> get_pool_alignment(int64_t pool_id); | |
623 | ||
624 | using LSPoolsSig = void(std::vector<std::pair<std::int64_t, std::string>>); | |
625 | using LSPoolsComp = ceph::async::Completion<LSPoolsSig>; | |
626 | template<typename CompletionToken> | |
627 | auto list_pools(CompletionToken&& token) { | |
628 | boost::asio::async_completion<CompletionToken, LSPoolsSig> init(token); | |
629 | list_pools(LSPoolsComp::create(get_executor(), | |
630 | std::move(init.completion_handler))); | |
631 | return init.result.get(); | |
632 | } | |
633 | ||
634 | ||
635 | ||
636 | using SimpleOpSig = void(boost::system::error_code); | |
637 | using SimpleOpComp = ceph::async::Completion<SimpleOpSig>; | |
638 | template<typename CompletionToken> | |
639 | auto create_pool_snap(int64_t pool, std::string_view snapName, | |
640 | CompletionToken&& token) { | |
641 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
642 | create_pool_snap(pool, snapName, | |
643 | SimpleOpComp::create(get_executor(), | |
644 | std::move(init.completion_handler))); | |
645 | return init.result.get(); | |
646 | } | |
647 | ||
648 | using SMSnapSig = void(boost::system::error_code, std::uint64_t); | |
649 | using SMSnapComp = ceph::async::Completion<SMSnapSig>; | |
650 | template<typename CompletionToken> | |
651 | auto allocate_selfmanaged_snap(int64_t pool, | |
652 | CompletionToken&& token) { | |
653 | boost::asio::async_completion<CompletionToken, SMSnapSig> init(token); | |
654 | allocate_selfmanaged_snap(pool, | |
655 | SMSnapComp::create( | |
656 | get_executor(), | |
657 | std::move(init.completion_handler))); | |
658 | return init.result.get(); | |
659 | } | |
660 | ||
661 | template<typename CompletionToken> | |
662 | auto delete_pool_snap(int64_t pool, std::string_view snapName, | |
663 | CompletionToken&& token) { | |
664 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
665 | delete_pool_snap(pool, snapName, | |
666 | SimpleOpComp::create(get_executor(), | |
667 | std::move(init.completion_handler))); | |
668 | return init.result.get(); | |
669 | } | |
670 | ||
671 | template<typename CompletionToken> | |
672 | auto delete_selfmanaged_snap(int64_t pool, std::string_view snapName, | |
673 | CompletionToken&& token) { | |
674 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
675 | delete_selfmanaged_snap(pool, snapName, | |
676 | SimpleOpComp::create( | |
677 | get_executor(), | |
678 | std::move(init.completion_handler))); | |
679 | return init.result.get(); | |
680 | } | |
681 | ||
682 | template<typename CompletionToken> | |
683 | auto create_pool(std::string_view name, std::optional<int> crush_rule, | |
684 | CompletionToken&& token) { | |
685 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
686 | create_pool(name, crush_rule, | |
687 | SimpleOpComp::create(get_executor(), | |
688 | std::move(init.completion_handler))); | |
689 | return init.result.get(); | |
690 | } | |
691 | ||
692 | template<typename CompletionToken> | |
693 | auto delete_pool(std::string_view name, | |
694 | CompletionToken&& token) { | |
695 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
696 | delete_pool(name, | |
697 | SimpleOpComp::create(get_executor(), | |
698 | std::move(init.completion_handler))); | |
699 | return init.result.get(); | |
700 | } | |
701 | ||
702 | template<typename CompletionToken> | |
703 | auto delete_pool(int64_t pool, | |
704 | CompletionToken&& token) { | |
705 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
706 | delete_pool(pool, | |
707 | SimpleOpComp::create(get_executor(), | |
708 | std::move(init.completion_handler))); | |
709 | return init.result.get(); | |
710 | } | |
711 | ||
712 | using PoolStatSig = void(boost::system::error_code, | |
713 | boost::container::flat_map<std::string, | |
714 | PoolStats>, bool); | |
715 | using PoolStatComp = ceph::async::Completion<PoolStatSig>; | |
716 | template<typename CompletionToken> | |
717 | auto stat_pools(const std::vector<std::string>& pools, | |
718 | CompletionToken&& token) { | |
719 | boost::asio::async_completion<CompletionToken, PoolStatSig> init(token); | |
720 | stat_pools(pools, | |
721 | PoolStatComp::create(get_executor(), | |
722 | std::move(init.completion_handler))); | |
723 | return init.result.get(); | |
724 | } | |
725 | ||
726 | using StatFSSig = void(boost::system::error_code, | |
727 | FSStats); | |
728 | using StatFSComp = ceph::async::Completion<StatFSSig>; | |
729 | template<typename CompletionToken> | |
730 | auto statfs(std::optional<int64_t> pool, | |
731 | CompletionToken&& token) { | |
732 | boost::asio::async_completion<CompletionToken, StatFSSig> init(token); | |
733 | ceph_statfs(pool, StatFSComp::create(get_executor(), | |
734 | std::move(init.completion_handler))); | |
735 | return init.result.get(); | |
736 | } | |
737 | ||
738 | using WatchCB = fu2::unique_function<void(boost::system::error_code, | |
739 | uint64_t notify_id, | |
740 | uint64_t cookie, | |
741 | uint64_t notifier_id, | |
742 | ceph::buffer::list&& bl)>; | |
743 | ||
744 | using WatchSig = void(boost::system::error_code ec, | |
745 | uint64_t cookie); | |
746 | using WatchComp = ceph::async::Completion<WatchSig>; | |
747 | template<typename CompletionToken> | |
748 | auto watch(const Object& o, const IOContext& ioc, | |
749 | std::optional<std::chrono::seconds> timeout, | |
750 | WatchCB&& cb, CompletionToken&& token) { | |
751 | boost::asio::async_completion<CompletionToken, WatchSig> init(token); | |
752 | watch(o, ioc, timeout, std::move(cb), | |
753 | WatchComp::create(get_executor(), | |
754 | std::move(init.completion_handler))); | |
755 | return init.result.get(); | |
756 | } | |
757 | ||
758 | template<typename CompletionToken> | |
759 | auto watch(const Object& o, std::int64_t pool, | |
760 | std::optional<std::chrono::seconds> timeout, | |
761 | WatchCB&& cb, CompletionToken&& token, | |
762 | std::optional<std::string_view> ns = {}, | |
763 | std::optional<std::string_view> key = {}) { | |
764 | boost::asio::async_completion<CompletionToken, WatchSig> init(token); | |
765 | watch(o, pool, timeout, std::move(cb), | |
766 | WatchComp::create(get_executor(), | |
767 | std::move(init.completion_handler)), | |
768 | ns, key); | |
769 | return init.result.get(); | |
770 | } | |
771 | ||
772 | template<typename CompletionToken> | |
773 | auto notify_ack(const Object& o, | |
774 | const IOContext& ioc, | |
775 | uint64_t notify_id, | |
776 | uint64_t cookie, | |
777 | ceph::buffer::list&& bl, | |
778 | CompletionToken&& token) { | |
779 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
780 | notify_ack(o, ioc, notify_id, cookie, std::move(bl), | |
781 | SimpleOpComp::create(get_executor(), | |
782 | std::move(init.completion_handler))); | |
783 | return init.result.get(); | |
784 | } | |
785 | ||
786 | template<typename CompletionToken> | |
787 | auto notify_ack(const Object& o, | |
788 | std::int64_t pool, | |
789 | uint64_t notify_id, | |
790 | uint64_t cookie, | |
791 | ceph::buffer::list&& bl, | |
792 | CompletionToken&& token, | |
793 | std::optional<std::string_view> ns = {}, | |
794 | std::optional<std::string_view> key = {}) { | |
795 | boost::asio::async_completion<CompletionToken, WatchSig> init(token); | |
796 | notify_ack(o, pool, notify_id, cookie, std::move(bl), | |
797 | SimpleOpComp::create(get_executor(), | |
798 | std::move(init.completion_handler)), | |
799 | ns, key); | |
800 | return init.result.get(); | |
801 | } | |
802 | ||
803 | template<typename CompletionToken> | |
804 | auto unwatch(uint64_t cookie, const IOContext& ioc, | |
805 | CompletionToken&& token) { | |
806 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
807 | unwatch(cookie, ioc, | |
808 | SimpleOpComp::create(get_executor(), | |
809 | std::move(init.completion_handler))); | |
810 | return init.result.get(); | |
811 | } | |
812 | ||
813 | template<typename CompletionToken> | |
814 | auto unwatch(uint64_t cookie, std::int64_t pool, | |
815 | CompletionToken&& token, | |
816 | std::optional<std::string_view> ns = {}, | |
817 | std::optional<std::string_view> key = {}) { | |
818 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
819 | unwatch(cookie, pool, | |
820 | SimpleOpComp::create(get_executor(), | |
821 | std::move(init.completion_handler)), | |
822 | ns, key); | |
823 | return init.result.get(); | |
824 | } | |
825 | ||
826 | // This is one of those places where having to force everything into | |
827 | // a .cc file is really infuriating. If we had modules, that would | |
828 | // let us separate out the implementation details without | |
829 | // sacrificing all the benefits of templates. | |
830 | using VoidOpSig = void(); | |
831 | using VoidOpComp = ceph::async::Completion<VoidOpSig>; | |
832 | template<typename CompletionToken> | |
833 | auto flush_watch(CompletionToken&& token) { | |
834 | boost::asio::async_completion<CompletionToken, VoidOpSig> init(token); | |
835 | flush_watch(VoidOpComp::create(get_executor(), | |
836 | std::move(init.completion_handler))); | |
837 | return init.result.get(); | |
838 | } | |
839 | ||
840 | using NotifySig = void(boost::system::error_code, ceph::buffer::list); | |
841 | using NotifyComp = ceph::async::Completion<NotifySig>; | |
842 | template<typename CompletionToken> | |
843 | auto notify(const Object& oid, const IOContext& ioc, ceph::buffer::list&& bl, | |
844 | std::optional<std::chrono::milliseconds> timeout, | |
845 | CompletionToken&& token) { | |
846 | boost::asio::async_completion<CompletionToken, NotifySig> init(token); | |
847 | notify(oid, ioc, std::move(bl), timeout, | |
848 | NotifyComp::create(get_executor(), | |
849 | std::move(init.completion_handler))); | |
850 | ||
851 | return init.result.get(); | |
852 | } | |
853 | ||
854 | template<typename CompletionToken> | |
855 | auto notify(const Object& oid, std::int64_t pool, ceph::buffer::list&& bl, | |
856 | std::optional<std::chrono::milliseconds> timeout, | |
857 | CompletionToken&& token, | |
858 | std::optional<std::string_view> ns = {}, | |
859 | std::optional<std::string_view> key = {}) { | |
860 | boost::asio::async_completion<CompletionToken, NotifySig> init(token); | |
861 | notify(oid, pool, bl, timeout, | |
862 | NotifyComp::create(get_executor(), | |
863 | std::move(init.completion_handler)), | |
864 | ns, key); | |
865 | ||
866 | return init.result.get(); | |
867 | } | |
868 | ||
869 | // The versions with pointers are fine for coroutines, but | |
870 | // extraordinarily unappealing for callback-oriented programming. | |
871 | using EnumerateSig = void(boost::system::error_code, | |
872 | std::vector<Entry>, | |
873 | Cursor); | |
874 | using EnumerateComp = ceph::async::Completion<EnumerateSig>; | |
875 | template<typename CompletionToken> | |
876 | auto enumerate_objects(const IOContext& ioc, const Cursor& begin, | |
877 | const Cursor& end, const std::uint32_t max, | |
878 | const ceph::buffer::list& filter, | |
879 | CompletionToken&& token) { | |
880 | boost::asio::async_completion<CompletionToken, EnumerateSig> init(token); | |
881 | enumerate_objects(ioc, begin, end, max, filter, | |
882 | EnumerateComp::create(get_executor(), | |
883 | std::move(init.completion_handler))); | |
884 | return init.result.get(); | |
885 | } | |
886 | ||
887 | template<typename CompletionToken> | |
888 | auto enumerate_objects(std::int64_t pool, const Cursor& begin, | |
889 | const Cursor& end, const std::uint32_t max, | |
890 | const ceph::buffer::list& filter, | |
891 | CompletionToken&& token, | |
892 | std::optional<std::string_view> ns = {}, | |
893 | std::optional<std::string_view> key = {}) { | |
894 | boost::asio::async_completion<CompletionToken, EnumerateSig> init(token); | |
895 | enumerate_objects(pool, begin, end, max, filter, | |
896 | EnumerateComp::create(get_executor(), | |
897 | std::move(init.completion_handler)), | |
898 | ns, key); | |
899 | return init.result.get(); | |
900 | } | |
901 | ||
902 | using CommandSig = void(boost::system::error_code, | |
903 | std::string, ceph::buffer::list); | |
904 | using CommandComp = ceph::async::Completion<CommandSig>; | |
905 | template<typename CompletionToken> | |
906 | auto osd_command(int osd, std::vector<std::string>&& cmd, | |
907 | ceph::buffer::list&& in, CompletionToken&& token) { | |
908 | boost::asio::async_completion<CompletionToken, CommandSig> init(token); | |
909 | osd_command(osd, std::move(cmd), std::move(in), | |
910 | CommandComp::create(get_executor(), | |
911 | std::move(init.completion_handler))); | |
912 | return init.result.get(); | |
913 | } | |
914 | template<typename CompletionToken> | |
915 | auto pg_command(PG pg, std::vector<std::string>&& cmd, | |
916 | ceph::buffer::list&& in, CompletionToken&& token) { | |
917 | boost::asio::async_completion<CompletionToken, CommandSig> init(token); | |
918 | pg_command(pg, std::move(cmd), std::move(in), | |
919 | CommandComp::create(get_executor(), | |
920 | std::move(init.completion_handler))); | |
921 | return init.result.get(); | |
922 | } | |
923 | ||
924 | template<typename CompletionToken> | |
925 | auto mon_command(std::vector<std::string> command, | |
926 | const ceph::buffer::list& bl, | |
927 | std::string* outs, ceph::buffer::list* outbl, | |
928 | CompletionToken&& token) { | |
929 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
930 | mon_command(command, bl, outs, outbl, | |
931 | SimpleOpComp::create(get_executor(), | |
932 | std::move(init.completion_handler))); | |
933 | return init.result.get(); | |
934 | } | |
935 | ||
936 | template<typename CompletionToken> | |
937 | auto enable_application(std::string_view pool, std::string_view app_name, | |
938 | bool force, CompletionToken&& token) { | |
939 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
940 | enable_application(pool, app_name, force, | |
941 | SimpleOpComp::create(get_executor(), | |
942 | std::move(init.completion_handler))); | |
943 | return init.result.get(); | |
944 | } | |
945 | ||
946 | template<typename CompletionToken> | |
947 | auto blocklist_add(std::string_view client_address, | |
948 | std::optional<std::chrono::seconds> expire, | |
949 | CompletionToken&& token) { | |
950 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
951 | blocklist_add(client_address, expire, | |
952 | SimpleOpComp::create(get_executor(), | |
953 | std::move(init.completion_handler))); | |
954 | return init.result.get(); | |
955 | } | |
956 | ||
957 | template<typename CompletionToken> | |
958 | auto wait_for_latest_osd_map(CompletionToken&& token) { | |
959 | boost::asio::async_completion<CompletionToken, SimpleOpSig> init(token); | |
960 | wait_for_latest_osd_map( | |
961 | SimpleOpComp::create(get_executor(), std::move(init.completion_handler))); | |
962 | return init.result.get(); | |
963 | } | |
964 | ||
965 | uint64_t instance_id() const; | |
966 | ||
967 | private: | |
968 | ||
969 | RADOS(); | |
970 | ||
971 | friend Builder; | |
972 | ||
973 | RADOS(std::unique_ptr<detail::Client> impl); | |
974 | static void make_with_cct(CephContext* cct, | |
975 | boost::asio::io_context& ioctx, | |
976 | std::unique_ptr<BuildComp> c); | |
977 | ||
978 | void execute(const Object& o, const IOContext& ioc, ReadOp&& op, | |
979 | ceph::buffer::list* bl, std::unique_ptr<Op::Completion> c, | |
980 | uint64_t* objver, const blkin_trace_info* trace_info); | |
981 | ||
982 | void execute(const Object& o, const IOContext& ioc, WriteOp&& op, | |
983 | std::unique_ptr<Op::Completion> c, uint64_t* objver, | |
984 | const blkin_trace_info* trace_info); | |
985 | ||
986 | void execute(const Object& o, std::int64_t pool, ReadOp&& op, | |
987 | ceph::buffer::list* bl, std::unique_ptr<Op::Completion> c, | |
988 | std::optional<std::string_view> ns, | |
989 | std::optional<std::string_view> key, | |
990 | uint64_t* objver); | |
991 | ||
992 | void execute(const Object& o, std::int64_t pool, WriteOp&& op, | |
993 | std::unique_ptr<Op::Completion> c, | |
994 | std::optional<std::string_view> ns, | |
995 | std::optional<std::string_view> key, | |
996 | uint64_t* objver); | |
997 | ||
998 | void lookup_pool(std::string_view name, std::unique_ptr<LookupPoolComp> c); | |
999 | void list_pools(std::unique_ptr<LSPoolsComp> c); | |
1000 | void create_pool_snap(int64_t pool, std::string_view snapName, | |
1001 | std::unique_ptr<SimpleOpComp> c); | |
1002 | void allocate_selfmanaged_snap(int64_t pool, std::unique_ptr<SMSnapComp> c); | |
1003 | void delete_pool_snap(int64_t pool, std::string_view snapName, | |
1004 | std::unique_ptr<SimpleOpComp> c); | |
1005 | void delete_selfmanaged_snap(int64_t pool, std::uint64_t snap, | |
1006 | std::unique_ptr<SimpleOpComp> c); | |
1007 | void create_pool(std::string_view name, std::optional<int> crush_rule, | |
1008 | std::unique_ptr<SimpleOpComp> c); | |
1009 | void delete_pool(std::string_view name, | |
1010 | std::unique_ptr<SimpleOpComp> c); | |
1011 | void delete_pool(int64_t pool, | |
1012 | std::unique_ptr<SimpleOpComp> c); | |
1013 | void stat_pools(const std::vector<std::string>& pools, | |
1014 | std::unique_ptr<PoolStatComp> c); | |
1015 | void stat_fs(std::optional<std::int64_t> pool, | |
1016 | std::unique_ptr<StatFSComp> c); | |
1017 | ||
1018 | void watch(const Object& o, const IOContext& ioc, | |
1019 | std::optional<std::chrono::seconds> timeout, | |
1020 | WatchCB&& cb, std::unique_ptr<WatchComp> c); | |
1021 | void watch(const Object& o, std::int64_t pool, | |
1022 | std::optional<std::chrono::seconds> timeout, | |
1023 | WatchCB&& cb, std::unique_ptr<WatchComp> c, | |
1024 | std::optional<std::string_view> ns, | |
1025 | std::optional<std::string_view> key); | |
1026 | tl::expected<ceph::timespan, boost::system::error_code> | |
1027 | watch_check(uint64_t cookie); | |
1028 | void notify_ack(const Object& o, | |
1029 | const IOContext& _ioc, | |
1030 | uint64_t notify_id, | |
1031 | uint64_t cookie, | |
1032 | ceph::buffer::list&& bl, | |
1033 | std::unique_ptr<SimpleOpComp>); | |
1034 | void notify_ack(const Object& o, | |
1035 | std::int64_t pool, | |
1036 | uint64_t notify_id, | |
1037 | uint64_t cookie, | |
1038 | ceph::buffer::list&& bl, | |
1039 | std::unique_ptr<SimpleOpComp>, | |
1040 | std::optional<std::string_view> ns, | |
1041 | std::optional<std::string_view> key); | |
1042 | void unwatch(uint64_t cookie, const IOContext& ioc, | |
1043 | std::unique_ptr<SimpleOpComp>); | |
1044 | void unwatch(uint64_t cookie, std::int64_t pool, | |
1045 | std::unique_ptr<SimpleOpComp>, | |
1046 | std::optional<std::string_view> ns, | |
1047 | std::optional<std::string_view> key); | |
1048 | void notify(const Object& oid, const IOContext& ioctx, | |
1049 | ceph::buffer::list&& bl, | |
1050 | std::optional<std::chrono::milliseconds> timeout, | |
1051 | std::unique_ptr<NotifyComp> c); | |
1052 | void notify(const Object& oid, std::int64_t pool, | |
1053 | ceph::buffer::list&& bl, | |
1054 | std::optional<std::chrono::milliseconds> timeout, | |
1055 | std::unique_ptr<NotifyComp> c, | |
1056 | std::optional<std::string_view> ns, | |
1057 | std::optional<std::string_view> key); | |
1058 | void flush_watch(std::unique_ptr<VoidOpComp>); | |
1059 | ||
1060 | void enumerate_objects(const IOContext& ioc, const Cursor& begin, | |
1061 | const Cursor& end, const std::uint32_t max, | |
1062 | const ceph::buffer::list& filter, | |
1063 | std::vector<Entry>* ls, | |
1064 | Cursor* cursor, | |
1065 | std::unique_ptr<SimpleOpComp> c); | |
1066 | void enumerate_objects(std::int64_t pool, const Cursor& begin, | |
1067 | const Cursor& end, const std::uint32_t max, | |
1068 | const ceph::buffer::list& filter, | |
1069 | std::vector<Entry>* ls, | |
1070 | Cursor* cursor, | |
1071 | std::unique_ptr<SimpleOpComp> c, | |
1072 | std::optional<std::string_view> ns, | |
1073 | std::optional<std::string_view> key); | |
1074 | void enumerate_objects(const IOContext& ioc, const Cursor& begin, | |
1075 | const Cursor& end, const std::uint32_t max, | |
1076 | const ceph::buffer::list& filter, | |
1077 | std::unique_ptr<EnumerateComp> c); | |
1078 | void enumerate_objects(std::int64_t pool, const Cursor& begin, | |
1079 | const Cursor& end, const std::uint32_t max, | |
1080 | const ceph::buffer::list& filter, | |
1081 | std::unique_ptr<EnumerateComp> c, | |
1082 | std::optional<std::string_view> ns, | |
1083 | std::optional<std::string_view> key); | |
1084 | void osd_command(int osd, std::vector<std::string>&& cmd, | |
1085 | ceph::buffer::list&& in, std::unique_ptr<CommandComp> c); | |
1086 | void pg_command(PG pg, std::vector<std::string>&& cmd, | |
1087 | ceph::buffer::list&& in, std::unique_ptr<CommandComp> c); | |
1088 | ||
1089 | void mon_command(std::vector<std::string> command, | |
1090 | const ceph::buffer::list& bl, | |
1091 | std::string* outs, ceph::buffer::list* outbl, | |
1092 | std::unique_ptr<SimpleOpComp> c); | |
1093 | ||
1094 | void enable_application(std::string_view pool, std::string_view app_name, | |
1095 | bool force, std::unique_ptr<SimpleOpComp> c); | |
1096 | ||
1097 | void blocklist_add(std::string_view client_address, | |
1098 | std::optional<std::chrono::seconds> expire, | |
1099 | std::unique_ptr<SimpleOpComp> c); | |
1100 | ||
1101 | void wait_for_latest_osd_map(std::unique_ptr<SimpleOpComp> c); | |
1102 | ||
1103 | // Proxy object to provide access to low-level RADOS messaging clients | |
1104 | std::unique_ptr<detail::Client> impl; | |
1105 | }; | |
1106 | ||
1107 | enum class errc { | |
1108 | pool_dne = 1, | |
1109 | invalid_snapcontext | |
1110 | }; | |
1111 | ||
1112 | const boost::system::error_category& error_category() noexcept; | |
1113 | } | |
1114 | ||
1115 | namespace boost::system { | |
1116 | template<> | |
1117 | struct is_error_code_enum<::neorados::errc> { | |
1118 | static const bool value = true; | |
1119 | }; | |
1120 | ||
1121 | template<> | |
1122 | struct is_error_condition_enum<::neorados::errc> { | |
1123 | static const bool value = false; | |
1124 | }; | |
1125 | } | |
1126 | ||
1127 | namespace neorados { | |
1128 | // explicit conversion: | |
1129 | inline boost::system::error_code make_error_code(errc e) noexcept { | |
1130 | return { static_cast<int>(e), error_category() }; | |
1131 | } | |
1132 | ||
1133 | // implicit conversion: | |
1134 | inline boost::system::error_condition make_error_condition(errc e) noexcept { | |
1135 | return { static_cast<int>(e), error_category() }; | |
1136 | } | |
1137 | } | |
1138 | ||
1139 | namespace std { | |
1140 | template<> | |
1141 | struct hash<neorados::Object> { | |
1142 | size_t operator ()(const neorados::Object& r) const; | |
1143 | }; | |
1144 | template<> | |
1145 | struct hash<neorados::IOContext> { | |
1146 | size_t operator ()(const neorados::IOContext& r) const; | |
1147 | }; | |
1148 | } // namespace std | |
1149 | ||
1150 | #endif // NEORADOS_RADOS_HPP |