]>
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 | #include "sub_items_stage.h" | |
5 | ||
6 | #include "crimson/os/seastore/onode_manager/staged-fltree/node_extent_mutable.h" | |
7 | ||
8 | namespace crimson::os::seastore::onode { | |
9 | ||
10 | template <KeyT KT> | |
11 | const laddr_packed_t* internal_sub_items_t::insert_at( | |
12 | NodeExtentMutable& mut, const internal_sub_items_t& sub_items, | |
20effc67 TL |
13 | const full_key_t<KT>& key, const laddr_t& value, |
14 | index_t index, node_offset_t size, const char* p_left_bound) | |
15 | { | |
f67539c2 TL |
16 | assert(index <= sub_items.keys()); |
17 | assert(size == estimate_insert<KT>(key, value)); | |
18 | const char* p_shift_start = p_left_bound; | |
19 | const char* p_shift_end = reinterpret_cast<const char*>( | |
20 | sub_items.p_first_item + 1 - index); | |
21 | mut.shift_absolute(p_shift_start, p_shift_end - p_shift_start, -(int)size); | |
22 | ||
23 | auto p_insert = const_cast<char*>(p_shift_end) - size; | |
20effc67 TL |
24 | auto item = internal_sub_item_t{ |
25 | snap_gen_t::from_key<KT>(key), laddr_packed_t{value}}; | |
f67539c2 TL |
26 | mut.copy_in_absolute(p_insert, item); |
27 | return &reinterpret_cast<internal_sub_item_t*>(p_insert)->value; | |
28 | } | |
29 | #define IA_TEMPLATE(KT) \ | |
30 | template const laddr_packed_t* internal_sub_items_t::insert_at<KT>( \ | |
31 | NodeExtentMutable&, const internal_sub_items_t&, const full_key_t<KT>&, \ | |
20effc67 | 32 | const laddr_t&, index_t, node_offset_t, const char*) |
f67539c2 TL |
33 | IA_TEMPLATE(KeyT::VIEW); |
34 | IA_TEMPLATE(KeyT::HOBJ); | |
35 | ||
36 | node_offset_t internal_sub_items_t::trim_until( | |
20effc67 TL |
37 | NodeExtentMutable& mut, internal_sub_items_t& items, index_t index) |
38 | { | |
f67539c2 TL |
39 | assert(index != 0); |
40 | auto keys = items.keys(); | |
41 | assert(index <= keys); | |
42 | size_t ret = sizeof(internal_sub_item_t) * (keys - index); | |
20effc67 | 43 | assert(ret < mut.get_length()); |
f67539c2 TL |
44 | return ret; |
45 | } | |
46 | ||
20effc67 TL |
47 | node_offset_t internal_sub_items_t::erase_at( |
48 | NodeExtentMutable& mut, const internal_sub_items_t& sub_items, | |
49 | index_t index, const char* p_left_bound) | |
50 | { | |
51 | assert(index < sub_items.keys()); | |
52 | node_offset_t erase_size = sizeof(internal_sub_item_t); | |
53 | const char* p_shift_start = p_left_bound; | |
54 | const char* p_shift_end = reinterpret_cast<const char*>( | |
55 | sub_items.p_first_item - index); | |
56 | mut.shift_absolute(p_shift_start, p_shift_end - p_shift_start, erase_size); | |
57 | return erase_size; | |
58 | } | |
59 | ||
f67539c2 TL |
60 | template <KeyT KT> |
61 | void internal_sub_items_t::Appender<KT>::append( | |
20effc67 TL |
62 | const internal_sub_items_t& src, index_t from, index_t items) |
63 | { | |
f67539c2 TL |
64 | assert(from <= src.keys()); |
65 | if (items == 0) { | |
66 | return; | |
67 | } | |
68 | assert(from < src.keys()); | |
69 | assert(from + items <= src.keys()); | |
70 | node_offset_t size = sizeof(internal_sub_item_t) * items; | |
71 | p_append -= size; | |
72 | p_mut->copy_in_absolute(p_append, src.p_first_item + 1 - from - items, size); | |
73 | } | |
74 | ||
75 | template <KeyT KT> | |
76 | void internal_sub_items_t::Appender<KT>::append( | |
20effc67 TL |
77 | const full_key_t<KT>& key, const laddr_t& value, |
78 | const laddr_packed_t*& p_value) | |
79 | { | |
f67539c2 | 80 | p_append -= sizeof(internal_sub_item_t); |
20effc67 TL |
81 | auto item = internal_sub_item_t{ |
82 | snap_gen_t::from_key<KT>(key), laddr_packed_t{value}}; | |
f67539c2 TL |
83 | p_mut->copy_in_absolute(p_append, item); |
84 | p_value = &reinterpret_cast<internal_sub_item_t*>(p_append)->value; | |
85 | } | |
86 | ||
87 | template <KeyT KT> | |
20effc67 | 88 | const value_header_t* leaf_sub_items_t::insert_at( |
f67539c2 | 89 | NodeExtentMutable& mut, const leaf_sub_items_t& sub_items, |
20effc67 TL |
90 | const full_key_t<KT>& key, const value_config_t& value, |
91 | index_t index, node_offset_t size, const char* p_left_bound) | |
92 | { | |
f67539c2 TL |
93 | assert(index <= sub_items.keys()); |
94 | assert(size == estimate_insert<KT>(key, value)); | |
95 | // a. [... item(index)] << size | |
96 | const char* p_shift_start = p_left_bound; | |
97 | const char* p_shift_end = sub_items.get_item_end(index); | |
98 | mut.shift_absolute(p_shift_start, p_shift_end - p_shift_start, -(int)size); | |
99 | ||
100 | // b. insert item | |
101 | auto p_insert = const_cast<char*>(p_shift_end - size); | |
20effc67 TL |
102 | auto p_value = reinterpret_cast<value_header_t*>(p_insert); |
103 | p_value->initiate(mut, value); | |
104 | p_insert += value.allocation_size(); | |
f67539c2 TL |
105 | mut.copy_in_absolute(p_insert, snap_gen_t::template from_key<KT>(key)); |
106 | assert(p_insert + sizeof(snap_gen_t) + sizeof(node_offset_t) == p_shift_end); | |
107 | ||
108 | // c. compensate affected offsets | |
20effc67 | 109 | auto item_size = value.allocation_size() + sizeof(snap_gen_t); |
f67539c2 TL |
110 | for (auto i = index; i < sub_items.keys(); ++i) { |
111 | const node_offset_packed_t& offset_i = sub_items.get_offset(i); | |
112 | mut.copy_in_absolute((void*)&offset_i, node_offset_t(offset_i.value + item_size)); | |
113 | } | |
114 | ||
115 | // d. [item(index-1) ... item(0) ... offset(index)] <<< sizeof(node_offset_t) | |
116 | const char* p_offset = (index == 0 ? | |
117 | (const char*)&sub_items.get_offset(0) + sizeof(node_offset_t) : | |
118 | (const char*)&sub_items.get_offset(index - 1)); | |
119 | p_shift_start = p_shift_end; | |
120 | p_shift_end = p_offset; | |
121 | mut.shift_absolute(p_shift_start, p_shift_end - p_shift_start, -(int)sizeof(node_offset_t)); | |
122 | ||
123 | // e. insert offset | |
124 | node_offset_t offset_to_item_start = item_size + sub_items.get_offset_to_end(index); | |
125 | mut.copy_in_absolute( | |
126 | const_cast<char*>(p_shift_end) - sizeof(node_offset_t), offset_to_item_start); | |
127 | ||
128 | // f. update num_sub_keys | |
129 | mut.copy_in_absolute((void*)sub_items.p_num_keys, num_keys_t(sub_items.keys() + 1)); | |
130 | ||
131 | return p_value; | |
132 | } | |
20effc67 | 133 | template const value_header_t* leaf_sub_items_t::insert_at<KeyT::HOBJ>( |
f67539c2 | 134 | NodeExtentMutable&, const leaf_sub_items_t&, const full_key_t<KeyT::HOBJ>&, |
20effc67 | 135 | const value_config_t&, index_t, node_offset_t, const char*); |
f67539c2 TL |
136 | |
137 | node_offset_t leaf_sub_items_t::trim_until( | |
20effc67 TL |
138 | NodeExtentMutable& mut, leaf_sub_items_t& items, index_t index) |
139 | { | |
f67539c2 TL |
140 | assert(index != 0); |
141 | auto keys = items.keys(); | |
142 | assert(index <= keys); | |
143 | if (index == keys) { | |
144 | return 0; | |
145 | } | |
146 | index_t trim_items = keys - index; | |
147 | const char* p_items_start = items.p_start(); | |
148 | const char* p_shift_start = items.get_item_end(index); | |
149 | const char* p_shift_end = items.get_item_end(0); | |
150 | size_t size_trim_offsets = sizeof(node_offset_t) * trim_items; | |
151 | mut.shift_absolute(p_shift_start, p_shift_end - p_shift_start, | |
152 | size_trim_offsets); | |
153 | mut.copy_in_absolute((void*)items.p_num_keys, num_keys_t(index)); | |
154 | size_t ret = size_trim_offsets + (p_shift_start - p_items_start); | |
20effc67 | 155 | assert(ret < mut.get_length()); |
f67539c2 TL |
156 | return ret; |
157 | } | |
158 | ||
20effc67 TL |
159 | node_offset_t leaf_sub_items_t::erase_at( |
160 | NodeExtentMutable& mut, const leaf_sub_items_t& sub_items, | |
161 | index_t index, const char* p_left_bound) | |
162 | { | |
163 | assert(sub_items.keys() > 0); | |
164 | assert(index < sub_items.keys()); | |
165 | auto p_item_start = sub_items.get_item_start(index); | |
166 | auto p_item_end = sub_items.get_item_end(index); | |
167 | assert(p_item_start < p_item_end); | |
168 | node_offset_t item_erase_size = p_item_end - p_item_start; | |
169 | node_offset_t erase_size = item_erase_size + sizeof(node_offset_t); | |
170 | auto p_offset_end = (const char*)&sub_items.get_offset(index); | |
171 | ||
172 | // a. compensate affected offset[n] ... offset[index+1] | |
173 | for (auto i = index + 1; i < sub_items.keys(); ++i) { | |
174 | const node_offset_packed_t& offset_i = sub_items.get_offset(i); | |
175 | mut.copy_in_absolute((void*)&offset_i, node_offset_t(offset_i.value - item_erase_size)); | |
176 | } | |
177 | ||
178 | // b. kv[index-1] ... kv[0] ... offset[index+1] >> sizeof(node_offset_t) | |
179 | mut.shift_absolute(p_item_end, p_offset_end - p_item_end, sizeof(node_offset_t)); | |
180 | ||
181 | // c. ... kv[n] ... kv[index+1] >> item_erase_size | |
182 | mut.shift_absolute(p_left_bound, p_item_start - p_left_bound, erase_size); | |
183 | ||
184 | // d. update num_keys | |
185 | mut.copy_in_absolute((void*)sub_items.p_num_keys, num_keys_t(sub_items.keys() - 1)); | |
186 | ||
187 | return erase_size; | |
188 | } | |
189 | ||
f67539c2 TL |
190 | template class internal_sub_items_t::Appender<KeyT::VIEW>; |
191 | template class internal_sub_items_t::Appender<KeyT::HOBJ>; | |
192 | ||
193 | // helper type for the visitor | |
194 | template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; | |
195 | // explicit deduction guide | |
196 | template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; | |
197 | ||
198 | template <KeyT KT> | |
20effc67 TL |
199 | void leaf_sub_items_t::Appender<KT>::append( |
200 | const leaf_sub_items_t& src, index_t from, index_t items) | |
201 | { | |
202 | if (p_append) { | |
203 | // append from empty | |
204 | assert(cnt <= APPENDER_LIMIT); | |
205 | assert(from <= src.keys()); | |
206 | if (items == 0) { | |
207 | return; | |
208 | } | |
209 | if (op_src) { | |
210 | assert(*op_src == src); | |
211 | } else { | |
212 | op_src = src; | |
213 | } | |
214 | assert(from < src.keys()); | |
215 | assert(from + items <= src.keys()); | |
216 | appends[cnt] = range_items_t{from, items}; | |
217 | ++cnt; | |
218 | } else { | |
219 | // append from existing | |
220 | assert(op_dst.has_value()); | |
221 | assert(!p_appended); | |
222 | assert(from == 0); | |
223 | assert(items); | |
224 | assert(items == src.keys()); | |
225 | ||
226 | num_keys_t num_keys = op_dst->keys(); | |
227 | node_offset_t compensate = op_dst->get_offset(num_keys - 1).value; | |
228 | const char* p_items_start = op_dst->p_start(); | |
229 | const char* p_items_end = op_dst->p_items_end; | |
230 | ||
231 | // update dst num_keys | |
232 | num_keys += items; | |
233 | p_mut->copy_in_absolute((char*)op_dst->p_num_keys, num_keys); | |
234 | ||
235 | // shift dst items | |
236 | std::size_t src_offsets_size = sizeof(node_offset_t) * items; | |
237 | p_mut->shift_absolute(p_items_start, | |
238 | p_items_end - p_items_start, | |
239 | -(int)src_offsets_size); | |
240 | ||
241 | // fill offsets from src | |
242 | node_offset_t offset; | |
243 | char* p_cur_offset = const_cast<char*>(p_items_end); | |
244 | for (auto i = from; i < from + items; ++i) { | |
245 | offset = src.get_offset(i).value + compensate; | |
246 | p_cur_offset -= sizeof(node_offset_t); | |
247 | p_mut->copy_in_absolute(p_cur_offset, offset); | |
248 | } | |
249 | ||
250 | // fill items from src | |
251 | auto p_src_items_start = src.get_item_end(from + items); | |
252 | std::size_t src_items_size = src.get_item_end(from) - p_src_items_start; | |
253 | p_appended = const_cast<char*>(p_items_start) - src_offsets_size - src_items_size; | |
254 | p_mut->copy_in_absolute(p_appended, p_src_items_start, src_items_size); | |
255 | } | |
256 | } | |
257 | ||
258 | template <KeyT KT> | |
259 | char* leaf_sub_items_t::Appender<KT>::wrap() | |
260 | { | |
261 | if (op_dst.has_value()) { | |
262 | // append from existing | |
263 | assert(p_appended); | |
264 | return p_appended; | |
265 | } | |
266 | // append from empty | |
267 | assert(p_append); | |
f67539c2 TL |
268 | auto p_cur = p_append; |
269 | num_keys_t num_keys = 0; | |
270 | for (auto i = 0u; i < cnt; ++i) { | |
271 | auto& a = appends[i]; | |
272 | std::visit(overloaded { | |
273 | [&] (const range_items_t& arg) { num_keys += arg.items; }, | |
274 | [&] (const kv_item_t& arg) { ++num_keys; } | |
275 | }, a); | |
276 | } | |
277 | assert(num_keys); | |
278 | p_cur -= sizeof(num_keys_t); | |
279 | p_mut->copy_in_absolute(p_cur, num_keys); | |
280 | ||
281 | node_offset_t last_offset = 0; | |
282 | for (auto i = 0u; i < cnt; ++i) { | |
283 | auto& a = appends[i]; | |
284 | std::visit(overloaded { | |
285 | [&] (const range_items_t& arg) { | |
286 | int compensate = (last_offset - op_src->get_offset_to_end(arg.from)); | |
287 | node_offset_t offset; | |
288 | for (auto i = arg.from; i < arg.from + arg.items; ++i) { | |
289 | offset = op_src->get_offset(i).value + compensate; | |
290 | p_cur -= sizeof(node_offset_t); | |
291 | p_mut->copy_in_absolute(p_cur, offset); | |
292 | } | |
293 | last_offset = offset; | |
294 | }, | |
295 | [&] (const kv_item_t& arg) { | |
20effc67 | 296 | last_offset += sizeof(snap_gen_t) + arg.value_config.allocation_size(); |
f67539c2 TL |
297 | p_cur -= sizeof(node_offset_t); |
298 | p_mut->copy_in_absolute(p_cur, last_offset); | |
299 | } | |
300 | }, a); | |
301 | } | |
302 | ||
303 | for (auto i = 0u; i < cnt; ++i) { | |
304 | auto& a = appends[i]; | |
305 | std::visit(overloaded { | |
306 | [&] (const range_items_t& arg) { | |
307 | auto _p_start = op_src->get_item_end(arg.from + arg.items); | |
308 | size_t _len = op_src->get_item_end(arg.from) - _p_start; | |
309 | p_cur -= _len; | |
310 | p_mut->copy_in_absolute(p_cur, _p_start, _len); | |
311 | }, | |
312 | [&] (const kv_item_t& arg) { | |
313 | assert(pp_value); | |
314 | p_cur -= sizeof(snap_gen_t); | |
315 | p_mut->copy_in_absolute(p_cur, snap_gen_t::template from_key<KT>(*arg.p_key)); | |
20effc67 TL |
316 | p_cur -= arg.value_config.allocation_size(); |
317 | auto p_value = reinterpret_cast<value_header_t*>(p_cur); | |
318 | p_value->initiate(*p_mut, arg.value_config); | |
319 | *pp_value = p_value; | |
f67539c2 TL |
320 | } |
321 | }, a); | |
322 | } | |
323 | return p_cur; | |
324 | } | |
325 | ||
326 | template class leaf_sub_items_t::Appender<KeyT::VIEW>; | |
327 | template class leaf_sub_items_t::Appender<KeyT::HOBJ>; | |
328 | ||
329 | } |