rippled
nodestore/impl/Shard.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2017 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_NODESTORE_SHARD_H_INCLUDED
21 #define RIPPLE_NODESTORE_SHARD_H_INCLUDED
22 
23 #include <ripple/app/ledger/Ledger.h>
24 #include <ripple/app/rdb/RelationalDatabase.h>
25 #include <ripple/basics/BasicConfig.h>
26 #include <ripple/basics/KeyCache.h>
27 #include <ripple/basics/MathUtilities.h>
28 #include <ripple/basics/RangeSet.h>
29 #include <ripple/basics/ThreadSafetyAnalysis.h>
30 #include <ripple/core/DatabaseCon.h>
31 #include <ripple/nodestore/NodeObject.h>
32 #include <ripple/nodestore/Scheduler.h>
33 #include <ripple/nodestore/impl/DeterministicShard.h>
34 
35 #include <boost/filesystem.hpp>
36 #include <nudb/nudb.hpp>
37 
38 #include <atomic>
39 
40 namespace ripple {
41 namespace NodeStore {
42 
44 using NCache = KeyCache;
45 class DatabaseShard;
46 
47 /* A range of historical ledgers backed by a node store.
48  Shards are indexed and store `ledgersPerShard`.
49  Shard `i` stores ledgers starting with sequence: `1 + (i * ledgersPerShard)`
50  and ending with sequence: `(i + 1) * ledgersPerShard`.
51  Once a shard has all its ledgers, it is never written to again.
52 
53  Public functions can be called concurrently from any thread.
54 */
55 class Shard final
56 {
57 public:
59  Shard(Shard const&) = delete;
60 
62  Shard(Shard&&) = delete;
63 
64  // Copy assignment (disallowed)
65  Shard&
66  operator=(Shard const&) = delete;
67 
68  // Move assignment (disallowed)
69  Shard&
70  operator=(Shard&&) = delete;
71 
72  Shard(
73  Application& app,
74  DatabaseShard const& db,
76  boost::filesystem::path const& dir,
77  beast::Journal j);
78 
79  Shard(
80  Application& app,
81  DatabaseShard const& db,
83  beast::Journal j);
84 
85  ~Shard();
86 
92  [[nodiscard]] bool
93  init(Scheduler& scheduler, nudb::context& context);
94 
97  [[nodiscard]] bool
98  isOpen() const;
99 
104  bool
105  tryClose();
106 
109  void
110  stop() noexcept
111  {
112  stop_ = true;
113  }
114 
115  [[nodiscard]] std::optional<std::uint32_t>
116  prepare();
117 
118  [[nodiscard]] bool
119  storeNodeObject(std::shared_ptr<NodeObject> const& nodeObject);
120 
121  [[nodiscard]] std::shared_ptr<NodeObject>
122  fetchNodeObject(uint256 const& hash, FetchReport& fetchReport);
123 
131  {
132  std::uint64_t count{0}; // Number of storage calls
133  std::uint64_t size{0}; // Number of bytes stored
134  bool error{false};
135  };
136 
137  [[nodiscard]] StoreLedgerResult
138  storeLedger(
139  std::shared_ptr<Ledger const> const& srcLedger,
140  std::shared_ptr<Ledger const> const& next);
141 
142  [[nodiscard]] bool
144 
145  [[nodiscard]] bool
146  containsLedger(std::uint32_t ledgerSeq) const;
147 
148  [[nodiscard]] std::uint32_t
149  index() const noexcept
150  {
151  return index_;
152  }
153 
154  [[nodiscard]] boost::filesystem::path const&
155  getDir() const noexcept
156  {
157  return dir_;
158  }
159 
160  [[nodiscard]] std::chrono::steady_clock::time_point
161  getLastUse() const;
162 
167  getFileInfo() const;
168 
169  [[nodiscard]] ShardState
170  getState() const noexcept
171  {
172  return state_;
173  }
174 
178  [[nodiscard]] std::uint32_t
179  getPercentProgress() const noexcept
180  {
182  }
183 
184  [[nodiscard]] std::int32_t
185  getWriteLoad();
186 
189  [[nodiscard]] bool
190  isLegacy() const;
191 
200  [[nodiscard]] bool
201  finalize(bool writeSQLite, std::optional<uint256> const& referenceHash);
202 
205  void
206  removeOnDestroy() noexcept
207  {
208  removeOnDestroy_ = true;
209  }
210 
213  {
214  std::lock_guard lock(mutex_);
215  if (!acquireInfo_)
216  return "";
217 
218  return to_string(acquireInfo_->storedSeqs);
219  }
220 
226  template <typename... Args>
227  bool
228  callForLedgerSQL(std::function<bool(Args... args)> const& callback)
229  {
230  return callForSQL(callback, lgrSQLiteDB_->checkoutDb());
231  }
232 
238  template <typename... Args>
239  bool
240  callForTransactionSQL(std::function<bool(Args... args)> const& callback)
241  {
242  return callForSQL(callback, txSQLiteDB_->checkoutDb());
243  }
244 
245  // Current shard version
246  static constexpr std::uint32_t version{2};
247 
248  // The finalKey is a hard coded value of zero. It is used to store
249  // finalizing shard data to the backend. The data contains a version,
250  // last ledger's hash, and the first and last ledger sequences.
251  static uint256 const finalKey;
252 
253 private:
254  class Count final
255  {
256  public:
257  Count(Count const&) = delete;
258  Count&
259  operator=(Count const&) = delete;
260  Count&
261  operator=(Count&&) = delete;
262 
263  Count(Count&& other) noexcept : counter_(other.counter_)
264  {
265  other.counter_ = nullptr;
266  }
267 
268  explicit Count(std::atomic<std::uint32_t>* counter) noexcept
269  : counter_(counter)
270  {
271  if (counter_)
272  ++(*counter_);
273  }
274 
275  ~Count() noexcept
276  {
277  if (counter_)
278  --(*counter_);
279  }
280 
281  explicit operator bool() const noexcept
282  {
283  return counter_ != nullptr;
284  }
285 
286  private:
288  };
289 
290  struct AcquireInfo
291  {
292  // SQLite database to track information about what has been acquired
294 
295  // Tracks the sequences of ledgers acquired and stored in the backend
297  };
298 
303 
304  // Shard Index
306 
307  // First ledger sequence in the shard
309 
310  // Last ledger sequence in the shard
312 
313  // The maximum number of ledgers the shard can store
314  // The earliest shard may store fewer ledgers than subsequent shards
316 
317  // Path to database files
318  boost::filesystem::path const dir_;
319 
320  // Storage space utilized by the shard
321  GUARDED_BY(mutex_) std::uint64_t fileSz_{0};
322 
323  // Number of file descriptors required by the shard
324  GUARDED_BY(mutex_) std::uint32_t fdRequired_{0};
325 
326  // NuDB key/value store for node objects
328 
330 
331  // Ledger SQLite database used for indexes
333 
334  // Transaction SQLite database used for indexes
336 
337  // Tracking information used only when acquiring a shard from the network.
338  // If the shard is finalized, this member will be null.
340  ;
341 
342  // Older shard without an acquire database or final key
343  // Eventually there will be no need for this and should be removed
344  GUARDED_BY(mutex_) bool legacy_{false};
345 
346  // Determines if the shard needs to stop processing for shutdown
348 
349  // Determines if the shard busy with replacing by deterministic one
351 
352  // State of the shard
354 
355  // Number of ledgers processed for the current shard state
357 
358  // Determines if the shard directory should be removed in the destructor
360 
361  // The time of the last access of a shard with a finalized state
362  std::chrono::steady_clock::time_point lastAccess_ GUARDED_BY(mutex_);
363  ;
364 
365  // Open shard databases
366  [[nodiscard]] bool
367  open(std::lock_guard<std::mutex> const& lock) REQUIRES(mutex_);
368 
369  // Open/Create SQLite databases
370  // Lock over mutex_ required
371  [[nodiscard]] bool
373 
374  // Write SQLite entries for this ledger
375  [[nodiscard]] bool
377 
378  // Set storage and file descriptor usage stats
379  // Lock over mutex_ required
380  void
382 
383  // Verify this ledger by walking its SHAMaps and verifying its Merkle trees
384  // Every node object verified will be stored in the deterministic shard
385  [[nodiscard]] bool
386  verifyLedger(
387  std::shared_ptr<Ledger const> const& ledger,
388  std::shared_ptr<Ledger const> const& next,
389  std::shared_ptr<DeterministicShard> const& dShard) const;
390 
391  // Fetches from backend and log errors based on status codes
392  [[nodiscard]] std::shared_ptr<NodeObject>
393  verifyFetch(uint256 const& hash) const;
394 
395  // Open databases if they are closed
396  [[nodiscard]] Shard::Count
398 
399  // Invoke a callback on the supplied session parameter
400  template <typename... Args>
401  bool
403  std::function<bool(Args... args)> const& callback,
404  LockedSociSession&& db)
405  {
406  auto const scopedCount{makeBackendCount()};
407  if (!scopedCount)
408  return false;
409 
410  return doCallForSQL(callback, std::move(db));
411  }
412 
413  // Invoke a callback that accepts a SQLite session parameter
414  bool
415  doCallForSQL(
416  std::function<bool(soci::session& session)> const& callback,
417  LockedSociSession&& db);
418 
419  // Invoke a callback that accepts a SQLite session and the
420  // shard index as parameters
421  bool
422  doCallForSQL(
424  bool(soci::session& session, std::uint32_t shardIndex)> const&
425  callback,
426  LockedSociSession&& db);
427 };
428 
429 } // namespace NodeStore
430 } // namespace ripple
431 
432 #endif
ripple::NodeStore::Shard::dir_
const boost::filesystem::path dir_
Definition: nodestore/impl/Shard.h:318
ripple::Application
Definition: Application.h:115
ripple::NodeStore::Shard::mutex_
std::mutex mutex_
Definition: nodestore/impl/Shard.h:301
ripple::NodeStore::Shard::getPercentProgress
std::uint32_t getPercentProgress() const noexcept
Returns a percent signifying how complete the current state of the shard is.
Definition: nodestore/impl/Shard.h:179
std::string
STL class.
std::shared_ptr< NodeObject >
ripple::NodeStore::Shard::removeOnDestroy_
std::atomic< bool > removeOnDestroy_
Definition: nodestore/impl/Shard.h:359
ripple::NodeStore::Shard::removeOnDestroy
void removeOnDestroy() noexcept
Enables removal of the shard directory on destruction.
Definition: nodestore/impl/Shard.h:206
ripple::TaggedCache
Map/cache combination.
Definition: Application.h:64
ripple::NodeStore::Shard::storeLedger
StoreLedgerResult storeLedger(std::shared_ptr< Ledger const > const &srcLedger, std::shared_ptr< Ledger const > const &next)
Definition: nodestore/impl/Shard.cpp:290
ripple::NodeStore::Shard::prepare
std::optional< std::uint32_t > prepare()
Definition: nodestore/impl/Shard.cpp:184
std::pair
ripple::NodeStore::Shard::open
bool open(std::lock_guard< std::mutex > const &lock) REQUIRES(mutex_)
Definition: nodestore/impl/Shard.cpp:831
ripple::NodeStore::Shard::Count::~Count
~Count() noexcept
Definition: nodestore/impl/Shard.h:275
ripple::NodeStore::Shard::callForLedgerSQL
bool callForLedgerSQL(std::function< bool(Args... args)> const &callback)
Invoke a callback on the ledger SQLite db.
Definition: nodestore/impl/Shard.h:228
ripple::NodeStore::Shard::Shard
Shard(Shard const &)=delete
Copy constructor (disallowed)
ripple::NodeStore::Shard::Count::Count
Count(std::atomic< std::uint32_t > *counter) noexcept
Definition: nodestore/impl/Shard.h:268
ripple::NodeStore::Shard::getStoredSeqs
std::string getStoredSeqs()
Definition: nodestore/impl/Shard.h:212
ripple::NodeStore::Shard::getFileInfo
std::pair< std::uint64_t, std::uint32_t > getFileInfo() const
Returns a pair where the first item describes the storage space utilized and the second item is the n...
Definition: nodestore/impl/Shard.cpp:532
std::lock_guard
STL class.
ripple::NodeStore::Shard::Count::Count
Count(Count &&other) noexcept
Definition: nodestore/impl/Shard.h:263
ripple::NodeStore::Shard::operator=
Shard & operator=(Shard const &)=delete
ripple::NodeStore::FetchReport
Contains information about a fetch operation.
Definition: ripple/nodestore/Scheduler.h:32
ripple::NodeStore::Shard::isOpen
bool isOpen() const
Returns true if the database are open.
Definition: nodestore/impl/Shard.cpp:127
std::function
ripple::NodeStore::Shard::finalKey
static const uint256 finalKey
Definition: nodestore/impl/Shard.h:251
ripple::NodeStore::Shard::lastSeq_
const std::uint32_t lastSeq_
Definition: nodestore/impl/Shard.h:311
ripple::ShardState
ShardState
Shard states.
Definition: nodestore/Types.h:60
ripple::NodeStore::Shard::storedMutex_
std::mutex storedMutex_
Definition: nodestore/impl/Shard.h:302
ripple::NodeStore::Shard::GUARDED_BY
GUARDED_BY(mutex_) std GUARDED_BY(mutex_) std std::unique_ptr< Backend > backend_ GUARDED_BY(mutex_)
ripple::NodeStore::Shard::AcquireInfo
Definition: nodestore/impl/Shard.h:290
ripple::NodeStore::Shard::AcquireInfo::storedSeqs
RangeSet< std::uint32_t > storedSeqs
Definition: nodestore/impl/Shard.h:296
ripple::NodeStore::Shard::verifyFetch
std::shared_ptr< NodeObject > verifyFetch(uint256 const &hash) const
Definition: nodestore/impl/Shard.cpp:1192
ripple::NodeStore::Shard::tryClose
bool tryClose()
Try to close databases if not in use.
Definition: nodestore/impl/Shard.cpp:140
ripple::NodeStore::Shard::StoreLedgerResult::size
std::uint64_t size
Definition: nodestore/impl/Shard.h:133
ripple::NodeStore::Shard::isLegacy
bool isLegacy() const
Returns true if shard is older, without final key data.
Definition: nodestore/impl/Shard.cpp:549
ripple::NodeStore::Shard::version
static constexpr std::uint32_t version
Definition: nodestore/impl/Shard.h:246
ripple::NodeStore::Shard::storeSQLite
bool storeSQLite(std::shared_ptr< Ledger const > const &ledger)
Definition: nodestore/impl/Shard.cpp:1034
ripple::KeyCache
TaggedCache< uint256, int, true > KeyCache
Definition: KeyCache.h:28
ripple::base_uint< 256 >
ripple::NodeStore::Shard::j_
const beast::Journal j_
Definition: nodestore/impl/Shard.h:300
ripple::NodeStore::Shard::containsLedger
bool containsLedger(std::uint32_t ledgerSeq) const
Definition: nodestore/impl/Shard.cpp:507
ripple::NodeStore::Shard::StoreLedgerResult::error
bool error
Definition: nodestore/impl/Shard.h:134
ripple::NodeStore::Shard::storeNodeObject
bool storeNodeObject(std::shared_ptr< NodeObject > const &nodeObject)
Definition: nodestore/impl/Shard.cpp:207
ripple::NodeStore::Shard::stop
void stop() noexcept
Notify shard to prepare for shutdown.
Definition: nodestore/impl/Shard.h:110
ripple::NodeStore::Shard::initSQLite
bool initSQLite(std::lock_guard< std::mutex > const &) REQUIRES(mutex_)
Definition: nodestore/impl/Shard.cpp:958
ripple::NodeStore::Shard::fetchNodeObject
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, FetchReport &fetchReport)
Definition: nodestore/impl/Shard.cpp:241
ripple::NodeStore::Shard::setFileStats
void setFileStats(std::lock_guard< std::mutex > const &) REQUIRES(mutex_)
Definition: nodestore/impl/Shard.cpp:1081
ripple::NodeStore::DatabaseShard
A collection of historical shards.
Definition: DatabaseShard.h:37
ripple::calculatePercent
constexpr std::size_t calculatePercent(std::size_t count, std::size_t total)
Calculate one number divided by another number in percentage.
Definition: MathUtilities.h:44
ripple::NodeStore::Shard::firstSeq_
const std::uint32_t firstSeq_
Definition: nodestore/impl/Shard.h:308
ripple::NodeStore::Shard::AcquireInfo::SQLiteDB
std::unique_ptr< DatabaseCon > SQLiteDB
Definition: nodestore/impl/Shard.h:293
ripple::NodeStore::Shard::maxLedgers_
const std::uint32_t maxLedgers_
Definition: nodestore/impl/Shard.h:315
ripple::NodeStore::Shard::~Shard
~Shard()
Definition: nodestore/impl/Shard.cpp:60
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::NodeStore::Shard::verifyLedger
bool verifyLedger(std::shared_ptr< Ledger const > const &ledger, std::shared_ptr< Ledger const > const &next, std::shared_ptr< DeterministicShard > const &dShard) const
Definition: nodestore/impl/Shard.cpp:1106
ripple::NodeStore::Shard::GUARDED_BY
GUARDED_BY(mutex_) bool legacy_
Definition: nodestore/impl/Shard.h:344
std::uint32_t
atomic
ripple::NodeStore::Scheduler
Scheduling for asynchronous backend activity.
Definition: ripple/nodestore/Scheduler.h:60
ripple::NodeStore::Shard::StoreLedgerResult
Store a ledger.
Definition: nodestore/impl/Shard.h:130
ripple::NodeStore::Shard::Count::Count
Count(Count const &)=delete
ripple::NodeStore::Shard::index
std::uint32_t index() const noexcept
Definition: nodestore/impl/Shard.h:149
ripple::NodeStore::Shard::app_
Application & app_
Definition: nodestore/impl/Shard.h:299
ripple::NodeStore::Shard::callForSQL
bool callForSQL(std::function< bool(Args... args)> const &callback, LockedSociSession &&db)
Definition: nodestore/impl/Shard.h:402
ripple::NodeStore::Shard::progress_
std::atomic< std::uint32_t > progress_
Definition: nodestore/impl/Shard.h:356
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LockedSociSession
Definition: DatabaseCon.h:37
ripple::NodeStore::Shard::makeBackendCount
Shard::Count makeBackendCount()
Definition: nodestore/impl/Shard.cpp:1231
ripple::NodeStore::Shard::callForTransactionSQL
bool callForTransactionSQL(std::function< bool(Args... args)> const &callback)
Invoke a callback on the transaction SQLite db.
Definition: nodestore/impl/Shard.h:240
ripple::ShardState::acquire
@ acquire
ripple::NodeStore::Shard::StoreLedgerResult::count
std::uint64_t count
Definition: nodestore/impl/Shard.h:132
ripple::NodeStore::Shard::getDir
boost::filesystem::path const & getDir() const noexcept
Definition: nodestore/impl/Shard.h:155
ripple::NodeStore::Shard::Count::operator=
Count & operator=(Count const &)=delete
ripple::NodeStore::Shard::state_
std::atomic< ShardState > state_
Definition: nodestore/impl/Shard.h:353
ripple::NodeStore::Shard::doCallForSQL
bool doCallForSQL(std::function< bool(soci::session &session)> const &callback, LockedSociSession &&db)
Definition: nodestore/impl/Shard.cpp:1254
std::optional< std::uint32_t >
std::mutex
STL class.
ripple::NodeStore::Shard::init
bool init(Scheduler &scheduler, nudb::context &context)
Initialize shard.
Definition: nodestore/impl/Shard.cpp:95
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::RangeSet
boost::icl::interval_set< T, std::less, ClosedInterval< T > > RangeSet
A set of closed intervals over the domain T.
Definition: RangeSet.h:69
ripple::NodeStore::Shard::finalize
bool finalize(bool writeSQLite, std::optional< uint256 > const &referenceHash)
Finalize shard by walking its ledgers, verifying each Merkle tree and creating a deterministic backen...
Definition: nodestore/impl/Shard.cpp:556
ripple::NodeStore::Shard::setLedgerStored
bool setLedgerStored(std::shared_ptr< Ledger const > const &ledger)
Definition: nodestore/impl/Shard.cpp:416
ripple::NodeStore::Shard::getState
ShardState getState() const noexcept
Definition: nodestore/impl/Shard.h:170
ripple::NodeStore::Shard
Definition: nodestore/impl/Shard.h:55
ripple::NodeStore::Shard::Count
Definition: nodestore/impl/Shard.h:254
ripple::NodeStore::Shard::index_
const std::uint32_t index_
Definition: nodestore/impl/Shard.h:305
std::unique_ptr
STL class.
ripple::NodeStore::Shard::stop_
std::atomic< bool > stop_
Definition: nodestore/impl/Shard.h:347
ripple::NodeStore::Shard::Count::counter_
std::atomic< std::uint32_t > * counter_
Definition: nodestore/impl/Shard.h:287
ripple::NodeStore::Shard::backendCount_
std::atomic< std::uint32_t > backendCount_
Definition: nodestore/impl/Shard.h:329
ripple::NodeStore::Shard::getLastUse
std::chrono::steady_clock::time_point getLastUse() const
Definition: nodestore/impl/Shard.cpp:525
ripple::NodeStore::Shard::getWriteLoad
std::int32_t getWriteLoad()
Definition: nodestore/impl/Shard.cpp:539
ripple::NodeStore::Shard::busy_
std::atomic< bool > busy_
Definition: nodestore/impl/Shard.h:350