rippled
RawStateTable.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/ledger/detail/RawStateTable.h>
21 #include <ripple/basics/contract.h>
22 
23 namespace ripple {
24 namespace detail {
25 
28 {
29 private:
31  ReadView::sles_type::iterator iter0_;
32  ReadView::sles_type::iterator end0_;
34  items_t::const_iterator iter1_;
35  items_t::const_iterator end1_;
36 
37 public:
38  sles_iter_impl (sles_iter_impl const&) = default;
39 
40  sles_iter_impl (items_t::const_iterator iter1,
41  items_t::const_iterator end1,
42  ReadView::sles_type::iterator iter0,
43  ReadView::sles_type::iterator end0)
44  : iter0_ (iter0)
45  , end0_ (end0)
46  , iter1_ (iter1)
47  , end1_ (end1)
48  {
49  if (iter0_ != end0_)
50  sle0_ = *iter0_;
51  if (iter1_ != end1)
52  {
53  sle1_ = iter1_->second.second;
54  skip ();
55  }
56  }
57 
59  copy() const override
60  {
61  return std::make_unique<sles_iter_impl>(*this);
62  }
63 
64  bool
65  equal (base_type const& impl) const override
66  {
67  auto const& other = dynamic_cast<
68  sles_iter_impl const&>(impl);
69  assert(end1_ == other.end1_ &&
70  end0_ == other.end0_);
71  return iter1_ == other.iter1_ &&
72  iter0_ == other.iter0_;
73  }
74 
75  void
76  increment() override
77  {
78  assert (sle1_ || sle0_);
79 
80  if (sle1_ && !sle0_)
81  {
82  inc1();
83  return;
84  }
85 
86  if (sle0_ && !sle1_)
87  {
88  inc0();
89  return;
90  }
91 
92  if (sle1_->key () == sle0_->key())
93  {
94  inc1();
95  inc0();
96  }
97  else if (sle1_->key () < sle0_->key())
98  {
99  inc1();
100  }
101  else
102  {
103  inc0();
104  }
105  skip();
106  }
107 
108  value_type
109  dereference() const override
110  {
111  if (! sle1_)
112  return sle0_;
113  else if (! sle0_)
114  return sle1_;
115  if (sle1_->key() <= sle0_->key())
116  return sle1_;
117  return sle0_;
118  }
119 private:
120  void inc0()
121  {
122  ++iter0_;
123  if (iter0_ == end0_)
124  sle0_ = nullptr;
125  else
126  sle0_ = *iter0_;
127  }
128 
129  void inc1()
130  {
131  ++iter1_;
132  if (iter1_ == end1_)
133  sle1_ = nullptr;
134  else
135  sle1_ = iter1_->second.second;
136  }
137 
138  void skip()
139  {
140  while (iter1_ != end1_ &&
141  iter1_->second.first == 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 
156 void
158 {
160  for (auto const& elem : items_)
161  {
162  auto const& item = elem.second;
163  switch(item.first)
164  {
165  case Action::erase:
166  to.rawErase(item.second);
167  break;
168  case Action::insert:
169  to.rawInsert(item.second);
170  break;
171  case Action::replace:
172  to.rawReplace(item.second);
173  break;
174  }
175  }
176 }
177 
178 bool
180  Keylet const& k) const
181 {
182  assert(k.key.isNonZero());
183  auto const iter = items_.find(k.key);
184  if (iter == items_.end())
185  return base.exists(k);
186  auto const& item = iter->second;
187  if (item.first == Action::erase)
188  return false;
189  if (! k.check(*item.second))
190  return false;
191  return true;
192 }
193 
194 /* This works by first calculating succ() on the parent,
195  then calculating succ() our internal list, and taking
196  the lower of the two.
197 */
198 auto
200  key_type const& key, boost::optional<
201  key_type> const& last) const ->
202  boost::optional<key_type>
203 {
204  boost::optional<key_type> next = key;
205  items_t::const_iterator iter;
206  // Find base successor that is
207  // not also deleted in our list
208  do
209  {
210  next = base.succ(*next, last);
211  if (! next)
212  break;
213  iter = items_.find(*next);
214  }
215  while (iter != items_.end() &&
216  iter->second.first == Action::erase);
217  // Find non-deleted successor in our list
218  for (iter = items_.upper_bound(key);
219  iter != items_.end (); ++iter)
220  {
221  if (iter->second.first != Action::erase)
222  {
223  // Found both, return the lower key
224  if (! next || next > iter->first)
225  next = iter->first;
226  break;
227  }
228  }
229  // Nothing in our list, return
230  // what we got from the parent.
231  if (last && next >= last)
232  return boost::none;
233  return next;
234 }
235 
236 void
238  std::shared_ptr<SLE> const& sle)
239 {
240  // The base invariant is checked during apply
241  auto const result = items_.emplace(
242  std::piecewise_construct,
243  std::forward_as_tuple(sle->key()),
245  Action::erase, sle));
246  if (result.second)
247  return;
248  auto& item = result.first->second;
249  switch(item.first)
250  {
251  case Action::erase:
252  LogicError("RawStateTable::erase: already erased");
253  break;
254  case Action::insert:
255  items_.erase(result.first);
256  break;
257  case Action::replace:
258  item.first = Action::erase;
259  item.second = sle;
260  break;
261  }
262 }
263 
264 void
266  std::shared_ptr<SLE> const& sle)
267 {
268  auto const result = items_.emplace(
269  std::piecewise_construct,
270  std::forward_as_tuple(sle->key()),
272  Action::insert, sle));
273  if (result.second)
274  return;
275  auto& item = result.first->second;
276  switch(item.first)
277  {
278  case Action::erase:
279  item.first = Action::replace;
280  item.second = sle;
281  break;
282  case Action::insert:
283  LogicError("RawStateTable::insert: already inserted");
284  break;
285  case Action::replace:
286  LogicError("RawStateTable::insert: already exists");
287  break;
288  }
289 }
290 
291 void
293  std::shared_ptr<SLE> const& sle)
294 {
295  auto const result = items_.emplace(
296  std::piecewise_construct,
297  std::forward_as_tuple(sle->key()),
299  Action::replace, sle));
300  if (result.second)
301  return;
302  auto& item = result.first->second;
303  switch(item.first)
304  {
305  case Action::erase:
306  LogicError("RawStateTable::replace: was erased");
307  break;
308  case Action::insert:
309  case Action::replace:
310  item.second = sle;
311  break;
312  }
313 }
314 
317  Keylet const& k) const
318 {
319  auto const iter =
320  items_.find(k.key);
321  if (iter == items_.end())
322  return base.read(k);
323  auto const& item = iter->second;
324  if (item.first == Action::erase)
325  return nullptr;
326  // Convert to SLE const
328  SLE const> sle = item.second;
329  if (! k.check(*sle))
330  return nullptr;
331  return sle;
332 }
333 
334 void
336 {
337  dropsDestroyed_ += fee;
338 }
339 
342 {
343  return std::make_unique<sles_iter_impl>(
344  items_.begin(), items_.end(),
345  base.sles.begin(), base.sles.end());
346 }
347 
349 RawStateTable::slesEnd (ReadView const& base) const
350 {
351  return std::make_unique<sles_iter_impl>(
352  items_.end(), items_.end(),
353  base.sles.end(), base.sles.end());
354 }
355 
357 RawStateTable::slesUpperBound (ReadView const& base, uint256 const& key) const
358 {
359  return std::make_unique<sles_iter_impl>(
360  items_.upper_bound(key), items_.end(),
361  base.sles.upper_bound(key), base.sles.end());
362 }
363 
364 } // detail
365 } // ripple
ripple::detail::RawStateTable::dropsDestroyed_
XRPAmount dropsDestroyed_
Definition: RawStateTable.h:98
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::detail::RawStateTable::sles_iter_impl::sles_iter_impl
sles_iter_impl(sles_iter_impl const &)=default
ripple::STLedgerEntry
Definition: STLedgerEntry.h:30
std::shared_ptr
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:430
std::map::find
T find(T... args)
ripple::detail::RawStateTable::sles_iter_impl::iter0_
ReadView::sles_type::iterator iter0_
Definition: RawStateTable.cpp:31
ripple::RawView::rawDestroyXRP
virtual void rawDestroyXRP(XRPAmount const &fee)=0
Destroy XRP.
ripple::detail::RawStateTable::Action::erase
@ erase
std::map::emplace
T emplace(T... args)
ripple::detail::RawStateTable::read
std::shared_ptr< SLE const > read(ReadView const &base, Keylet const &k) const
Definition: RawStateTable.cpp:316
ripple::detail::RawStateTable::sles_iter_impl::inc0
void inc0()
Definition: RawStateTable.cpp:120
ripple::ReadView::sles_type::upper_bound
iterator upper_bound(key_type const &key) const
Definition: ReadView.cpp:154
ripple::detail::RawStateTable::Action::replace
@ replace
ripple::RawView::rawReplace
virtual void rawReplace(std::shared_ptr< SLE > const &sle)=0
Unconditionally replace a state item.
ripple::ReadView::sles_type::begin
iterator begin() const
Definition: ReadView.cpp:138
ripple::detail::RawStateTable::sles_iter_impl::sles_iter_impl
sles_iter_impl(items_t::const_iterator iter1, items_t::const_iterator end1, ReadView::sles_type::iterator iter0, ReadView::sles_type::iterator end0)
Definition: RawStateTable.cpp:40
ripple::RawView::rawErase
virtual void rawErase(std::shared_ptr< SLE > const &sle)=0
Delete an existing state item.
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::base_uint< 256 >
ripple::RawView
Interface for ledger entry changes.
Definition: RawView.h:37
ripple::detail::RawStateTable::sles_iter_impl
Definition: RawStateTable.cpp:26
ripple::detail::RawStateTable::sles_iter_impl::dereference
value_type dereference() const override
Definition: RawStateTable.cpp:109
ripple::detail::RawStateTable::slesUpperBound
std::unique_ptr< ReadView::sles_type::iter_base > slesUpperBound(ReadView const &base, uint256 const &key) const
Definition: RawStateTable.cpp:357
ripple::RawView::rawInsert
virtual void rawInsert(std::shared_ptr< SLE > const &sle)=0
Unconditionally insert a state item.
ripple::ReadView::sles_type::end
iterator const & end() const
Definition: ReadView.cpp:145
ripple::ReadView::exists
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
std::map::erase
T erase(T... args)
ripple::ReadView::sles
sles_type sles
Iterable range of ledger state items.
Definition: ReadView.h:398
ripple::detail::RawStateTable::Action::insert
@ insert
ripple::detail::RawStateTable::slesBegin
std::unique_ptr< ReadView::sles_type::iter_base > slesBegin(ReadView const &base) const
Definition: RawStateTable.cpp:341
ripple::detail::RawStateTable::sles_iter_impl::equal
bool equal(base_type const &impl) const override
Definition: RawStateTable.cpp:65
std::forward_as_tuple
T forward_as_tuple(T... args)
ripple::detail::RawStateTable::erase
void erase(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:237
ripple::detail::RawStateTable::exists
bool exists(ReadView const &base, Keylet const &k) const
Definition: RawStateTable.cpp:179
std::map::upper_bound
T upper_bound(T... args)
ripple::detail::RawStateTable::sles_iter_impl::end1_
items_t::const_iterator end1_
Definition: RawStateTable.cpp:35
ripple::detail::RawStateTable::succ
boost::optional< key_type > succ(ReadView const &base, key_type const &key, boost::optional< key_type > const &last) const
Definition: RawStateTable.cpp:199
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::detail::RawStateTable::sles_iter_impl::copy
std::unique_ptr< base_type > copy() const override
Definition: RawStateTable.cpp:59
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:186
ripple::detail::RawStateTable::sles_iter_impl::increment
void increment() override
Definition: RawStateTable.cpp:76
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::detail::RawStateTable::apply
void apply(RawView &to) const
Definition: RawStateTable.cpp:157
ripple::detail::RawStateTable::items_
items_t items_
Definition: RawStateTable.h:97
ripple::detail::RawStateTable::destroyXRP
void destroyXRP(XRPAmount const &fee)
Definition: RawStateTable.cpp:335
ripple::detail::RawStateTable::sles_iter_impl::sle0_
std::shared_ptr< SLE const > sle0_
Definition: RawStateTable.cpp:30
std::map::begin
T begin(T... args)
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:50
ripple::detail::RawStateTable::sles_iter_impl::skip
void skip()
Definition: RawStateTable.cpp:138
ripple::detail::RawStateTable::insert
void insert(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:265
ripple::detail::ReadViewFwdRange< std::shared_ptr< SLE const > >::iter_base
ReadViewFwdIter< std::shared_ptr< SLE const > > iter_base
Definition: ReadViewFwdRange.h:75
ripple::detail::RawStateTable::sles_iter_impl::iter1_
items_t::const_iterator iter1_
Definition: RawStateTable.cpp:34
ripple::detail::RawStateTable::replace
void replace(std::shared_ptr< SLE > const &sle)
Definition: RawStateTable.cpp:292
ripple::Keylet::check
bool check(STLedgerEntry const &) const
Returns true if the SLE matches the type.
Definition: Keylet.cpp:26
ripple::detail::RawStateTable::sles_iter_impl::sle1_
std::shared_ptr< SLE const > sle1_
Definition: RawStateTable.cpp:33
std::map::end
T end(T... args)
ripple::detail::RawStateTable::sles_iter_impl::inc1
void inc1()
Definition: RawStateTable.cpp:129
ripple::detail::RawStateTable::slesEnd
std::unique_ptr< ReadView::sles_type::iter_base > slesEnd(ReadView const &base) const
Definition: RawStateTable.cpp:349
std::unique_ptr
STL class.
ripple::detail::RawStateTable::sles_iter_impl::end0_
ReadView::sles_type::iterator end0_
Definition: RawStateTable.cpp:32
ripple::XRPAmount
Definition: XRPAmount.h:46