]> git.proxmox.com Git - ceph.git/blame - ceph/src/crimson/os/seastore/onode_manager/staged-fltree/stages/item_iterator_stage.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / crimson / os / seastore / onode_manager / staged-fltree / stages / item_iterator_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 * item_iterator_t
16 *
17 * The STAGE_STRING implementation for node N0/N1, implements staged contract
18 * as an iterative container to resolve crush hash conflicts.
19 *
20 * The layout of the contaner to index ns, oid strings storing n items:
21 *
22 * # <--------- container range ---------> #
23 * #<~># items [i+1, n) #
24 * # # items [0, i) #<~>#
25 * # # <------ item i -------------> # #
26 * # # <--- item_range ---> | # #
27 * # # | # #
28 * # # next-stage | ns-oid | back_ # #
29 * # # contaner | strings | offset # #
30 * #...# range | | #...#
31 * ^ ^ | ^
32 * | | | |
33 * | +---------------------------+ |
34 * + p_items_start p_items_end +
35 */
36template <node_type_t NODE_TYPE>
37class item_iterator_t {
20effc67 38 using value_input_t = value_input_type_t<NODE_TYPE>;
f67539c2
TL
39 using value_t = value_type_t<NODE_TYPE>;
40 public:
20effc67
TL
41 item_iterator_t(const container_range_t& range)
42 : node_size{range.node_size},
43 p_items_start(range.range.p_start),
44 p_items_end(range.range.p_end) {
45 assert(is_valid_node_size(node_size));
f67539c2
TL
46 assert(p_items_start < p_items_end);
47 next_item_range(p_items_end);
48 }
49
50 const char* p_start() const { return item_range.p_start; }
51 const char* p_end() const { return item_range.p_end + sizeof(node_offset_t); }
52 const memory_range_t& get_item_range() const { return item_range; }
53 node_offset_t get_back_offset() const { return back_offset; }
54
55 // container type system
56 using key_get_type = const ns_oid_view_t&;
57 static constexpr auto CONTAINER_TYPE = ContainerType::ITERATIVE;
58 index_t index() const { return _index; }
59 key_get_type get_key() const {
60 if (!key.has_value()) {
61 key = ns_oid_view_t(item_range.p_end);
62 assert(item_range.p_start < (*key).p_start());
63 }
64 return *key;
65 }
66 node_offset_t size() const {
67 size_t ret = item_range.p_end - item_range.p_start + sizeof(node_offset_t);
20effc67 68 assert(ret < node_size);
f67539c2
TL
69 return ret;
70 };
71 node_offset_t size_to_nxt() const {
72 size_t ret = get_key().size() + sizeof(node_offset_t);
20effc67 73 assert(ret < node_size);
f67539c2
TL
74 return ret;
75 }
76 node_offset_t size_overhead() const {
77 return sizeof(node_offset_t) + get_key().size_overhead();
78 }
20effc67
TL
79 container_range_t get_nxt_container() const {
80 return {{item_range.p_start, get_key().p_start()}, node_size};
f67539c2
TL
81 }
82 bool has_next() const {
83 assert(p_items_start <= item_range.p_start);
84 return p_items_start < item_range.p_start;
85 }
86 const item_iterator_t<NODE_TYPE>& operator++() const {
87 assert(has_next());
88 next_item_range(item_range.p_start);
89 key.reset();
90 ++_index;
91 return *this;
92 }
93 void encode(const char* p_node_start, ceph::bufferlist& encoded) const {
94 int start_offset = p_items_start - p_node_start;
20effc67
TL
95 int stage_size = p_items_end - p_items_start;
96 assert(start_offset > 0);
97 assert(stage_size > 0);
98 assert(start_offset + stage_size <= (int)node_size);
f67539c2 99 ceph::encode(static_cast<node_offset_t>(start_offset), encoded);
20effc67 100 ceph::encode(static_cast<node_offset_t>(stage_size), encoded);
f67539c2
TL
101 ceph::encode(_index, encoded);
102 }
103
104 static item_iterator_t decode(const char* p_node_start,
20effc67 105 extent_len_t node_size,
f67539c2
TL
106 ceph::bufferlist::const_iterator& delta) {
107 node_offset_t start_offset;
108 ceph::decode(start_offset, delta);
20effc67
TL
109 node_offset_t stage_size;
110 ceph::decode(stage_size, delta);
111 assert(start_offset > 0);
112 assert(stage_size > 0);
113 assert((unsigned)start_offset + stage_size <= node_size);
f67539c2
TL
114 index_t index;
115 ceph::decode(index, delta);
116
20effc67
TL
117 item_iterator_t ret({{p_node_start + start_offset,
118 p_node_start + start_offset + stage_size},
119 node_size});
f67539c2
TL
120 while (index > 0) {
121 ++ret;
122 --index;
123 }
124 return ret;
125 }
126
127 static node_offset_t header_size() { return 0u; }
128
129 template <KeyT KT>
130 static node_offset_t estimate_insert(
20effc67 131 const full_key_t<KT>& key, const value_input_t&) {
f67539c2
TL
132 return ns_oid_view_t::estimate_size<KT>(key) + sizeof(node_offset_t);
133 }
134
135 template <KeyT KT>
136 static memory_range_t insert_prefix(
137 NodeExtentMutable& mut, const item_iterator_t<NODE_TYPE>& iter,
138 const full_key_t<KT>& key, bool is_end,
139 node_offset_t size, const char* p_left_bound);
140
141 static void update_size(
142 NodeExtentMutable& mut, const item_iterator_t<NODE_TYPE>& iter, int change);
143
144 static node_offset_t trim_until(NodeExtentMutable&, const item_iterator_t<NODE_TYPE>&);
145 static node_offset_t trim_at(
146 NodeExtentMutable&, const item_iterator_t<NODE_TYPE>&, node_offset_t trimmed);
147
20effc67
TL
148 static node_offset_t erase(
149 NodeExtentMutable&, const item_iterator_t<NODE_TYPE>&, const char*);
150
f67539c2
TL
151 template <KeyT KT>
152 class Appender;
153
154 private:
155 void next_item_range(const char* p_end) const {
156 auto p_item_end = p_end - sizeof(node_offset_t);
157 assert(p_items_start < p_item_end);
158 back_offset = reinterpret_cast<const node_offset_packed_t*>(p_item_end)->value;
159 assert(back_offset);
160 const char* p_item_start = p_item_end - back_offset;
161 assert(p_items_start <= p_item_start);
162 item_range = {p_item_start, p_item_end};
163 }
164
20effc67 165 extent_len_t node_size;
f67539c2
TL
166 const char* p_items_start;
167 const char* p_items_end;
168 mutable memory_range_t item_range;
169 mutable node_offset_t back_offset;
170 mutable std::optional<ns_oid_view_t> key;
171 mutable index_t _index = 0u;
172};
173
174template <node_type_t NODE_TYPE>
175template <KeyT KT>
176class item_iterator_t<NODE_TYPE>::Appender {
177 public:
178 Appender(NodeExtentMutable* p_mut, char* p_append)
179 : p_mut{p_mut}, p_append{p_append} {}
20effc67 180 Appender(NodeExtentMutable*, const item_iterator_t&, bool open);
f67539c2
TL
181 bool append(const item_iterator_t<NODE_TYPE>& src, index_t& items);
182 char* wrap() { return p_append; }
183 std::tuple<NodeExtentMutable*, char*> open_nxt(const key_get_type&);
184 std::tuple<NodeExtentMutable*, char*> open_nxt(const full_key_t<KT>&);
185 void wrap_nxt(char* _p_append);
186
187 private:
188 NodeExtentMutable* p_mut;
189 char* p_append;
190 char* p_offset_while_open;
191};
192
193}