rippled
Loading...
Searching...
No Matches
RawStateTable.cpp
1#include <xrpl/basics/contract.h>
2#include <xrpl/ledger/detail/RawStateTable.h>
3
4namespace ripple {
5namespace detail {
6
8{
9private:
14 items_t::const_iterator iter1_;
15 items_t::const_iterator end1_;
16
17public:
18 sles_iter_impl(sles_iter_impl const&) = default;
19
21 items_t::const_iterator iter1,
22 items_t::const_iterator end1,
25 : iter0_(iter0), end0_(end0), iter1_(iter1), end1_(end1)
26 {
27 if (iter0_ != end0_)
28 sle0_ = *iter0_;
29 if (iter1_ != end1)
30 {
31 sle1_ = iter1_->second.sle;
32 skip();
33 }
34 }
35
37 copy() const override
38 {
40 }
41
42 bool
43 equal(base_type const& impl) const override
44 {
45 if (auto const p = dynamic_cast<sles_iter_impl const*>(&impl))
46 {
47 XRPL_ASSERT(
48 end1_ == p->end1_ && end0_ == p->end0_,
49 "ripple::detail::RawStateTable::equal : matching end "
50 "iterators");
51 return iter1_ == p->iter1_ && iter0_ == p->iter0_;
52 }
53
54 return false;
55 }
56
57 void
58 increment() override
59 {
60 XRPL_ASSERT(
61 sle1_ || sle0_,
62 "ripple::detail::RawStateTable::increment : either SLE is "
63 "non-null");
64
65 if (sle1_ && !sle0_)
66 {
67 inc1();
68 return;
69 }
70
71 if (sle0_ && !sle1_)
72 {
73 inc0();
74 return;
75 }
76
77 if (sle1_->key() == sle0_->key())
78 {
79 inc1();
80 inc0();
81 }
82 else if (sle1_->key() < sle0_->key())
83 {
84 inc1();
85 }
86 else
87 {
88 inc0();
89 }
90 skip();
91 }
92
94 dereference() const override
95 {
96 if (!sle1_)
97 return sle0_;
98 else if (!sle0_)
99 return sle1_;
100 if (sle1_->key() <= sle0_->key())
101 return sle1_;
102 return sle0_;
103 }
104
105private:
106 void
108 {
109 ++iter0_;
110 if (iter0_ == end0_)
111 sle0_ = nullptr;
112 else
113 sle0_ = *iter0_;
114 }
115
116 void
118 {
119 ++iter1_;
120 if (iter1_ == end1_)
121 sle1_ = nullptr;
122 else
123 sle1_ = iter1_->second.sle;
124 }
125
126 void
128 {
129 while (iter1_ != end1_ && iter1_->second.action == Action::erase &&
130 sle0_->key() == sle1_->key())
131 {
132 inc1();
133 inc0();
134 if (!sle0_)
135 return;
136 }
137 }
138};
139
140//------------------------------------------------------------------------------
141
142// Base invariants are checked by the base during apply()
143
144void
146{
148 for (auto const& elem : items_)
149 {
150 auto const& item = elem.second;
151 switch (item.action)
152 {
153 case Action::erase:
154 to.rawErase(item.sle);
155 break;
156 case Action::insert:
157 to.rawInsert(item.sle);
158 break;
159 case Action::replace:
160 to.rawReplace(item.sle);
161 break;
162 }
163 }
164}
165
166bool
167RawStateTable::exists(ReadView const& base, Keylet const& k) const
168{
169 XRPL_ASSERT(
170 k.key.isNonZero(),
171 "ripple::detail::RawStateTable::exists : nonzero key");
172 auto const iter = items_.find(k.key);
173 if (iter == items_.end())
174 return base.exists(k);
175 auto const& item = iter->second;
176 if (item.action == Action::erase)
177 return false;
178 if (!k.check(*item.sle))
179 return false;
180 return true;
181}
182
183/* This works by first calculating succ() on the parent,
184 then calculating succ() our internal list, and taking
185 the lower of the two.
186*/
187auto
189 ReadView const& base,
190 key_type const& key,
192{
193 std::optional<key_type> next = key;
194 items_t::const_iterator iter;
195 // Find base successor that is
196 // not also deleted in our list
197 do
198 {
199 next = base.succ(*next, last);
200 if (!next)
201 break;
202 iter = items_.find(*next);
203 } while (iter != items_.end() && iter->second.action == Action::erase);
204 // Find non-deleted successor in our list
205 for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
206 {
207 if (iter->second.action != Action::erase)
208 {
209 // Found both, return the lower key
210 if (!next || next > iter->first)
211 next = iter->first;
212 break;
213 }
214 }
215 // Nothing in our list, return
216 // what we got from the parent.
217 if (last && next >= last)
218 return std::nullopt;
219 return next;
220}
221
222void
224{
225 // The base invariant is checked during apply
226 auto const result = items_.emplace(
228 std::forward_as_tuple(sle->key()),
230 if (result.second)
231 return;
232 auto& item = result.first->second;
233 switch (item.action)
234 {
235 case Action::erase:
236 LogicError("RawStateTable::erase: already erased");
237 break;
238 case Action::insert:
239 items_.erase(result.first);
240 break;
241 case Action::replace:
242 item.action = Action::erase;
243 item.sle = sle;
244 break;
245 }
246}
247
248void
250{
251 auto const result = items_.emplace(
253 std::forward_as_tuple(sle->key()),
255 if (result.second)
256 return;
257 auto& item = result.first->second;
258 switch (item.action)
259 {
260 case Action::erase:
261 item.action = Action::replace;
262 item.sle = sle;
263 break;
264 case Action::insert:
265 LogicError("RawStateTable::insert: already inserted");
266 break;
267 case Action::replace:
268 LogicError("RawStateTable::insert: already exists");
269 break;
270 }
271}
272
273void
275{
276 auto const result = items_.emplace(
278 std::forward_as_tuple(sle->key()),
280 if (result.second)
281 return;
282 auto& item = result.first->second;
283 switch (item.action)
284 {
285 case Action::erase:
286 LogicError("RawStateTable::replace: was erased");
287 break;
288 case Action::insert:
289 case Action::replace:
290 item.sle = sle;
291 break;
292 }
293}
294
296RawStateTable::read(ReadView const& base, Keylet const& k) const
297{
298 auto const iter = items_.find(k.key);
299 if (iter == items_.end())
300 return base.read(k);
301 auto const& item = iter->second;
302 if (item.action == Action::erase)
303 return nullptr;
304 // Convert to SLE const
305 std::shared_ptr<SLE const> sle = item.sle;
306 if (!k.check(*sle))
307 return nullptr;
308 return sle;
309}
310
311void
313{
314 dropsDestroyed_ += fee;
315}
316
319{
321 items_.begin(), items_.end(), base.sles.begin(), base.sles.end());
322}
323
326{
328 items_.end(), items_.end(), base.sles.end(), base.sles.end());
329}
330
332RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const
333{
335 items_.upper_bound(key),
336 items_.end(),
337 base.sles.upper_bound(key),
338 base.sles.end());
339}
340
341} // namespace detail
342} // namespace ripple
T begin(T... args)
Interface for ledger entry changes.
Definition RawView.h:15
virtual void rawInsert(std::shared_ptr< SLE > const &sle)=0
Unconditionally insert a state item.
virtual void rawDestroyXRP(XRPAmount const &fee)=0
Destroy XRP.
virtual void rawReplace(std::shared_ptr< SLE > const &sle)=0
Unconditionally replace a state item.
virtual void rawErase(std::shared_ptr< SLE > const &sle)=0
Delete an existing state item.
A view into a ledger.
Definition ReadView.h:32
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
sles_type sles
Iterable range of ledger state items.
Definition ReadView.h:226
bool isNonZero() const
Definition base_uint.h:526
sles_iter_impl(items_t::const_iterator iter1, items_t::const_iterator end1, ReadView::sles_type::iterator iter0, ReadView::sles_type::iterator end0)
sles_iter_impl(sles_iter_impl const &)=default
std::unique_ptr< base_type > copy() const override
bool equal(base_type const &impl) const override
std::optional< key_type > succ(ReadView const &base, key_type const &key, std::optional< key_type > const &last) const
void destroyXRP(XRPAmount const &fee)
bool exists(ReadView const &base, Keylet const &k) const
void apply(RawView &to) const
std::unique_ptr< ReadView::sles_type::iter_base > slesUpperBound(ReadView const &base, uint256 const &key) const
std::shared_ptr< SLE const > read(ReadView const &base, Keylet const &k) const
std::unique_ptr< ReadView::sles_type::iter_base > slesBegin(ReadView const &base) const
std::unique_ptr< ReadView::sles_type::iter_base > slesEnd(ReadView const &base) const
T emplace(T... args)
T end(T... args)
T erase(T... args)
T find(T... args)
T forward_as_tuple(T... args)
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
T piecewise_construct
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Definition Keylet.cpp:9
uint256 key
Definition Keylet.h:21
iterator upper_bound(key_type const &key) const
Definition ReadView.cpp:22
iterator begin() const
Definition ReadView.cpp:10
T upper_bound(T... args)