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 {
98 return sle0_;
99 }
100 if (!sle0_)
101 {
102 return sle1_;
103 }
104 if (sle1_->key() <= sle0_->key())
105 return sle1_;
106 return sle0_;
107 }
108
109private:
110 void
112 {
113 ++iter0_;
114 if (iter0_ == end0_)
115 {
116 sle0_ = nullptr;
117 }
118 else
119 {
120 sle0_ = *iter0_;
121 }
122 }
123
124 void
126 {
127 ++iter1_;
128 if (iter1_ == end1_)
129 {
130 sle1_ = nullptr;
131 }
132 else
133 {
134 sle1_ = iter1_->second.sle;
135 }
136 }
137
138 void
140 {
141 while (iter1_ != end1_ && iter1_->second.action == Action::erase &&
142 sle0_->key() == sle1_->key())
143 {
144 inc1();
145 inc0();
146 if (!sle0_)
147 return;
148 }
149 }
150};
151
152//------------------------------------------------------------------------------
153
154// Base invariants are checked by the base during apply()
155
156void
158{
160 for (auto const& elem : items_)
161 {
162 auto const& item = elem.second;
163 switch (item.action)
164 {
165 case Action::erase:
166 to.rawErase(item.sle);
167 break;
168 case Action::insert:
169 to.rawInsert(item.sle);
170 break;
171 case Action::replace:
172 to.rawReplace(item.sle);
173 break;
174 }
175 }
176}
177
178bool
179RawStateTable::exists(ReadView const& base, Keylet const& k) const
180{
181 XRPL_ASSERT(k.key.isNonZero(), "xrpl::detail::RawStateTable::exists : nonzero key");
182 auto const iter = items_.find(k.key);
183 if (iter == items_.end())
184 return base.exists(k);
185 auto const& item = iter->second;
186 if (item.action == Action::erase)
187 return false;
188 if (!k.check(*item.sle))
189 return false;
190 return true;
191}
192
193/* This works by first calculating succ() on the parent,
194 then calculating succ() our internal list, and taking
195 the lower of the two.
196*/
197auto
200{
201 std::optional<key_type> next = key;
202 items_t::const_iterator iter;
203 // Find base successor that is
204 // not also deleted in our list
205 do
206 {
207 next = base.succ(*next, last);
208 if (!next)
209 break;
210 iter = items_.find(*next);
211 } while (iter != items_.end() && iter->second.action == Action::erase);
212 // Find non-deleted successor in our list
213 for (iter = items_.upper_bound(key); iter != items_.end(); ++iter)
214 {
215 if (iter->second.action != Action::erase)
216 {
217 // Found both, return the lower key
218 if (!next || next > iter->first)
219 next = iter->first;
220 break;
221 }
222 }
223 // Nothing in our list, return
224 // what we got from the parent.
225 if (last && next >= last)
226 return std::nullopt;
227 return next;
228}
229
230void
232{
233 // The base invariant is checked during apply
234 auto const result = items_.emplace(
236 std::forward_as_tuple(sle->key()),
238 if (result.second)
239 return;
240 auto& item = result.first->second;
241 switch (item.action)
242 {
243 case Action::erase:
244 LogicError("RawStateTable::erase: already erased");
245 break;
246 case Action::insert:
247 items_.erase(result.first);
248 break;
249 case Action::replace:
250 item.action = Action::erase;
251 item.sle = sle;
252 break;
253 }
254}
255
256void
258{
259 auto const result = items_.emplace(
261 std::forward_as_tuple(sle->key()),
263 if (result.second)
264 return;
265 auto& item = result.first->second;
266 switch (item.action)
267 {
268 case Action::erase:
269 item.action = Action::replace;
270 item.sle = sle;
271 break;
272 case Action::insert:
273 LogicError("RawStateTable::insert: already inserted");
274 break;
275 case Action::replace:
276 LogicError("RawStateTable::insert: already exists");
277 break;
278 }
279}
280
281void
283{
284 auto const result = items_.emplace(
286 std::forward_as_tuple(sle->key()),
288 if (result.second)
289 return;
290 auto& item = result.first->second;
291 switch (item.action)
292 {
293 case Action::erase:
294 LogicError("RawStateTable::replace: was erased");
295 break;
296 case Action::insert:
297 case Action::replace:
298 item.sle = sle;
299 break;
300 }
301}
302
304RawStateTable::read(ReadView const& base, Keylet const& k) const
305{
306 auto const iter = items_.find(k.key);
307 if (iter == items_.end())
308 return base.read(k);
309 auto const& item = iter->second;
310 if (item.action == Action::erase)
311 return nullptr;
312 // Convert to SLE const
313 std::shared_ptr<SLE const> sle = item.sle;
314 if (!k.check(*sle))
315 return nullptr;
316 return sle;
317}
318
319void
321{
322 dropsDestroyed_ += fee;
323}
324
327{
329 items_.begin(), items_.end(), base.sles.begin(), base.sles.end());
330}
331
334{
336 items_.end(), items_.end(), base.sles.end(), base.sles.end());
337}
338
340RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const
341{
343 items_.upper_bound(key), items_.end(), base.sles.upper_bound(key), base.sles.end());
344}
345
346} // namespace detail
347} // namespace xrpl
T begin(T... args)
Interface for ledger entry changes.
Definition RawView.h:14
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:31
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:219
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:518
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:5
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:19
uint256 key
Definition Keylet.h:20
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)