1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "cyan_store.h"
6 #include <boost/algorithm/string/trim.hpp>
7 #include <fmt/format.h>
8 #include <fmt/ostream.h>
10 #include "common/safe_io.h"
11 #include "os/Transaction.h"
13 #include "crimson/common/buffer_io.h"
14 #include "crimson/common/config_proxy.h"
15 #include "cyan_collection.h"
16 #include "cyan_object.h"
19 seastar::logger
& logger() {
20 return crimson::get_logger(ceph_subsys_filestore
);
25 using crimson::common::local_conf
;
27 namespace crimson::os
{
29 using ObjectRef
= boost::intrusive_ptr
<Object
>;
31 CyanStore::CyanStore(const std::string
& path
)
35 CyanStore::~CyanStore() = default;
37 template <const char* MsgV
>
38 struct singleton_ec
: std::error_code
{
40 : error_code(42, this_error_category
{}) {
43 struct this_error_category
: std::error_category
{
44 const char* name() const noexcept final
{
45 // XXX: we could concatenate with MsgV at compile-time but the burden
46 // isn't worth the benefit.
47 return "singleton_ec";
49 std::string
message([[maybe_unused
]] const int ev
) const final
{
56 CyanStore::mount_ertr::future
<> CyanStore::mount()
58 static const char read_file_errmsg
[]{"read_file"};
60 std::string fn
= path
+ "/collections";
62 if (int r
= bl
.read_file(fn
.c_str(), &err
); r
< 0) {
63 return crimson::stateful_ec
{ singleton_ec
<read_file_errmsg
>() };
66 std::set
<coll_t
> collections
;
68 ceph::decode(collections
, p
);
70 for (auto& coll
: collections
) {
71 std::string fn
= fmt::format("{}/{}", path
, coll
);
73 if (int r
= cbl
.read_file(fn
.c_str(), &err
); r
< 0) {
74 return crimson::stateful_ec
{ singleton_ec
<read_file_errmsg
>() };
76 boost::intrusive_ptr
<Collection
> c
{new Collection
{coll
}};
77 auto p
= cbl
.cbegin();
80 used_bytes
+= c
->used_bytes();
82 return mount_ertr::now();
85 seastar::future
<> CyanStore::umount()
87 return seastar::do_with(std::set
<coll_t
>{}, [this](auto& collections
) {
88 return seastar::do_for_each(coll_map
, [&collections
, this](auto& coll
) {
89 auto& [col
, ch
] = coll
;
90 collections
.insert(col
);
94 std::string fn
= fmt::format("{}/{}", path
, col
);
95 return crimson::write_file(std::move(bl
), fn
);
96 }).then([&collections
, this] {
98 ceph::encode(collections
, bl
);
99 std::string fn
= fmt::format("{}/collections", path
);
100 return crimson::write_file(std::move(bl
), fn
);
105 CyanStore::mkfs_ertr::future
<> CyanStore::mkfs(uuid_d new_osd_fsid
)
107 static const char read_meta_errmsg
[]{"read_meta"};
108 static const char parse_fsid_errmsg
[]{"failed to parse fsid"};
109 static const char match_ofsid_errmsg
[]{"unmatched osd_fsid"};
110 return read_meta("fsid").then([=](auto&& ret
) -> mkfs_ertr::future
<> {
111 auto& [r
, fsid_str
] = ret
;
113 if (new_osd_fsid
.is_zero()) {
114 osd_fsid
.generate_random();
116 osd_fsid
= new_osd_fsid
;
118 return write_meta("fsid", fmt::format("{}", osd_fsid
));
120 return crimson::stateful_ec
{ singleton_ec
<read_meta_errmsg
>() };
122 logger().info("mkfs already has fsid {}", fsid_str
);
123 if (!osd_fsid
.parse(fsid_str
.c_str())) {
124 return crimson::stateful_ec
{ singleton_ec
<parse_fsid_errmsg
>() };
125 } else if (osd_fsid
!= new_osd_fsid
) {
126 logger().error("on-disk fsid {} != provided {}", osd_fsid
, new_osd_fsid
);
127 return crimson::stateful_ec
{ singleton_ec
<match_ofsid_errmsg
>() };
129 return mkfs_ertr::now();
133 std::string fn
= path
+ "/collections";
135 std::set
<coll_t
> collections
;
136 ceph::encode(collections
, bl
);
137 return crimson::write_file(std::move(bl
), fn
);
138 }).safe_then([this] {
139 return write_meta("type", "memstore");
143 seastar::future
<store_statfs_t
> CyanStore::stat() const
145 logger().debug("{}", __func__
);
147 st
.total
= crimson::common::local_conf().get_val
<Option::size_t>("memstore_device_bytes");
148 st
.available
= st
.total
- used_bytes
;
149 return seastar::make_ready_future
<store_statfs_t
>(std::move(st
));
152 seastar::future
<std::tuple
<std::vector
<ghobject_t
>, ghobject_t
>>
153 CyanStore::list_objects(CollectionRef ch
,
154 const ghobject_t
& start
,
155 const ghobject_t
& end
,
156 uint64_t limit
) const
158 auto c
= static_cast<Collection
*>(ch
.get());
159 logger().debug("{} {} {} {} {}",
160 __func__
, c
->get_cid(), start
, end
, limit
);
161 std::vector
<ghobject_t
> objects
;
162 objects
.reserve(limit
);
163 ghobject_t next
= ghobject_t::get_max();
164 for (const auto& [oid
, obj
] :
165 boost::make_iterator_range(c
->object_map
.lower_bound(start
),
166 c
->object_map
.end())) {
168 if (oid
>= end
|| objects
.size() >= limit
) {
172 objects
.push_back(oid
);
174 return seastar::make_ready_future
<std::tuple
<std::vector
<ghobject_t
>, ghobject_t
>>(
175 std::make_tuple(std::move(objects
), next
));
178 seastar::future
<CollectionRef
> CyanStore::create_new_collection(const coll_t
& cid
)
180 auto c
= new Collection
{cid
};
181 new_coll_map
[cid
] = c
;
182 return seastar::make_ready_future
<CollectionRef
>(c
);
185 seastar::future
<CollectionRef
> CyanStore::open_collection(const coll_t
& cid
)
187 return seastar::make_ready_future
<CollectionRef
>(_get_collection(cid
));
190 seastar::future
<std::vector
<coll_t
>> CyanStore::list_collections()
192 std::vector
<coll_t
> collections
;
193 for (auto& coll
: coll_map
) {
194 collections
.push_back(coll
.first
);
196 return seastar::make_ready_future
<std::vector
<coll_t
>>(std::move(collections
));
199 CyanStore::read_errorator::future
<ceph::bufferlist
> CyanStore::read(
201 const ghobject_t
& oid
,
206 auto c
= static_cast<Collection
*>(ch
.get());
207 logger().debug("{} {} {} {}~{}",
208 __func__
, c
->get_cid(), oid
, offset
, len
);
210 return crimson::ct_error::enoent::make();
212 ObjectRef o
= c
->get_object(oid
);
214 return crimson::ct_error::enoent::make();
216 if (offset
>= o
->get_size())
217 return read_errorator::make_ready_future
<ceph::bufferlist
>();
219 if (l
== 0 && offset
== 0) // note: len == 0 means read the entire object
221 else if (offset
+ l
> o
->get_size())
222 l
= o
->get_size() - offset
;
223 return read_errorator::make_ready_future
<ceph::bufferlist
>(o
->read(offset
, l
));
226 CyanStore::read_errorator::future
<ceph::bufferlist
> CyanStore::readv(
228 const ghobject_t
& oid
,
229 interval_set
<uint64_t>& m
,
232 return seastar::do_with(ceph::bufferlist
{},
233 [this, ch
, oid
, &m
, op_flags
](auto& bl
) {
234 return crimson::do_for_each(m
,
235 [this, ch
, oid
, op_flags
, &bl
](auto& p
) {
236 return read(ch
, oid
, p
.first
, p
.second
, op_flags
)
237 .safe_then([&bl
](auto ret
) {
238 bl
.claim_append(ret
);
241 return read_errorator::make_ready_future
<ceph::bufferlist
>(std::move(bl
));
247 CyanStore::get_attr_errorator::future
<ceph::bufferlist
> CyanStore::get_attr(
249 const ghobject_t
& oid
,
250 std::string_view name
) const
252 auto c
= static_cast<Collection
*>(ch
.get());
253 logger().debug("{} {} {}",
254 __func__
, c
->get_cid(), oid
);
255 auto o
= c
->get_object(oid
);
257 return crimson::ct_error::enoent::make();
259 if (auto found
= o
->xattr
.find(name
); found
!= o
->xattr
.end()) {
260 return get_attr_errorator::make_ready_future
<ceph::bufferlist
>(found
->second
);
262 return crimson::ct_error::enodata::make();
266 CyanStore::get_attrs_ertr::future
<CyanStore::attrs_t
> CyanStore::get_attrs(
268 const ghobject_t
& oid
)
270 auto c
= static_cast<Collection
*>(ch
.get());
271 logger().debug("{} {} {}",
272 __func__
, c
->get_cid(), oid
);
273 auto o
= c
->get_object(oid
);
275 return crimson::ct_error::enoent::make();
277 return get_attrs_ertr::make_ready_future
<attrs_t
>(o
->xattr
);
280 auto CyanStore::omap_get_values(CollectionRef ch
,
281 const ghobject_t
& oid
,
282 const omap_keys_t
& keys
)
283 -> read_errorator::future
<omap_values_t
>
285 auto c
= static_cast<Collection
*>(ch
.get());
286 logger().debug("{} {} {}", __func__
, c
->get_cid(), oid
);
287 auto o
= c
->get_object(oid
);
289 return crimson::ct_error::enoent::make();
291 omap_values_t values
;
292 for (auto& key
: keys
) {
293 if (auto found
= o
->omap
.find(key
); found
!= o
->omap
.end()) {
294 values
.insert(*found
);
297 return seastar::make_ready_future
<omap_values_t
>(std::move(values
));
301 CyanStore::omap_get_values(CollectionRef ch
,
302 const ghobject_t
&oid
,
303 const std::optional
<string
> &start
)
304 -> read_errorator::future
<std::tuple
<bool, omap_values_t
>>
306 auto c
= static_cast<Collection
*>(ch
.get());
307 logger().debug("{} {} {}", __func__
, c
->get_cid(), oid
);
308 auto o
= c
->get_object(oid
);
310 return crimson::ct_error::enoent::make();
312 omap_values_t values
;
313 for (auto i
= start
? o
->omap
.upper_bound(*start
) : o
->omap
.begin();
314 values
.size() < MAX_KEYS_PER_OMAP_GET_CALL
&& i
!= o
->omap
.end();
318 return seastar::make_ready_future
<std::tuple
<bool, omap_values_t
>>(
319 std::make_tuple(true, std::move(values
)));
323 CyanStore::omap_get_header(CollectionRef ch
,
324 const ghobject_t
& oid
)
325 -> read_errorator::future
<ceph::bufferlist
>
327 auto c
= static_cast<Collection
*>(ch
.get());
328 auto o
= c
->get_object(oid
);
330 return crimson::ct_error::enoent::make();
333 return read_errorator::make_ready_future
<ceph::bufferlist
>(
337 seastar::future
<> CyanStore::do_transaction(CollectionRef ch
,
338 ceph::os::Transaction
&& t
)
340 using ceph::os::Transaction
;
344 while (i
.have_op()) {
346 switch (auto op
= i
.decode_op(); op
->op
) {
347 case Transaction::OP_NOP
:
349 case Transaction::OP_REMOVE
:
351 coll_t cid
= i
.get_cid(op
->cid
);
352 ghobject_t oid
= i
.get_oid(op
->oid
);
353 r
= _remove(cid
, oid
);
359 case Transaction::OP_TOUCH
:
361 coll_t cid
= i
.get_cid(op
->cid
);
362 ghobject_t oid
= i
.get_oid(op
->oid
);
363 r
= _touch(cid
, oid
);
366 case Transaction::OP_WRITE
:
368 coll_t cid
= i
.get_cid(op
->cid
);
369 ghobject_t oid
= i
.get_oid(op
->oid
);
370 uint64_t off
= op
->off
;
371 uint64_t len
= op
->len
;
372 uint32_t fadvise_flags
= i
.get_fadvise_flags();
375 r
= _write(cid
, oid
, off
, len
, bl
, fadvise_flags
);
378 case Transaction::OP_ZERO
:
380 coll_t cid
= i
.get_cid(op
->cid
);
381 ghobject_t oid
= i
.get_oid(op
->oid
);
382 uint64_t off
= op
->off
;
383 uint64_t len
= op
->len
;
384 r
= _zero(cid
, oid
, off
, len
);
387 case Transaction::OP_TRUNCATE
:
389 coll_t cid
= i
.get_cid(op
->cid
);
390 ghobject_t oid
= i
.get_oid(op
->oid
);
391 uint64_t off
= op
->off
;
392 r
= _truncate(cid
, oid
, off
);
395 case Transaction::OP_SETATTR
:
397 coll_t cid
= i
.get_cid(op
->cid
);
398 ghobject_t oid
= i
.get_oid(op
->oid
);
399 std::string name
= i
.decode_string();
402 std::map
<std::string
, bufferlist
> to_set
;
403 to_set
.emplace(name
, std::move(bl
));
404 r
= _setattrs(cid
, oid
, std::move(to_set
));
407 case Transaction::OP_SETATTRS
:
409 coll_t cid
= i
.get_cid(op
->cid
);
410 ghobject_t oid
= i
.get_oid(op
->oid
);
411 std::map
<std::string
, bufferlist
> aset
;
412 i
.decode_attrset(aset
);
413 r
= _setattrs(cid
, oid
, std::move(aset
));
416 case Transaction::OP_RMATTR
:
418 coll_t cid
= i
.get_cid(op
->cid
);
419 ghobject_t oid
= i
.get_oid(op
->oid
);
420 std::string name
= i
.decode_string();
421 r
= _rm_attr(cid
, oid
, name
);
424 case Transaction::OP_RMATTRS
:
426 coll_t cid
= i
.get_cid(op
->cid
);
427 ghobject_t oid
= i
.get_oid(op
->oid
);
428 r
= _rm_attrs(cid
, oid
);
431 case Transaction::OP_MKCOLL
:
433 coll_t cid
= i
.get_cid(op
->cid
);
434 r
= _create_collection(cid
, op
->split_bits
);
437 case Transaction::OP_SETALLOCHINT
:
442 case Transaction::OP_OMAP_CLEAR
:
444 coll_t cid
= i
.get_cid(op
->cid
);
445 ghobject_t oid
= i
.get_oid(op
->oid
);
446 r
= _omap_clear(cid
, oid
);
449 case Transaction::OP_OMAP_SETKEYS
:
451 coll_t cid
= i
.get_cid(op
->cid
);
452 ghobject_t oid
= i
.get_oid(op
->oid
);
453 std::map
<std::string
, ceph::bufferlist
> aset
;
454 i
.decode_attrset(aset
);
455 r
= _omap_set_values(cid
, oid
, std::move(aset
));
458 case Transaction::OP_OMAP_SETHEADER
:
460 const coll_t
&cid
= i
.get_cid(op
->cid
);
461 const ghobject_t
&oid
= i
.get_oid(op
->oid
);
464 r
= _omap_set_header(cid
, oid
, bl
);
467 case Transaction::OP_OMAP_RMKEYS
:
469 const coll_t
&cid
= i
.get_cid(op
->cid
);
470 const ghobject_t
&oid
= i
.get_oid(op
->oid
);
472 i
.decode_keyset(keys
);
473 r
= _omap_rmkeys(cid
, oid
, keys
);
476 case Transaction::OP_OMAP_RMKEYRANGE
:
478 const coll_t
&cid
= i
.get_cid(op
->cid
);
479 const ghobject_t
&oid
= i
.get_oid(op
->oid
);
481 first
= i
.decode_string();
482 last
= i
.decode_string();
483 r
= _omap_rmkeyrange(cid
, oid
, first
, last
);
486 case Transaction::OP_COLL_HINT
:
488 ceph::bufferlist hint
;
494 logger().error("bad op {}", static_cast<unsigned>(op
->op
));
501 } catch (std::exception
&e
) {
502 logger().error("{} got exception {}", __func__
, e
);
506 logger().error(" transaction dump:\n");
507 JSONFormatter
f(true);
508 f
.open_object_section("transaction");
511 std::stringstream str
;
513 logger().error("{}", str
.str());
519 t
.get_on_applied_sync()}) {
524 return seastar::now();
527 int CyanStore::_remove(const coll_t
& cid
, const ghobject_t
& oid
)
529 logger().debug("{} cid={} oid={}",
531 auto c
= _get_collection(cid
);
535 auto i
= c
->object_hash
.find(oid
);
536 if (i
== c
->object_hash
.end())
538 used_bytes
-= i
->second
->get_size();
539 c
->object_hash
.erase(i
);
540 c
->object_map
.erase(oid
);
544 int CyanStore::_touch(const coll_t
& cid
, const ghobject_t
& oid
)
546 logger().debug("{} cid={} oid={}",
548 auto c
= _get_collection(cid
);
552 c
->get_or_create_object(oid
);
556 int CyanStore::_write(const coll_t
& cid
, const ghobject_t
& oid
,
557 uint64_t offset
, size_t len
, const ceph::bufferlist
& bl
,
558 uint32_t fadvise_flags
)
560 logger().debug("{} {} {} {} ~ {}",
561 __func__
, cid
, oid
, offset
, len
);
562 assert(len
== bl
.length());
564 auto c
= _get_collection(cid
);
568 ObjectRef o
= c
->get_or_create_object(oid
);
569 if (len
> 0 && !local_conf()->memstore_debug_omit_block_device_write
) {
570 const ssize_t old_size
= o
->get_size();
571 o
->write(offset
, bl
);
572 used_bytes
+= (o
->get_size() - old_size
);
578 int CyanStore::_zero(const coll_t
& cid
, const ghobject_t
& oid
,
579 uint64_t offset
, size_t len
)
581 logger().debug("{} {} {} {} ~ {}",
582 __func__
, cid
, oid
, offset
, len
);
584 ceph::buffer::list bl
;
586 return _write(cid
, oid
, offset
, len
, bl
, 0);
589 int CyanStore::_omap_clear(
591 const ghobject_t
& oid
)
593 logger().debug("{} {} {}", __func__
, cid
, oid
);
595 auto c
= _get_collection(cid
);
599 ObjectRef o
= c
->get_object(oid
);
604 o
->omap_header
.clear();
608 int CyanStore::_omap_set_values(
610 const ghobject_t
& oid
,
611 std::map
<std::string
, ceph::bufferlist
> &&aset
)
615 __func__
, cid
, oid
, aset
.size());
617 auto c
= _get_collection(cid
);
621 ObjectRef o
= c
->get_or_create_object(oid
);
622 for (auto&& [key
, val
]: aset
) {
623 o
->omap
.insert_or_assign(std::move(key
), std::move(val
));
628 int CyanStore::_omap_set_header(
630 const ghobject_t
& oid
,
631 const ceph::bufferlist
&header
)
635 __func__
, cid
, oid
, header
.length());
637 auto c
= _get_collection(cid
);
641 ObjectRef o
= c
->get_or_create_object(oid
);
642 o
->omap_header
= header
;
646 int CyanStore::_omap_rmkeys(
648 const ghobject_t
& oid
,
649 const omap_keys_t
& aset
)
653 __func__
, cid
, oid
, aset
.size());
655 auto c
= _get_collection(cid
);
659 ObjectRef o
= c
->get_or_create_object(oid
);
660 for (auto &i
: aset
) {
666 int CyanStore::_omap_rmkeyrange(
668 const ghobject_t
& oid
,
669 const std::string
&first
,
670 const std::string
&last
)
673 "{} {} {} first={} last={}",
674 __func__
, cid
, oid
, first
, last
);
676 auto c
= _get_collection(cid
);
680 ObjectRef o
= c
->get_or_create_object(oid
);
681 for (auto i
= o
->omap
.lower_bound(first
);
682 i
!= o
->omap
.end() && i
->first
<= last
;
687 int CyanStore::_truncate(const coll_t
& cid
, const ghobject_t
& oid
, uint64_t size
)
689 logger().debug("{} cid={} oid={} size={}",
690 __func__
, cid
, oid
, size
);
691 auto c
= _get_collection(cid
);
695 ObjectRef o
= c
->get_object(oid
);
698 if (local_conf()->memstore_debug_omit_block_device_write
)
700 const ssize_t old_size
= o
->get_size();
701 int r
= o
->truncate(size
);
702 used_bytes
+= (o
->get_size() - old_size
);
706 int CyanStore::_setattrs(const coll_t
& cid
, const ghobject_t
& oid
,
707 std::map
<std::string
,bufferlist
>&& aset
)
709 logger().debug("{} cid={} oid={}",
711 auto c
= _get_collection(cid
);
715 ObjectRef o
= c
->get_object(oid
);
718 for (auto&& [key
, val
]: aset
) {
719 o
->xattr
.insert_or_assign(std::move(key
), std::move(val
));
724 int CyanStore::_rm_attr(const coll_t
& cid
, const ghobject_t
& oid
,
725 std::string_view name
)
727 logger().debug("{} cid={} oid={} name={}", __func__
, cid
, oid
, name
);
728 auto c
= _get_collection(cid
);
732 ObjectRef o
= c
->get_object(oid
);
736 auto i
= o
->xattr
.find(name
);
737 if (i
== o
->xattr
.end()) {
744 int CyanStore::_rm_attrs(const coll_t
& cid
, const ghobject_t
& oid
)
746 logger().debug("{} cid={} oid={}", __func__
, cid
, oid
);
747 auto c
= _get_collection(cid
);
751 ObjectRef o
= c
->get_object(oid
);
759 int CyanStore::_create_collection(const coll_t
& cid
, int bits
)
761 auto result
= coll_map
.try_emplace(cid
);
764 auto p
= new_coll_map
.find(cid
);
765 assert(p
!= new_coll_map
.end());
766 result
.first
->second
= p
->second
;
767 result
.first
->second
->bits
= bits
;
768 new_coll_map
.erase(p
);
772 boost::intrusive_ptr
<Collection
> CyanStore::_get_collection(const coll_t
& cid
)
774 auto cp
= coll_map
.find(cid
);
775 if (cp
== coll_map
.end())
780 seastar::future
<> CyanStore::write_meta(const std::string
& key
,
781 const std::string
& value
)
783 std::string v
= value
;
785 if (int r
= safe_write_file(path
.c_str(), key
.c_str(),
786 v
.c_str(), v
.length(), 0600);
788 throw std::runtime_error
{fmt::format("unable to write_meta({})", key
)};
790 return seastar::make_ready_future
<>();
793 seastar::future
<std::tuple
<int, std::string
>>
794 CyanStore::read_meta(const std::string
& key
)
796 std::string
fsid(4096, '\0');
797 int r
= safe_read_file(path
.c_str(), key
.c_str(), fsid
.data(), fsid
.size());
800 // drop trailing newlines
801 boost::algorithm::trim_right_if(fsid
,
802 [](unsigned char c
) {return isspace(c
);});
806 return seastar::make_ready_future
<std::tuple
<int, std::string
>>(
807 std::make_tuple(r
, fsid
));
810 uuid_d
CyanStore::get_fsid() const
815 unsigned CyanStore::get_max_attr_name_length() const
817 // arbitrary limitation exactly like in the case of MemStore.
821 seastar::future
<FuturizedStore::OmapIteratorRef
> CyanStore::get_omap_iterator(
823 const ghobject_t
& oid
)
825 auto c
= static_cast<Collection
*>(ch
.get());
826 auto o
= c
->get_object(oid
);
828 throw std::runtime_error(fmt::format("object does not exist: {}", oid
));
830 return seastar::make_ready_future
<FuturizedStore::OmapIteratorRef
>(
831 new CyanStore::CyanOmapIterator(o
));
834 seastar::future
<std::map
<uint64_t, uint64_t>>
837 const ghobject_t
& oid
,
841 auto c
= static_cast<Collection
*>(ch
.get());
843 ObjectRef o
= c
->get_object(oid
);
845 throw std::runtime_error(fmt::format("object does not exist: {}", oid
));
847 std::map
<uint64_t, uint64_t> m
{{0, o
->get_size()}};
848 return seastar::make_ready_future
<std::map
<uint64_t, uint64_t>>(std::move(m
));
851 seastar::future
<struct stat
>
854 const ghobject_t
& oid
)
856 auto c
= static_cast<Collection
*>(ch
.get());
857 auto o
= c
->get_object(oid
);
859 throw std::runtime_error(fmt::format("object does not exist: {}", oid
));
862 st
.st_size
= o
->get_size();
863 return seastar::make_ready_future
<struct stat
>(std::move(st
));
866 seastar::future
<> CyanStore::CyanOmapIterator::seek_to_first()
868 iter
= obj
->omap
.begin();
869 return seastar::make_ready_future
<>();
872 seastar::future
<> CyanStore::CyanOmapIterator::upper_bound(const std::string
& after
)
874 iter
= obj
->omap
.upper_bound(after
);
875 return seastar::make_ready_future
<>();
878 seastar::future
<> CyanStore::CyanOmapIterator::lower_bound(const std::string
&to
)
880 iter
= obj
->omap
.lower_bound(to
);
881 return seastar::make_ready_future
<>();
884 bool CyanStore::CyanOmapIterator::valid() const
886 return iter
!= obj
->omap
.end();
889 seastar::future
<> CyanStore::CyanOmapIterator::next()
892 return seastar::make_ready_future
<>();