]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
6 | #include "node_extent_mutable.h" | |
7 | #include "stages/node_stage.h" | |
8 | #include "stages/stage.h" | |
9 | ||
10 | #define STAGE_T node_to_stage_t<node_stage_t> | |
11 | ||
12 | namespace crimson::os::seastore::onode { | |
13 | ||
14 | /** | |
15 | * NodeLayoutReplayableT | |
16 | * | |
17 | * Contains templated logics to modify the layout of a NodeExtend which are | |
18 | * also replayable. Used by NodeExtentAccessorT at runtime and by | |
19 | * DeltaRecorderT during replay. | |
20 | */ | |
21 | template <typename FieldType, node_type_t NODE_TYPE> | |
22 | struct NodeLayoutReplayableT { | |
23 | using node_stage_t = node_extent_t<FieldType, NODE_TYPE>; | |
24 | using position_t = typename STAGE_T::position_t; | |
25 | using StagedIterator = typename STAGE_T::StagedIterator; | |
20effc67 | 26 | using value_input_t = value_input_type_t<NODE_TYPE>; |
f67539c2 TL |
27 | using value_t = value_type_t<NODE_TYPE>; |
28 | static constexpr auto FIELD_TYPE = FieldType::FIELD_TYPE; | |
29 | ||
30 | template <KeyT KT> | |
31 | static const value_t* insert( | |
32 | NodeExtentMutable& mut, | |
33 | const node_stage_t& node_stage, | |
34 | const full_key_t<KT>& key, | |
20effc67 | 35 | const value_input_t& value, |
f67539c2 TL |
36 | position_t& insert_pos, |
37 | match_stage_t& insert_stage, | |
38 | node_offset_t& insert_size) { | |
39 | auto p_value = STAGE_T::template proceed_insert<KT, false>( | |
40 | mut, node_stage, key, value, insert_pos, insert_stage, insert_size); | |
41 | return p_value; | |
42 | } | |
43 | ||
44 | static void split( | |
45 | NodeExtentMutable& mut, | |
46 | const node_stage_t& node_stage, | |
47 | StagedIterator& split_at) { | |
48 | node_stage_t::update_is_level_tail(mut, node_stage, false); | |
49 | STAGE_T::trim(mut, split_at); | |
50 | } | |
51 | ||
52 | template <KeyT KT> | |
53 | static const value_t* split_insert( | |
54 | NodeExtentMutable& mut, | |
55 | const node_stage_t& node_stage, | |
56 | StagedIterator& split_at, | |
57 | const full_key_t<KT>& key, | |
20effc67 | 58 | const value_input_t& value, |
f67539c2 TL |
59 | position_t& insert_pos, |
60 | match_stage_t& insert_stage, | |
61 | node_offset_t& insert_size) { | |
62 | node_stage_t::update_is_level_tail(mut, node_stage, false); | |
63 | STAGE_T::trim(mut, split_at); | |
64 | auto p_value = STAGE_T::template proceed_insert<KT, true>( | |
65 | mut, node_stage, key, value, insert_pos, insert_stage, insert_size); | |
66 | return p_value; | |
67 | } | |
68 | ||
69 | static void update_child_addr( | |
70 | NodeExtentMutable& mut, const laddr_t new_addr, laddr_packed_t* p_addr) { | |
71 | assert(NODE_TYPE == node_type_t::INTERNAL); | |
72 | mut.copy_in_absolute(p_addr, new_addr); | |
73 | } | |
20effc67 TL |
74 | |
75 | static std::tuple<match_stage_t, position_t> erase( | |
76 | NodeExtentMutable& mut, | |
77 | const node_stage_t& node_stage, | |
78 | const position_t& _erase_pos) { | |
79 | if (_erase_pos.is_end()) { | |
80 | // must be internal node | |
81 | assert(node_stage.is_level_tail()); | |
82 | // return erase_stage, last_pos | |
83 | return update_last_to_tail(mut, node_stage); | |
84 | } | |
85 | ||
86 | assert(node_stage.keys() != 0); | |
87 | position_t erase_pos = _erase_pos; | |
88 | auto erase_stage = STAGE_T::erase(mut, node_stage, erase_pos); | |
89 | // return erase_stage, next_pos | |
90 | return {erase_stage, erase_pos}; | |
91 | } | |
92 | ||
93 | static position_t make_tail( | |
94 | NodeExtentMutable& mut, | |
95 | const node_stage_t& node_stage) { | |
96 | assert(!node_stage.is_level_tail()); | |
97 | if constexpr (NODE_TYPE == node_type_t::INTERNAL) { | |
98 | auto [r_stage, r_last_pos] = update_last_to_tail(mut, node_stage); | |
99 | std::ignore = r_stage; | |
100 | return r_last_pos; | |
101 | } else { | |
102 | node_stage_t::update_is_level_tail(mut, node_stage, true); | |
103 | // no need to calculate the last pos | |
104 | return position_t::end(); | |
105 | } | |
106 | } | |
107 | ||
108 | private: | |
109 | static std::tuple<match_stage_t, position_t> update_last_to_tail( | |
110 | NodeExtentMutable& mut, | |
111 | const node_stage_t& node_stage) { | |
112 | if constexpr (NODE_TYPE == node_type_t::INTERNAL) { | |
113 | assert(node_stage.keys() != 0); | |
114 | position_t last_pos; | |
115 | laddr_t last_value; | |
116 | { | |
117 | const laddr_packed_t* p_last_value; | |
118 | STAGE_T::template get_largest_slot<true, false, true>( | |
119 | node_stage, &last_pos, nullptr, &p_last_value); | |
120 | last_value = p_last_value->value; | |
121 | } | |
122 | ||
123 | auto erase_pos = last_pos; | |
124 | auto erase_stage = STAGE_T::erase(mut, node_stage, erase_pos); | |
125 | assert(erase_pos.is_end()); | |
126 | ||
127 | node_stage_t::update_is_level_tail(mut, node_stage, true); | |
128 | auto p_last_value = const_cast<laddr_packed_t*>( | |
129 | node_stage.get_end_p_laddr()); | |
130 | mut.copy_in_absolute(p_last_value, last_value); | |
131 | // return erase_stage, last_pos | |
132 | return {erase_stage, last_pos}; | |
133 | } else { | |
134 | ceph_abort("impossible path"); | |
135 | } | |
136 | } | |
f67539c2 TL |
137 | }; |
138 | ||
139 | } |