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  beast::Journal j);
189 
191 
193  create(Rules const& rules, std::shared_ptr<Ledger const> const& ledger);
194 
195  static Result
196  apply_one(
197  Application& app,
198  OpenView& view,
199  std::shared_ptr<STTx const> const& tx,
200  bool retry,
201  ApplyFlags flags,
202  beast::Journal j);
203 };
204 
205 //------------------------------------------------------------------------------
206 
207 template <class FwdRange>
208 void
210  Application& app,
211  OpenView& view,
212  ReadView const& check,
213  FwdRange const& txs,
214  OrderedTxs& retries,
215  ApplyFlags flags,
216  beast::Journal j)
217 {
218  for (auto iter = txs.begin(); iter != txs.end(); ++iter)
219  {
220  try
221  {
222  // Dereferencing the iterator can throw since it may be transformed.
223  auto const tx = *iter;
224  auto const txId = tx->getTransactionID();
225  if (check.txExists(txId))
226  continue;
227  auto const result = apply_one(app, view, tx, true, flags, j);
228  if (result == Result::retry)
229  retries.insert(tx);
230  }
231  catch (std::exception const& e)
232  {
233  JLOG(j.error())
234  << "OpenLedger::apply: Caught exception: " << e.what();
235  }
236  }
237  bool retry = true;
238  for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
239  {
240  int changes = 0;
241  auto iter = retries.begin();
242  while (iter != retries.end())
243  {
244  switch (apply_one(app, view, iter->second, retry, flags, j))
245  {
246  case Result::success:
247  ++changes;
248  [[fallthrough]];
249  case Result::failure:
250  iter = retries.erase(iter);
251  break;
252  case Result::retry:
253  ++iter;
254  }
255  }
256  // A non-retry pass made no changes
257  if (!changes && !retry)
258  return;
259  // Stop retriable passes
260  if (!changes || (pass >= LEDGER_RETRY_PASSES))
261  retry = false;
262  }
263 
264  // If there are any transactions left, we must have
265  // tried them in at least one final pass
266  assert(retries.empty() || !retry);
267 }
268 
269 //------------------------------------------------------------------------------
270 
271 // For debug logging
272 
275 
277 debugTostr(OrderedTxs const& set);
278 
280 debugTostr(SHAMap const& set);
281 
284 
285 } // namespace ripple
286 
287 #endif
ripple::Application
Definition: Application.h:115
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.
ripple::TaggedCache< uint256, SLE const >
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:137
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:29
ripple::OpenLedger::success
@ success
Definition: OpenLedger.h:190
std::function
ripple::OpenLedger::modify_mutex_
std::mutex modify_mutex_
Definition: OpenLedger.h:54
ripple::OpenLedger::retry
@ retry
Definition: OpenLedger.h:190
ripple::OpenLedger::apply
static void apply(Application &app, OpenView &view, ReadView const &check, FwdRange const &txs, OrderedTxs &retries, ApplyFlags flags, beast::Journal j)
Algorithm for applying transactions.
Definition: OpenLedger.h:209
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:38
ripple::CanonicalTXSet::begin
const_iterator begin() const
Definition: CanonicalTXSet.h:143
ripple::OpenLedger::failure
@ failure
Definition: OpenLedger.h:190
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:313
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:181
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
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:189
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:149
ripple::OpenLedger
Represents the open ledger.
Definition: OpenLedger.h:49
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::OpenLedger::apply_one
static Result apply_one(Application &app, OpenView &view, std::shared_ptr< STTx const > const &tx, bool retry, ApplyFlags flags, beast::Journal j)
Definition: OpenLedger.cpp:158
ripple::OpenLedger::cache_
CachedSLEs & cache_
Definition: OpenLedger.h:53
cassert
ripple::CanonicalTXSet::empty
bool empty() const
Definition: CanonicalTXSet.h:160
ripple::Rules
Rules controlling protocol behavior.
Definition: Rules.h:33
mutex
ripple::OpenLedger::Result
Result
Definition: OpenLedger.h:190
ripple::OpenLedger::create
std::shared_ptr< OpenView > create(Rules const &rules, std::shared_ptr< Ledger const > const &ledger)
Definition: OpenLedger.cpp:147
ripple::OpenLedger::current_mutex_
std::mutex current_mutex_
Definition: OpenLedger.h:55
ripple::OpenLedger::modify
bool modify(modify_type const &f)
Modify the open ledger.
Definition: OpenLedger.cpp:57
std::exception::what
T what(T... args)