rippled
OpenLedger.h
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 #ifndef RIPPLE_APP_LEDGER_OPENLEDGER_H_INCLUDED
21 #define RIPPLE_APP_LEDGER_OPENLEDGER_H_INCLUDED
22 
23 #include <ripple/app/ledger/Ledger.h>
24 #include <ripple/app/misc/CanonicalTXSet.h>
25 #include <ripple/basics/Log.h>
26 #include <ripple/basics/UnorderedContainers.h>
27 #include <ripple/beast/utility/Journal.h>
28 #include <ripple/core/Config.h>
29 #include <ripple/ledger/CachedSLEs.h>
30 #include <ripple/ledger/OpenView.h>
31 #include <cassert>
32 #include <mutex>
33 
34 namespace ripple {
35 
36 // How many total extra passes we make
37 // We must ensure we make at least one non-retriable pass
38 #define LEDGER_TOTAL_PASSES 3
39 
40 // How many extra retry passes we
41 // make if the previous retry pass made changes
42 #define LEDGER_RETRY_PASSES 1
43 
45 
46 //------------------------------------------------------------------------------
47 
50 {
51 private:
57 
58 public:
71 
72  OpenLedger() = delete;
73  OpenLedger(OpenLedger const&) = delete;
74  OpenLedger&
75  operator=(OpenLedger const&) = delete;
76 
81  explicit OpenLedger(
82  std::shared_ptr<Ledger const> const& ledger,
83  CachedSLEs& cache,
84  beast::Journal journal);
85 
99  bool
100  empty() const;
101 
113  current() const;
114 
125  bool
126  modify(modify_type const& f);
127 
161  void
162  accept(
163  Application& app,
164  Rules const& rules,
165  std::shared_ptr<Ledger const> const& ledger,
166  OrderedTxs const& locals,
167  bool retriesFirst,
168  OrderedTxs& retries,
169  ApplyFlags flags,
170  std::string const& suffix = "",
171  modify_type const& f = {});
172 
173 private:
179  template <class FwdRange>
180  static void
181  apply(
182  Application& app,
183  OpenView& view,
184  ReadView const& check,
185  FwdRange const& txs,
186  OrderedTxs& retries,
187  ApplyFlags flags,
188  std::map<uint256, bool>& shouldRecover,
189  beast::Journal j);
190 
192 
194  create(Rules const& rules, std::shared_ptr<Ledger const> const& ledger);
195 
196  static Result
197  apply_one(
198  Application& app,
199  OpenView& view,
200  std::shared_ptr<STTx const> const& tx,
201  bool retry,
202  ApplyFlags flags,
203  bool shouldRecover,
204  beast::Journal j);
205 };
206 
207 //------------------------------------------------------------------------------
208 
209 template <class FwdRange>
210 void
212  Application& app,
213  OpenView& view,
214  ReadView const& check,
215  FwdRange const& txs,
216  OrderedTxs& retries,
217  ApplyFlags flags,
218  std::map<uint256, bool>& shouldRecover,
219  beast::Journal j)
220 {
221  for (auto iter = txs.begin(); iter != txs.end(); ++iter)
222  {
223  try
224  {
225  // Dereferencing the iterator can
226  // throw since it may be transformed.
227  auto const tx = *iter;
228  auto const txId = tx->getTransactionID();
229  if (check.txExists(txId))
230  continue;
231  auto const result =
232  apply_one(app, view, tx, true, flags, shouldRecover[txId], j);
233  if (result == Result::retry)
234  retries.insert(tx);
235  }
236  catch (std::exception const&)
237  {
238  JLOG(j.error()) << "Caught exception";
239  }
240  }
241  bool retry = true;
242  for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
243  {
244  int changes = 0;
245  auto iter = retries.begin();
246  while (iter != retries.end())
247  {
248  switch (apply_one(
249  app,
250  view,
251  iter->second,
252  retry,
253  flags,
254  shouldRecover[iter->second->getTransactionID()],
255  j))
256  {
257  case Result::success:
258  ++changes;
259  [[fallthrough]];
260  case Result::failure:
261  iter = retries.erase(iter);
262  break;
263  case Result::retry:
264  ++iter;
265  }
266  }
267  // A non-retry pass made no changes
268  if (!changes && !retry)
269  return;
270  // Stop retriable passes
271  if (!changes || (pass >= LEDGER_RETRY_PASSES))
272  retry = false;
273  }
274 
275  // If there are any transactions left, we must have
276  // tried them in at least one final pass
277  assert(retries.empty() || !retry);
278 }
279 
280 //------------------------------------------------------------------------------
281 
282 // For debug logging
283 
286 
288 debugTostr(OrderedTxs const& set);
289 
291 debugTostr(SHAMap const& set);
292 
295 
296 } // namespace ripple
297 
298 #endif
ripple::Application
Definition: Application.h:97
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
std::string
STL class.
std::shared_ptr
STL class.
std::exception
STL class.
ripple::OpenLedger::current_
std::shared_ptr< OpenView const > current_
Definition: OpenLedger.h:56
ripple::CanonicalTXSet::erase
const_iterator erase(const_iterator const &it)
Definition: CanonicalTXSet.h:136
ripple::OpenLedger::operator=
OpenLedger & operator=(OpenLedger const &)=delete
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:30
ripple::OpenLedger::success
@ success
Definition: OpenLedger.h:191
std::function
ripple::OpenLedger::modify_mutex_
std::mutex modify_mutex_
Definition: OpenLedger.h:54
ripple::OpenLedger::retry
@ retry
Definition: OpenLedger.h:191
ripple::OpenLedger::accept
void accept(Application &app, Rules const &rules, std::shared_ptr< Ledger const > const &ledger, OrderedTxs const &locals, bool retriesFirst, OrderedTxs &retries, ApplyFlags flags, std::string const &suffix="", modify_type const &f={})
Accept a new ledger.
Definition: OpenLedger.cpp:71
ripple::CanonicalTXSet
Holds transactions which were deferred to the next pass of consensus.
Definition: CanonicalTXSet.h:37
ripple::CanonicalTXSet::begin
const_iterator begin() const
Definition: CanonicalTXSet.h:142
ripple::OpenLedger::failure
@ failure
Definition: OpenLedger.h:191
ripple::CachedSLEs
Caches SLEs by their digest.
Definition: CachedSLEs.h:32
ripple::OpenLedger::j_
const beast::Journal j_
Definition: OpenLedger.h:52
ripple::OpenLedger::OpenLedger
OpenLedger()=delete
ripple::SHAMap
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition: SHAMap.h:95
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:276
beast::Journal::error
Stream error() const
Definition: Journal.h:333
ripple::debugTxstr
std::string debugTxstr(std::shared_ptr< STTx const > const &tx)
Definition: OpenLedger.cpp:210
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::map
STL class.
ripple::CanonicalTXSet::insert
void insert(std::shared_ptr< STTx const > const &txn)
Definition: CanonicalTXSet.cpp:52
ripple::debugTostr
std::string debugTostr(OrderedTxs const &set)
Definition: OpenLedger.cpp:218
ripple::OpenLedger::empty
bool empty() const
Returns true if there are no transactions.
Definition: OpenLedger.cpp:43
ripple::CanonicalTXSet::end
const_iterator end() const
Definition: CanonicalTXSet.h:148
ripple::OpenLedger
Represents the open ledger.
Definition: OpenLedger.h:49
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:192
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::OpenLedger::cache_
CachedSLEs & cache_
Definition: OpenLedger.h:53
cassert
ripple::CanonicalTXSet::empty
bool empty() const
Definition: CanonicalTXSet.h:159
ripple::Rules
Rules controlling protocol behavior.
Definition: ReadView.h:131
mutex
ripple::OpenLedger::Result
Result
Definition: OpenLedger.h:191
ripple::OpenLedger::create
std::shared_ptr< OpenView > create(Rules const &rules, std::shared_ptr< Ledger const > const &ledger)
Definition: OpenLedger.cpp:167
ripple::OpenLedger::current_mutex_
std::mutex current_mutex_
Definition: OpenLedger.h:55
ripple::OpenLedger::apply_one
static Result apply_one(Application &app, OpenView &view, std::shared_ptr< STTx const > const &tx, bool retry, ApplyFlags flags, bool shouldRecover, beast::Journal j)
Definition: OpenLedger.cpp:178
ripple::OpenLedger::apply
static void apply(Application &app, OpenView &view, ReadView const &check, FwdRange const &txs, OrderedTxs &retries, ApplyFlags flags, std::map< uint256, bool > &shouldRecover, beast::Journal j)
Algorithm for applying transactions.
Definition: OpenLedger.h:211
ripple::OpenLedger::modify
bool modify(modify_type const &f)
Modify the open ledger.
Definition: OpenLedger.cpp:57