Skip to content

Commit 4a8aecc

Browse files
zhscnMatan-B
authored andcommitted
crimson/os/seastore/btree: introduce BtreeCursor
Signed-off-by: Zhang Song <[email protected]> (cherry picked from commit 972c139)
1 parent 4c419f4 commit 4a8aecc

File tree

4 files changed

+182
-4
lines changed

4 files changed

+182
-4
lines changed

src/crimson/os/seastore/btree/btree_types.cc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// vim: ts=8 sw=2 smarttab
33

44
#include "crimson/os/seastore/btree/btree_types.h"
5+
#include "crimson/os/seastore/lba_manager/btree/lba_btree_node.h"
6+
#include "crimson/os/seastore/backref/backref_tree_node.h"
57

68
namespace crimson::os::seastore {
79

@@ -29,4 +31,40 @@ std::ostream& operator<<(std::ostream &out, const backref_map_val_t& val) {
2931
}
3032

3133
} // namespace backref
34+
35+
namespace {
36+
template <typename key_t, typename T>
37+
bool modified_since(T &&extent, uint64_t iter_modifications) {
38+
using backref::BackrefLeafNode;
39+
using lba_manager::btree::LBALeafNode;
40+
if constexpr (std::is_same_v<key_t, laddr_t>) {
41+
assert(extent->get_type() == extent_types_t::LADDR_LEAF);
42+
auto leaf = extent->template cast<LBALeafNode>();
43+
return leaf->modified_since(iter_modifications);
44+
} else {
45+
assert(extent->get_type() == extent_types_t::BACKREF_LEAF);
46+
auto leaf = extent->template cast<BackrefLeafNode>();
47+
return leaf->modified_since(iter_modifications);
48+
}
49+
}
50+
}
51+
52+
template <typename key_t, typename val_t>
53+
bool BtreeCursor<key_t, val_t>::is_viewable() const {
54+
LOG_PREFIX(BtreeCursor::is_viewable());
55+
if (!parent->is_valid() ||
56+
modified_since<key_t>(parent, modifications)) {
57+
return false;
58+
}
59+
60+
auto [viewable, state] = parent->is_viewable_by_trans(ctx.trans);
61+
assert(state != CachedExtent::viewable_state_t::invalid);
62+
SUBTRACET(seastore_cache, "{} with viewable state {}",
63+
ctx.trans, *parent, state);
64+
return viewable;
65+
}
66+
67+
template struct BtreeCursor<laddr_t, lba_manager::btree::lba_map_val_t>;
68+
template struct BtreeCursor<paddr_t, backref::backref_map_val_t>;
69+
3270
} // namespace crimson::os::seastore

src/crimson/os/seastore/btree/btree_types.h

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,142 @@ struct __attribute__((packed)) backref_map_val_le_t {
192192

193193
} // namespace backerf
194194

195+
/**
196+
* BtreeCursor
197+
*
198+
* BtreeCursor is the type-erased wrapper for FixedKVBtree::iterator, stores
199+
* a key-value mapping's location and the snapshot of its data at construction
200+
* time.
201+
*/
202+
template <typename key_t, typename val_t>
203+
struct BtreeCursor {
204+
BtreeCursor(
205+
op_context_t &ctx,
206+
CachedExtentRef parent,
207+
uint64_t modifications,
208+
key_t key,
209+
std::optional<val_t> val,
210+
btreenode_pos_t pos)
211+
: ctx(ctx),
212+
parent(std::move(parent)),
213+
modifications(modifications),
214+
key(key),
215+
val(std::move(val)),
216+
pos(pos)
217+
{
218+
if constexpr (std::is_same_v<key_t, laddr_t>) {
219+
static_assert(std::is_same_v<val_t, lba_manager::btree::lba_map_val_t>,
220+
"the value type of laddr_t for BtreeCursor should be lba_map_val_t");
221+
} else {
222+
static_assert(std::is_same_v<key_t, paddr_t>,
223+
"the key type of BtreeCursor should be either laddr_t or paddr_t");
224+
static_assert(std::is_same_v<val_t, backref::backref_map_val_t>,
225+
"the value type should be either lba_map_val_t or backref_map_val_t");
226+
}
227+
}
228+
229+
op_context_t ctx;
230+
CachedExtentRef parent;
231+
uint64_t modifications;
232+
key_t key;
233+
std::optional<val_t> val;
234+
btreenode_pos_t pos;
235+
236+
// NOTE: The overhead of calling is_viewable() might be not negligible in the
237+
// case of the parent extent is stable and shared by multiple transactions.
238+
// The best practice is to only hold cursors whose parent is pending in
239+
// current transaction in the long term.
240+
bool is_viewable() const;
241+
242+
bool is_end() const {
243+
auto max_key = min_max_t<key_t>::max;
244+
assert((key != max_key) == (bool)val);
245+
return key == max_key;
246+
}
247+
248+
extent_len_t get_length() const {
249+
assert(!is_end());
250+
return val->len;
251+
}
252+
};
253+
254+
struct LBACursor : BtreeCursor<laddr_t, lba_manager::btree::lba_map_val_t> {
255+
using Base = BtreeCursor<laddr_t, lba_manager::btree::lba_map_val_t>;
256+
using Base::BtreeCursor;
257+
bool is_indirect() const {
258+
assert(!is_end());
259+
return val->pladdr.is_laddr();
260+
}
261+
laddr_t get_laddr() const {
262+
return key;
263+
}
264+
paddr_t get_paddr() const {
265+
assert(!is_indirect());
266+
assert(!is_end());
267+
return val->pladdr.get_paddr();
268+
}
269+
laddr_t get_intermediate_key() const {
270+
assert(is_indirect());
271+
assert(!is_end());
272+
return val->pladdr.get_laddr();
273+
}
274+
checksum_t get_checksum() const {
275+
assert(!is_end());
276+
assert(!is_indirect());
277+
return val->checksum;
278+
}
279+
extent_ref_count_t get_refcount() const {
280+
assert(!is_end());
281+
assert(!is_indirect());
282+
return val->refcount;
283+
}
284+
std::unique_ptr<LBACursor> duplicate() const {
285+
return std::make_unique<LBACursor>(*this);
286+
}
287+
};
288+
using LBACursorRef = std::unique_ptr<LBACursor>;
289+
290+
struct BackrefCursor : BtreeCursor<paddr_t, backref::backref_map_val_t> {
291+
using Base = BtreeCursor<paddr_t, backref::backref_map_val_t>;
292+
using Base::BtreeCursor;
293+
paddr_t get_paddr() const {
294+
return key;
295+
}
296+
laddr_t get_laddr() const {
297+
assert(!is_end());
298+
return val->laddr;
299+
}
300+
extent_types_t get_type() const {
301+
assert(!is_end());
302+
return val->type;
303+
}
304+
};
305+
using BackrefCursorRef = std::unique_ptr<BackrefCursor>;
306+
307+
template <typename key_t, typename val_t>
308+
std::ostream &operator<<(
309+
std::ostream &out, const BtreeCursor<key_t, val_t> &cursor)
310+
{
311+
if constexpr (std::is_same_v<key_t, laddr_t>) {
312+
out << "LBACursor(";
313+
} else {
314+
out << "BackrefCursor(";
315+
}
316+
out << (void*)cursor.parent.get()
317+
<< "@" << cursor.pos
318+
<< "#" << cursor.modifications
319+
<< ",";
320+
if (cursor.is_end()) {
321+
return out << "END)";
322+
}
323+
return out << "," << cursor.key
324+
<< "~" << *cursor.val
325+
<< ")";
326+
}
327+
195328
} // namespace crimson::os::seastore
329+
330+
#if FMT_VERSION >= 90000
331+
template <> struct fmt::formatter<crimson::os::seastore::LBACursor> : fmt::ostream_formatter {};
332+
template <> struct fmt::formatter<crimson::os::seastore::BackrefCursor> : fmt::ostream_formatter {};
333+
#endif

src/crimson/os/seastore/linked_tree_node.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99

1010
namespace crimson::os::seastore {
1111

12-
// XXX: It happens to be true that the width of node
13-
// index in lba and omap tree are the same.
14-
using btreenode_pos_t = uint16_t;
15-
1612
template <typename ParentT>
1713
class child_pos_t {
1814
public:

src/crimson/os/seastore/seastore_types.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ using checksum_t = uint32_t;
7777
using checksum_le_t = ceph_le32;
7878
constexpr checksum_t CRC_NULL = 0;
7979

80+
// XXX: It happens to be true that the width of node
81+
// index in lba and omap tree are the same.
82+
using btreenode_pos_t = uint16_t;
83+
constexpr auto BTREENODE_POS_MAX = std::numeric_limits<btreenode_pos_t>::max();
84+
constexpr auto BTREENODE_POS_NULL = BTREENODE_POS_MAX;
85+
8086
// Immutable metadata for seastore to set at mkfs time
8187
struct seastore_meta_t {
8288
uuid_d seastore_id;

0 commit comments

Comments
 (0)