]> git.proxmox.com Git - ceph.git/blame - ceph/src/crimson/os/seastore/onode_manager/staged-fltree/stages/node_stage.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / crimson / os / seastore / onode_manager / staged-fltree / stages / node_stage.h
CommitLineData
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 "crimson/os/seastore/onode_manager/staged-fltree/node_types.h"
7#include "key_layout.h"
8#include "stage_types.h"
9
10namespace crimson::os::seastore::onode {
11
12class NodeExtentMutable;
13
14/**
15 * node_extent_t
16 *
17 * The top indexing stage implementation for node N0/N1/N2/N3, implements
18 * staged contract as an indexable container, and provides access to node
19 * header.
20 *
21 * The specific field layout are defined by FieldType which are
22 * node_fields_0_t, node_fields_1_t, node_fields_2_t, internal_fields_3_t and
23 * leaf_fields_3_t. Diagrams see node_stage_layout.h.
24 */
25template <typename FieldType, node_type_t _NODE_TYPE>
26class node_extent_t {
27 public:
20effc67 28 using value_input_t = value_input_type_t<_NODE_TYPE>;
f67539c2
TL
29 using value_t = value_type_t<_NODE_TYPE>;
30 using num_keys_t = typename FieldType::num_keys_t;
31 static constexpr node_type_t NODE_TYPE = _NODE_TYPE;
32 static constexpr field_type_t FIELD_TYPE = FieldType::FIELD_TYPE;
f67539c2
TL
33
34 // TODO: remove
35 node_extent_t() = default;
36
20effc67
TL
37 node_extent_t(const FieldType* p_fields, extent_len_t node_size)
38 : p_fields{p_fields}, node_size{node_size} {
39 assert(is_valid_node_size(node_size));
f67539c2
TL
40 validate(*p_fields);
41 }
42
43 const char* p_start() const { return fields_start(*p_fields); }
44
f67539c2
TL
45 bool is_level_tail() const { return p_fields->is_level_tail(); }
46 level_t level() const { return p_fields->header.level; }
47 node_offset_t free_size() const {
20effc67
TL
48 return p_fields->template free_size_before<NODE_TYPE>(
49 keys(), node_size);
50 }
51 extent_len_t total_size() const {
52 return p_fields->total_size(node_size);
f67539c2 53 }
f67539c2
TL
54 const char* p_left_bound() const;
55 template <node_type_t T = NODE_TYPE>
56 std::enable_if_t<T == node_type_t::INTERNAL, const laddr_packed_t*>
57 get_end_p_laddr() const {
58 assert(is_level_tail());
59 if constexpr (FIELD_TYPE == field_type_t::N3) {
20effc67 60 return p_fields->get_p_child_addr(keys(), node_size);
f67539c2 61 } else {
20effc67
TL
62 auto offset_start = p_fields->get_item_end_offset(
63 keys(), node_size);
64 assert(offset_start <= node_size);
f67539c2
TL
65 offset_start -= sizeof(laddr_packed_t);
66 auto p_addr = p_start() + offset_start;
67 return reinterpret_cast<const laddr_packed_t*>(p_addr);
68 }
69 }
70
71 // container type system
72 using key_get_type = typename FieldType::key_get_type;
73 static constexpr auto CONTAINER_TYPE = ContainerType::INDEXABLE;
74 index_t keys() const { return p_fields->num_keys; }
20effc67
TL
75 key_get_type operator[] (index_t index) const {
76 return p_fields->get_key(index, node_size);
77 }
78 extent_len_t size_before(index_t index) const {
79 auto free_size = p_fields->template free_size_before<NODE_TYPE>(
80 index, node_size);
f67539c2
TL
81 assert(total_size() >= free_size);
82 return total_size() - free_size;
83 }
84 node_offset_t size_to_nxt_at(index_t index) const;
85 node_offset_t size_overhead_at(index_t index) const {
86 return FieldType::ITEM_OVERHEAD; }
20effc67 87 container_range_t get_nxt_container(index_t index) const;
f67539c2
TL
88
89 template <typename T = FieldType>
90 std::enable_if_t<T::FIELD_TYPE == field_type_t::N3, const value_t*>
91 get_p_value(index_t index) const {
92 assert(index < keys());
93 if constexpr (NODE_TYPE == node_type_t::INTERNAL) {
20effc67 94 return p_fields->get_p_child_addr(index, node_size);
f67539c2 95 } else {
20effc67
TL
96 auto range = get_nxt_container(index).range;
97 auto ret = reinterpret_cast<const value_header_t*>(range.p_start);
98 assert(range.p_start + ret->allocation_size() == range.p_end);
f67539c2
TL
99 return ret;
100 }
101 }
102
103 void encode(const char* p_node_start, ceph::bufferlist& encoded) const {
104 assert(p_node_start == p_start());
105 // nothing to encode as the container range is the entire extent
106 }
107
108 static node_extent_t decode(const char* p_node_start,
20effc67 109 extent_len_t node_size,
f67539c2
TL
110 ceph::bufferlist::const_iterator& delta) {
111 // nothing to decode
20effc67
TL
112 return node_extent_t(
113 reinterpret_cast<const FieldType*>(p_node_start),
114 node_size);
f67539c2
TL
115 }
116
117 static void validate(const FieldType& fields) {
118#ifndef NDEBUG
119 assert(fields.header.get_node_type() == NODE_TYPE);
120 assert(fields.header.get_field_type() == FieldType::FIELD_TYPE);
121 if constexpr (NODE_TYPE == node_type_t::INTERNAL) {
122 assert(fields.header.level > 0u);
123 } else {
124 assert(fields.header.level == 0u);
125 }
126#endif
127 }
128
129 static void bootstrap_extent(
130 NodeExtentMutable&, field_type_t, node_type_t, bool, level_t);
131
132 static void update_is_level_tail(NodeExtentMutable&, const node_extent_t&, bool);
133
134 static node_offset_t header_size() { return FieldType::HEADER_SIZE; }
135
1e59de90 136 template <IsFullKey Key>
f67539c2 137 static node_offset_t estimate_insert(
1e59de90 138 const Key& key, const value_input_t& value) {
f67539c2
TL
139 auto size = FieldType::estimate_insert_one();
140 if constexpr (FIELD_TYPE == field_type_t::N2) {
1e59de90 141 size += ns_oid_view_t::estimate_size(key);
f67539c2
TL
142 } else if constexpr (FIELD_TYPE == field_type_t::N3 &&
143 NODE_TYPE == node_type_t::LEAF) {
20effc67 144 size += value.allocation_size();
f67539c2
TL
145 }
146 return size;
147 }
148
1e59de90 149 template <IsFullKey Key>
f67539c2
TL
150 static const value_t* insert_at(
151 NodeExtentMutable& mut, const node_extent_t&,
1e59de90 152 const Key& key, const value_input_t& value,
f67539c2
TL
153 index_t index, node_offset_t size, const char* p_left_bound) {
154 if constexpr (FIELD_TYPE == field_type_t::N3) {
155 ceph_abort("not implemented");
156 } else {
157 ceph_abort("impossible");
158 }
159 }
160
1e59de90 161 template <IsFullKey Key>
f67539c2
TL
162 static memory_range_t insert_prefix_at(
163 NodeExtentMutable&, const node_extent_t&,
1e59de90 164 const Key& key,
f67539c2
TL
165 index_t index, node_offset_t size, const char* p_left_bound);
166
167 static void update_size_at(
168 NodeExtentMutable&, const node_extent_t&, index_t index, int change);
169
170 static node_offset_t trim_until(
171 NodeExtentMutable&, const node_extent_t&, index_t index);
172 static node_offset_t trim_at(NodeExtentMutable&, const node_extent_t&,
173 index_t index, node_offset_t trimmed);
174
20effc67
TL
175 static node_offset_t erase_at(NodeExtentMutable&, const node_extent_t&,
176 index_t index, const char* p_left_bound);
177
f67539c2
TL
178 template <KeyT KT>
179 class Appender;
180
181 private:
182 const FieldType& fields() const { return *p_fields; }
183 const FieldType* p_fields;
20effc67 184 extent_len_t node_size;
f67539c2
TL
185};
186
187template <typename FieldType, node_type_t NODE_TYPE>
188template <KeyT KT>
189class node_extent_t<FieldType, NODE_TYPE>::Appender {
190 public:
191 Appender(NodeExtentMutable* p_mut, char* p_append)
192 : p_mut{p_mut}, p_start{p_append} {
193#ifndef NDEBUG
194 auto p_fields = reinterpret_cast<const FieldType*>(p_append);
195 assert(*(p_fields->header.get_field_type()) == FIELD_TYPE);
196 assert(p_fields->header.get_node_type() == NODE_TYPE);
197 assert(p_fields->num_keys == 0);
198#endif
199 p_append_left = p_start + FieldType::HEADER_SIZE;
20effc67 200 p_append_right = p_start + p_mut->get_length();
f67539c2 201 }
20effc67 202 Appender(NodeExtentMutable*, const node_extent_t&, bool open = false);
f67539c2 203 void append(const node_extent_t& src, index_t from, index_t items);
20effc67 204 void append(const full_key_t<KT>&, const value_input_t&, const value_t*&);
f67539c2
TL
205 char* wrap();
206 std::tuple<NodeExtentMutable*, char*> open_nxt(const key_get_type&);
207 std::tuple<NodeExtentMutable*, char*> open_nxt(const full_key_t<KT>&);
208 void wrap_nxt(char* p_append) {
209 if constexpr (FIELD_TYPE != field_type_t::N3) {
210 assert(p_append < p_append_right);
211 assert(p_append_left < p_append);
212 p_append_right = p_append;
20effc67
TL
213 auto new_offset = p_append - p_start;
214 assert(new_offset > 0);
215 assert(new_offset < p_mut->get_length());
216 FieldType::append_offset(*p_mut, new_offset, p_append_left);
f67539c2
TL
217 ++num_keys;
218 } else {
219 ceph_abort("not implemented");
220 }
221 }
222
223 private:
224 const node_extent_t* p_src = nullptr;
225 NodeExtentMutable* p_mut;
226 char* p_start;
227 char* p_append_left;
228 char* p_append_right;
229 num_keys_t num_keys = 0;
230};
231
232}