rippled
Loading...
Searching...
No Matches
RawStateTable.cpp
1#include <xrpl/basics/contract.h>
2#include <xrpl/ledger/detail/RawStateTable.h>
3
4namespace xrpl {
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 "xrpl::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 "xrpl::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(), "xrpl::detail::RawStateTable::exists : nonzero key");
171 auto const iter = items_.find(k.key);
172 if (iter == items_.end())
173 return base.exists(k);
174 auto const& item = iter->second;
175 if (item.action == Action::erase)
176 return false;
177 if (!k.check(*item.sle))
178 return false;
179 return true;
180}
181
182/* This works by first calculating succ() on the parent,
183 then calculating succ() our internal list, and taking
184 the lower of the two.
185*/
186auto
188 ReadView const& base,
189 key_type const& key,
191{
192 std::optional<key_type> next = key;
193 items_t::const_iterator iter;
194 // Find base successor that is
195 // not also deleted in our list
196 do
197 {
198 next = base.succ(*next, last);
199 if (!next)
200 break;
201 iter = items_.find(*next);
202 } while (iter != items_.end() && iter->second.action == Action::erase);
203 // Find non-deleted successor in our list
204 for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
205 {
206 if (iter->second.action != Action::erase)
207 {
208 // Found both, return the lower key
209 if (!next || next > iter->first)
210 next = iter->first;
211 break;
212 }
213 }
214 // Nothing in our list, return
215 // what we got from the parent.
216 if (last && next >= last)
217 return std::nullopt;
218 return next;
219}
220
221void
223{
224 // The base invariant is checked during apply
225 auto const result = items_.emplace(
227 std::forward_as_tuple(sle->key()),
229 if (result.second)
230 return;
231 auto& item = result.first->second;
232 switch (item.action)
233 {
234 case Action::erase:
235 LogicError("RawStateTable::erase: already erased");
236 break;
237 case Action::insert:
238 items_.erase(result.first);
239 break;
240 case Action::replace:
241 item.action = Action::erase;
242 item.sle = sle;
243 break;
244 }
245}
246
247void
249{
250 auto const result = items_.emplace(
252 std::forward_as_tuple(sle->key()),
254 if (result.second)
255 return;
256 auto& item = result.first->second;
257 switch (item.action)
258 {
259 case Action::erase:
260 item.action = Action::replace;
261 item.sle = sle;
262 break;
263 case Action::insert:
264 LogicError("RawStateTable::insert: already inserted");
265 break;
266 case Action::replace:
267 LogicError("RawStateTable::insert: already exists");
268 break;
269 }
270}
271
272void
274{
275 auto const result = items_.emplace(
277 std::forward_as_tuple(sle->key()),
279 if (result.second)
280 return;
281 auto& item = result.first->second;
282 switch (item.action)
283 {
284 case Action::erase:
285 LogicError("RawStateTable::replace: was erased");
286 break;
287 case Action::insert:
288 case Action::replace:
289 item.sle = sle;
290 break;
291 }
292}
293
295RawStateTable::read(ReadView const& base, Keylet const& k) const
296{
297 auto const iter = items_.find(k.key);
298 if (iter == items_.end())
299 return base.read(k);
300 auto const& item = iter->second;
301 if (item.action == Action::erase)
302 return nullptr;
303 // Convert to SLE const
304 std::shared_ptr<SLE const> sle = item.sle;
305 if (!k.check(*sle))
306 return nullptr;
307 return sle;
308}
309
310void
312{
313 dropsDestroyed_ += fee;
314}
315
318{
320 items_.begin(), items_.end(), base.sles.begin(), base.sles.end());
321}
322
325{
327 items_.end(), items_.end(), base.sles.end(), base.sles.end());
328}
329
331RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const
332{
334 items_.upper_bound(key),
335 items_.end(),
336 base.sles.upper_bound(key),
337 base.sles.end());
338}
339
340} // namespace detail
341} // namespace xrpl
T begin(T... args)
Interface for ledger entry changes.
Definition RawView.h:15
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.
virtual void rawInsert(std::shared_ptr< SLE > const &sle)=0
Unconditionally insert a state item.
virtual void rawDestroyXRP(XRPAmount const &fee)=0
Destroy XRP.
A view into a ledger.
Definition ReadView.h:32
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
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
bool isNonZero() const
Definition base_uint.h:526
std::unique_ptr< base_type > copy() const override
bool equal(base_type const &impl) const override
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::shared_ptr< SLE const > read(ReadView const &base, Keylet const &k) const
std::optional< key_type > succ(ReadView const &base, key_type const &key, std::optional< key_type > const &last) const
bool exists(ReadView const &base, Keylet const &k) const
std::unique_ptr< ReadView::sles_type::iter_base > slesBegin(ReadView const &base) const
void apply(RawView &to) const
void destroyXRP(XRPAmount const &fee)
std::unique_ptr< ReadView::sles_type::iter_base > slesUpperBound(ReadView const &base, uint256 const &key) 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
uint256 key
Definition Keylet.h:21
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Definition Keylet.cpp:9
iterator begin() const
Definition ReadView.cpp:10
iterator end() const
Definition ReadView.cpp:16
iterator upper_bound(key_type const &key) const
Definition ReadView.cpp:22
T upper_bound(T... args)