Skip to content

Commit 853c609

Browse files
authored
Merge pull request ceph#62530 from liu-chunmei/omap_iterate
crimson: implement crimson Omap iterate interface Reviewed-by: Yingxin Cheng <[email protected]>
2 parents 5debe65 + aa2f606 commit 853c609

File tree

20 files changed

+830
-415
lines changed

20 files changed

+830
-415
lines changed

src/crimson/os/alienstore/alien_store.cc

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -424,42 +424,30 @@ auto AlienStore::omap_get_values(CollectionRef ch,
424424
});
425425
}
426426

427-
auto AlienStore::omap_get_values(CollectionRef ch,
428-
const ghobject_t &oid,
429-
const std::optional<string> &start,
430-
uint32_t op_flags)
431-
-> read_errorator::future<std::tuple<bool, omap_values_t>>
427+
AlienStore::read_errorator::future<ObjectStore::omap_iter_ret_t>
428+
AlienStore::omap_iterate(CollectionRef ch,
429+
const ghobject_t &oid,
430+
ObjectStore::omap_iter_seek_t start_from,
431+
omap_iterate_cb_t callback,
432+
uint32_t op_flags)
432433
{
433434
logger().debug("{} with_start", __func__);
434435
assert(tp);
435-
return do_with_op_gate(omap_values_t{}, [=, this] (auto &values) {
436-
return tp->submit(ch->get_cid().hash_to_shard(tp->size()), [=, this, &values] {
436+
return do_with_op_gate(oid, [ch, start_from, callback, this] (auto& oid) {
437+
return tp->submit(ch->get_cid().hash_to_shard(tp->size()), [ch, oid, start_from, callback, this] {
437438
auto c = static_cast<AlienCollection*>(ch.get());
438439
return store->omap_iterate(
439-
c->collection, oid,
440-
ObjectStore::omap_iter_seek_t{
441-
.seek_position = start.value_or(std::string{}),
442-
// FIXME: classical OSDs begins iteration from LOWER_BOUND
443-
// (or UPPER_BOUND if filter_prefix > start). However, these
444-
// bits are not implemented yet
445-
.seek_type = ObjectStore::omap_iter_seek_t::UPPER_BOUND
446-
},
447-
[&values]
448-
(std::string_view key, std::string_view value) mutable {
449-
values[std::string{key}].append(value);
450-
// FIXME: there is limit on number of entries yet
451-
return ObjectStore::omap_iter_ret_t::NEXT;
452-
});
453-
}).then([&values] (int r)
454-
-> read_errorator::future<std::tuple<bool, omap_values_t>> {
440+
c->collection, oid, start_from, callback);
441+
}).then([] (int r)
442+
-> read_errorator::future<ObjectStore::omap_iter_ret_t> {
455443
if (r == -ENOENT) {
456444
return crimson::ct_error::enoent::make();
457-
} else if (r < 0){
458-
logger().error("omap_get_values(start): {}", r);
459-
return crimson::ct_error::input_output_error::make();
460445
} else {
461-
return read_errorator::make_ready_future<std::tuple<bool, omap_values_t>>(
462-
true, std::move(values));
446+
if (r == 1) {
447+
return read_errorator::make_ready_future<ObjectStore::omap_iter_ret_t>(ObjectStore::omap_iter_ret_t::STOP);
448+
} else {
449+
return read_errorator::make_ready_future<ObjectStore::omap_iter_ret_t>(ObjectStore::omap_iter_ret_t::NEXT);
450+
}
463451
}
464452
});
465453
});

src/crimson/os/alienstore/alien_store.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,20 @@ class AlienStore final : public FuturizedStore,
6666
const omap_keys_t& keys,
6767
uint32_t op_flags = 0) final;
6868

69-
/// Retrieves paged set of values > start (if present)
70-
read_errorator::future<std::tuple<bool, omap_values_t>> omap_get_values(
71-
CollectionRef c, ///< [in] collection
72-
const ghobject_t &oid, ///< [in] oid
73-
const std::optional<std::string> &start, ///< [in] start, empty for begin
74-
uint32_t op_flags = 0
75-
) final; ///< @return <done, values> values.empty() iff done
76-
7769
seastar::future<std::tuple<std::vector<ghobject_t>, ghobject_t>> list_objects(
7870
CollectionRef c,
7971
const ghobject_t& start,
8072
const ghobject_t& end,
8173
uint64_t limit,
8274
uint32_t op_flags = 0) const final;
8375

76+
read_errorator::future<ObjectStore::omap_iter_ret_t> omap_iterate(
77+
CollectionRef c,
78+
const ghobject_t &oid,
79+
ObjectStore::omap_iter_seek_t start_from,
80+
omap_iterate_cb_t callback,
81+
uint32_t op_flags = 0) final;
82+
8483
seastar::future<CollectionRef> create_new_collection(const coll_t& cid) final;
8584
seastar::future<CollectionRef> open_collection(const coll_t& cid) final;
8685
seastar::future<std::vector<coll_core_t>> list_collections() final;

src/crimson/os/cyanstore/cyan_store.cc

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -390,29 +390,33 @@ auto CyanStore::Shard::omap_get_values(
390390
return seastar::make_ready_future<omap_values_t>(std::move(values));
391391
}
392392

393-
auto CyanStore::Shard::omap_get_values(
393+
auto CyanStore::Shard::omap_iterate(
394394
CollectionRef ch,
395395
const ghobject_t &oid,
396-
const std::optional<string> &start,
396+
ObjectStore::omap_iter_seek_t start_from,
397+
omap_iterate_cb_t callback,
397398
uint32_t op_flags)
398-
-> CyanStore::Shard::read_errorator::future<std::tuple<bool, omap_values_t>>
399+
-> CyanStore::Shard::read_errorator::future<ObjectStore::omap_iter_ret_t>
399400
{
400401
auto c = static_cast<Collection*>(ch.get());
401402
logger().debug("{} {} {}", __func__, c->get_cid(), oid);
402403
auto o = c->get_object(oid);
403404
if (!o) {
404405
return crimson::ct_error::enoent::make();
405406
}
406-
omap_values_t values;
407-
for (auto i = start ? o->omap.upper_bound(*start) : o->omap.begin();
408-
i != o->omap.end();
409-
++i) {
410-
values.insert(*i);
407+
auto ret = ObjectStore::omap_iter_ret_t::NEXT;
408+
auto i = (start_from.seek_type == ObjectStore::omap_iter_seek_t::LOWER_BOUND) ?
409+
o->omap.lower_bound(start_from.seek_position) :
410+
o->omap.upper_bound(start_from.seek_position);
411+
for (; i != o->omap.end(); ++i) {
412+
ceph::bufferlist bl = i->second;
413+
std::string result(bl.c_str(), bl.length());
414+
ret = callback(i->first, result);
415+
if (ret == ObjectStore::omap_iter_ret_t::STOP)
416+
break;
411417
}
412-
return seastar::make_ready_future<std::tuple<bool, omap_values_t>>(
413-
std::make_tuple(true, std::move(values)));
418+
return read_errorator::make_ready_future<ObjectStore::omap_iter_ret_t>(ret);
414419
}
415-
416420
auto CyanStore::Shard::omap_get_header(
417421
CollectionRef ch,
418422
const ghobject_t& oid,

src/crimson/os/cyanstore/cyan_store.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ class CyanStore final : public FuturizedStore {
7272
const omap_keys_t& keys,
7373
uint32_t op_flags = 0) final;
7474

75-
read_errorator::future<std::tuple<bool, omap_values_t>> omap_get_values(
76-
CollectionRef c, ///< [in] collection
77-
const ghobject_t &oid, ///< [in] oid
78-
const std::optional<std::string> &start, ///< [in] start, empty for begin
75+
read_errorator::future<ObjectStore::omap_iter_ret_t> omap_iterate(
76+
CollectionRef c,
77+
const ghobject_t &oid,
78+
ObjectStore::omap_iter_seek_t start_from,
79+
omap_iterate_cb_t callback,
7980
uint32_t op_flags = 0
80-
) final;
81+
) final;
8182

8283
get_attr_errorator::future<ceph::bufferlist> omap_get_header(
8384
CollectionRef c,

src/crimson/os/futurized_store.h

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "include/buffer_fwd.h"
1818
#include "include/uuid.h"
1919
#include "osd/osd_types.h"
20+
#include "os/ObjectStore.h"
2021

2122
namespace ceph::os {
2223
class Transaction;
@@ -87,13 +88,36 @@ class FuturizedStore {
8788
const omap_keys_t& keys,
8889
uint32_t op_flags = 0) = 0;
8990

90-
using omap_values_paged_t = std::tuple<bool, omap_values_t>;
91-
virtual read_errorator::future<omap_values_paged_t> omap_get_values(
92-
CollectionRef c, ///< [in] collection
93-
const ghobject_t &oid, ///< [in] oid
94-
const std::optional<std::string> &start, ///< [in] start, empty for begin
91+
/**
92+
* Iterate over object map with user-provided callable
93+
*
94+
* Warning! f cannot block or perform IO and must not wait on a future.
95+
*
96+
* @param c collection
97+
* @param oid object
98+
* @param start_from where the iterator should point to at
99+
* the beginning
100+
* @param f callable that takes OMAP key and corresponding
101+
* value as string_views and controls iteration
102+
* by the return. It is executed for every object's
103+
* OMAP entry from `start_from` till end of the
104+
* object's OMAP or till the iteration is stopped
105+
* by `STOP`. Please note that if there is no such
106+
* entry, `visitor` will be called 0 times.
107+
* @return omap_iter_ret_t on success
108+
* omap_iter_ret_t::STOP means omap_iterate() is stopped by f,
109+
* omap_iter_ret_t::NEXT means omap_iterate() reaches the end of omap tree
110+
*/
111+
using omap_iterate_cb_t = std::function<ObjectStore::omap_iter_ret_t(std::string_view, std::string_view)>;
112+
virtual read_errorator::future<ObjectStore::omap_iter_ret_t> omap_iterate(
113+
CollectionRef c, ///< [in] collection
114+
const ghobject_t &oid, ///< [in] object
115+
ObjectStore::omap_iter_seek_t start_from, ///< [in] where the iterator should point to at the beginning
116+
omap_iterate_cb_t callback,
117+
///< [in] the callback function for each OMAP entry after start_from till end of the OMAP or
118+
/// till the iteration is stopped by `STOP`.
95119
uint32_t op_flags = 0
96-
) = 0; ///< @return <done, values> values.empty() only if done
120+
) = 0;
97121

98122
virtual get_attr_errorator::future<bufferlist> omap_get_header(
99123
CollectionRef c,

src/crimson/os/seastore/omap_manager.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include <iostream>
7+
#include <fmt/format.h>
78

89
#include <boost/intrusive_ptr.hpp>
910
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
@@ -13,13 +14,31 @@
1314
#include "crimson/osd/exceptions.h"
1415
#include "crimson/os/seastore/seastore_types.h"
1516
#include "crimson/os/seastore/transaction_manager.h"
17+
#include "os/ObjectStore.h" // for ObjectStore::omap_iter_seek_t
18+
1619

1720
//TODO: calculate the max key and value sizes the current layout supports,
1821
// and return errors during insert if the max is exceeded.
1922
#define OMAP_INNER_BLOCK_SIZE 8192
2023
#define OMAP_LEAF_BLOCK_SIZE 65536
2124
#define LOG_LEAF_BLOCK_SIZE 16384
2225

26+
template <>
27+
struct fmt::formatter<ObjectStore::omap_iter_seek_t> {
28+
constexpr auto parse(format_parse_context& ctx) const {
29+
return ctx.begin();
30+
}
31+
32+
auto format(const ObjectStore::omap_iter_seek_t& seek, format_context& ctx) const {
33+
return fmt::format_to(
34+
ctx.out(),
35+
"omap_iter_seek_t{{seek_position='{}', seek_type={}}}",
36+
seek.seek_position,
37+
seek.seek_type == ObjectStore::omap_iter_seek_t::LOWER_BOUND ? "LOWER_BOUND" : "UPPER_BOUND"
38+
);
39+
}
40+
};
41+
2342
namespace crimson::os::seastore {
2443

2544
std::ostream &operator<<(std::ostream &out, const std::list<std::string> &rhs);
@@ -98,10 +117,35 @@ class OMapManager {
98117
Transaction &t,
99118
const std::string &key) = 0;
100119

120+
/**
121+
* omap_iterate
122+
*
123+
* scan key/value pairs and give key/value from start_from.seek_poistion to function f
124+
*
125+
* @param omap_root: omap btree root information
126+
* @param t: current transaction
127+
* @param start_from: seek start key and seek type
128+
* Upon transaction conflict, start_from will be updated to the
129+
* upper bound of the last key of the last visited omap leaf node.
130+
* @param f: function is called for each seeked key/value pair
131+
*
132+
*/
133+
using omap_iterate_cb_t = std::function<ObjectStore::omap_iter_ret_t(std::string_view, std::string_view)>;
134+
using omap_iterate_iertr = base_iertr;
135+
using omap_iterate_ret = omap_iterate_iertr::future<ObjectStore::omap_iter_ret_t>;
136+
virtual omap_iterate_ret omap_iterate(
137+
const omap_root_t &omap_root,
138+
Transaction &t,
139+
ObjectStore::omap_iter_seek_t &start_from,
140+
omap_iterate_cb_t callback
141+
) = 0;
142+
101143
/**
102144
* omap_list
103145
*
104146
* Scans key/value pairs in order.
147+
* // TODO: omap_list() is deprecated in favor of omap_iterate()
148+
* // TODO: omap_rm_key_range() that omap_list_config_t needs to be dropped from that interface
105149
*
106150
* @param omap_root: omap btree root information
107151
* @param t: current transaction

src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,26 @@ BtreeOMapManager::omap_rm_key_range(
268268
});
269269
}
270270

271+
BtreeOMapManager::omap_iterate_ret
272+
BtreeOMapManager::omap_iterate(
273+
const omap_root_t &omap_root,
274+
Transaction &t,
275+
ObjectStore::omap_iter_seek_t &start_from,
276+
omap_iterate_cb_t callback)
277+
{
278+
LOG_PREFIX(BtreeOMapManager::omap_iterate);
279+
DEBUGT("{}, {}", t, omap_root, start_from);
280+
return get_omap_root(
281+
get_omap_context(t, omap_root),
282+
omap_root
283+
).si_then([this, &t, &start_from, callback, &omap_root](auto extent) {
284+
return extent->iterate(
285+
get_omap_context(t, omap_root),
286+
start_from,
287+
callback);
288+
});
289+
}
290+
271291
BtreeOMapManager::omap_list_ret
272292
BtreeOMapManager::omap_list(
273293
const omap_root_t &omap_root,

src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ class BtreeOMapManager : public OMapManager {
9696
const std::string &last,
9797
omap_list_config_t config) final;
9898

99+
omap_iterate_ret omap_iterate(
100+
const omap_root_t &omap_root,
101+
Transaction &t,
102+
ObjectStore::omap_iter_seek_t &start_from,
103+
omap_iterate_cb_t callback) final;
104+
99105
omap_list_ret omap_list(
100106
const omap_root_t &omap_root,
101107
Transaction &t,

src/crimson/os/seastore/omap_manager/btree/omap_btree_node.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ struct OMapNode : LogicalChildNode {
8080
omap_context_t oc,
8181
const std::string &key) = 0;
8282

83+
using iterate_iertr = base_iertr;
84+
using iterate_ret = OMapManager::omap_iterate_ret;
85+
using omap_iterate_cb_t = OMapManager::omap_iterate_cb_t;
86+
virtual iterate_ret iterate(
87+
omap_context_t oc,
88+
ObjectStore::omap_iter_seek_t &start_from,
89+
omap_iterate_cb_t callback) = 0;
90+
8391
using omap_list_config_t = OMapManager::omap_list_config_t;
8492
using list_iertr = base_iertr;
8593
using list_bare_ret = OMapManager::omap_list_bare_ret;

0 commit comments

Comments
 (0)