rippled
DatabaseShardImp.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_DATABASESHARDIMP_H_INCLUDED
21 #define RIPPLE_NODESTORE_DATABASESHARDIMP_H_INCLUDED
22 
23 #include <ripple/nodestore/DatabaseShard.h>
24 #include <ripple/nodestore/impl/Shard.h>
25 #include <ripple/nodestore/impl/TaskQueue.h>
26 
27 #include <boost/asio/basic_waitable_timer.hpp>
28 
29 namespace ripple {
30 namespace NodeStore {
31 
33 {
34 public:
35  DatabaseShardImp() = delete;
36  DatabaseShardImp(DatabaseShardImp const&) = delete;
39  operator=(DatabaseShardImp const&) = delete;
41  operator=(DatabaseShardImp&&) = delete;
42 
44  Application& app,
45  Stoppable& parent,
46  std::string const& name,
47  Scheduler& scheduler,
48  int readThreads,
49  beast::Journal j);
50 
51  ~DatabaseShardImp() override;
52 
53  bool
54  init() override;
55 
56  boost::optional<std::uint32_t>
57  prepareLedger(std::uint32_t validLedgerSeq) override;
58 
59  bool
60  prepareShard(std::uint32_t shardIndex) override;
61 
62  void
63  removePreShard(std::uint32_t shardIndex) override;
64 
66  getPreShards() override;
67 
68  bool
69  importShard(std::uint32_t shardIndex, boost::filesystem::path const& srcDir)
70  override;
71 
73  fetchLedger(uint256 const& hash, std::uint32_t seq) override;
74 
75  void
76  setStored(std::shared_ptr<Ledger const> const& ledger) override;
77 
79  getCompleteShards() override;
80 
81  void
82  validate() override;
83 
85  ledgersPerShard() const override
86  {
87  return ledgersPerShard_;
88  }
89 
91  earliestShardIndex() const override
92  {
93  return earliestShardIndex_;
94  }
95 
97  seqToShardIndex(std::uint32_t seq) const override
98  {
99  assert(seq >= earliestLedgerSeq());
101  }
102 
104  firstLedgerSeq(std::uint32_t shardIndex) const override
105  {
106  assert(shardIndex >= earliestShardIndex_);
107  if (shardIndex <= earliestShardIndex_)
108  return earliestLedgerSeq();
109  return 1 + (shardIndex * ledgersPerShard_);
110  }
111 
113  lastLedgerSeq(std::uint32_t shardIndex) const override
114  {
115  assert(shardIndex >= earliestShardIndex_);
116  return (shardIndex + 1) * ledgersPerShard_;
117  }
118 
119  boost::filesystem::path const&
120  getRootDir() const override
121  {
122  return dir_;
123  }
124 
126  getName() const override
127  {
128  return backendName_;
129  }
130 
131  void
132  onStop() override;
133 
138  void
139  import(Database& source) override;
140 
142  getWriteLoad() const override;
143 
144  void
145  store(
146  NodeObjectType type,
147  Blob&& data,
148  uint256 const& hash,
149  std::uint32_t seq) override;
150 
152  fetch(uint256 const& hash, std::uint32_t seq) override;
153 
154  bool
155  asyncFetch(
156  uint256 const& hash,
157  std::uint32_t seq,
158  std::shared_ptr<NodeObject>& object) override;
159 
160  bool
161  storeLedger(std::shared_ptr<Ledger const> const& srcLedger) override;
162 
163  int
165 
166  float
167  getCacheHitRate() override;
168 
169  void
170  tune(int size, std::chrono::seconds age) override{};
171 
172  void
173  sweep() override;
174 
175 private:
176  struct ShardInfo
177  {
178  enum class State {
179  none,
180  final, // Immutable, complete and validated
181  acquire, // Being acquired
182  import, // Being imported
183  finalize // Being finalized
184  };
185 
186  ShardInfo() = default;
188  : shard(std::move(shard_)), state(state_)
189  {
190  }
191 
194  };
195 
196  enum class PathDesignation : uint8_t {
197  none, // No path specified
198  historical // Needs a historical path
199  };
200 
204  bool init_{false};
205 
206  // The context shared with all shard backend databases
208 
209  // Queue of background tasks to be performed
211 
212  // Shards held by this server
214 
215  // Shard index being acquired from the peer network
217 
218  // The shard store root directory
219  boost::filesystem::path dir_;
220 
221  // If new shards can be stored
222  bool canAdd_{true};
223 
224  // Complete shard indexes
226 
227  // The name associated with the backend used with the shard store
229 
230  // Maximum number of historical shards to store.
232 
233  // Contains historical shard paths
235 
236  // Storage space utilized by the shard store (in bytes)
238 
239  // Each shard stores 16384 ledgers. The earliest shard may store
240  // less if the earliest ledger sequence truncates its beginning.
241  // The value should only be altered for unit tests.
243 
244  // The earliest shard index
246 
247  // Average storage space required by a shard (in bytes)
249 
250  // File name used to mark shards being imported from node store
251  static constexpr auto importMarker_ = "import";
252 
253  // latestShardIndex_ and secondLatestShardIndex hold the indexes
254  // of the shards most recently confirmed by the network. These
255  // values are not updated in real time and are modified only
256  // when adding shards to the database, in order to determine where
257  // pending shards will be stored on the filesystem. A value of
258  // boost::none indicates that the corresponding shard is not held
259  // by the database.
260  boost::optional<std::uint32_t> latestShardIndex_;
261  boost::optional<std::uint32_t> secondLatestShardIndex_;
262 
263  // Initialize settings from the configuration file
264  // Lock must be held
265  bool
267 
269  fetchFrom(uint256 const& hash, std::uint32_t seq) override;
270 
271  void
273  {
274  Throw<std::runtime_error>("Shard store import not supported");
275  }
276 
277  // Randomly select a shard index not stored
278  // Lock must be held
279  boost::optional<std::uint32_t>
281  std::uint32_t validLedgerSeq,
283 
284 private:
285  // Queue a task to finalize a shard by validating its databases
286  // Lock must be held
287  void
289  ShardInfo& shardInfo,
290  bool writeSQLite,
292  boost::optional<uint256> const& expectedHash);
293 
294  // Set storage and file descriptor usage stats
295  // Lock must NOT be held
296  void
297  setFileStats();
298 
299  // Update status string
300  // Lock must be held
301  void
303 
305  getCache(std::uint32_t seq);
306 
307  // Returns true if the filesystem has enough storage
308  // available to hold the specified number of shards.
309  // The value of pathDesignation determines whether
310  // the shard(s) in question are historical and thus
311  // meant to be stored at a path designated for historical
312  // shards.
313  bool
315  std::uint32_t numShards,
316  PathDesignation pathDesignation,
317  std::lock_guard<std::mutex> const&) const;
318 
319  bool
321  std::shared_ptr<Shard>& shard,
322  std::shared_ptr<Ledger const> const& ledger);
323 
324  void
326 
327  // Returns the index that represents the logical
328  // partition between historical and recent shards
331 
334 
335  // Shifts the recent and second most recent (by index)
336  // shards as new shards become available on the network.
337  // Older shards are moved to a historical shard path.
338  void
340 
341  // Checks whether the shard can be stored. If
342  // the new shard can't be stored, returns
343  // boost::none. Otherwise returns an enum
344  // indicating whether the new shard should be
345  // placed in a separate directory for historical
346  // shards.
347  boost::optional<PathDesignation>
349  std::uint32_t shardIndex,
351  std::lock_guard<std::mutex> const& lock);
352 
353  boost::filesystem::path
355 
356  bool
357  checkHistoricalPaths() const;
358 };
359 
360 } // namespace NodeStore
361 } // namespace ripple
362 
363 #endif
ripple::NodeStore::DatabaseShardImp::ShardInfo::State
State
Definition: DatabaseShardImp.h:178
ripple::Application
Definition: Application.h:97
ripple::NodeStore::DatabaseShardImp::earliestShardIndex_
std::uint32_t earliestShardIndex_
Definition: DatabaseShardImp.h:245
ripple::NodeStore::DatabaseShardImp::ledgersPerShard_
std::uint32_t ledgersPerShard_
Definition: DatabaseShardImp.h:242
ripple::NodeStore::DatabaseShardImp::finalizeShard
void finalizeShard(ShardInfo &shardInfo, bool writeSQLite, std::lock_guard< std::mutex > &, boost::optional< uint256 > const &expectedHash)
Definition: DatabaseShardImp.cpp:1286
ripple::NodeStore::DatabaseShardImp::lastLedgerSeq
std::uint32_t lastLedgerSeq(std::uint32_t shardIndex) const override
Calculates the last ledger sequence for a given shard index.
Definition: DatabaseShardImp.h:113
ripple::NodeStore::DatabaseShardImp::for_each
void for_each(std::function< void(std::shared_ptr< NodeObject >)> f) override
Visit every object in the database This is usually called during import.
Definition: DatabaseShardImp.h:272
ripple::NodeStore::DatabaseShardImp::earliestShardIndex
std::uint32_t earliestShardIndex() const override
Definition: DatabaseShardImp.h:91
ripple::NodeStore::DatabaseShardImp::ShardInfo::ShardInfo
ShardInfo(std::shared_ptr< Shard > shard_, State state_)
Definition: DatabaseShardImp.h:187
ripple::NodeStore::DatabaseShardImp::mutex_
std::mutex mutex_
Definition: DatabaseShardImp.h:203
ripple::NodeStore::DatabaseShardImp::prepareLedger
boost::optional< std::uint32_t > prepareLedger(std::uint32_t validLedgerSeq) override
Prepare to store a new ledger in the shard being acquired.
Definition: DatabaseShardImp.cpp:238
ripple::NodeStore::DatabaseShardImp::app_
Application & app_
Definition: DatabaseShardImp.h:201
ripple::NodeStore::DatabaseShardImp::storeLedger
bool storeLedger(std::shared_ptr< Ledger const > const &srcLedger) override
Copies a ledger stored in a different database to this one.
Definition: DatabaseShardImp.cpp:1010
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:53
std::string
STL class.
ripple::NodeStore::DatabaseShardImp::fetch
std::shared_ptr< NodeObject > fetch(uint256 const &hash, std::uint32_t seq) override
Fetch an object.
Definition: DatabaseShardImp.cpp:982
std::shared_ptr< Ledger >
ripple::NodeStore::DatabaseShardImp::seqToShardIndex
std::uint32_t seqToShardIndex(std::uint32_t seq) const override
Calculates the shard index for a given ledger sequence.
Definition: DatabaseShardImp.h:97
ripple::NodeStore::DatabaseShardImp::PathDesignation
PathDesignation
Definition: DatabaseShardImp.h:196
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::none
@ none
ripple::NodeStore::DatabaseShardImp::getName
std::string getName() const override
Retrieve the name associated with this backend.
Definition: DatabaseShardImp.h:126
std::pair
ripple::NodeStore::DatabaseShardImp::getCache
std::pair< std::shared_ptr< PCache >, std::shared_ptr< NCache > > getCache(std::uint32_t seq)
Definition: DatabaseShardImp.cpp:1460
ripple::NodeStore::DatabaseShardImp::removePreShard
void removePreShard(std::uint32_t shardIndex) override
Remove a previously prepared shard index for import.
Definition: DatabaseShardImp.cpp:366
ripple::NodeStore::DatabaseShardImp::fileSz_
std::uint64_t fileSz_
Definition: DatabaseShardImp.h:237
std::vector< unsigned char >
ripple::NodeObjectType
NodeObjectType
The types of node objects.
Definition: NodeObject.h:32
ripple::NodeStore::DatabaseShardImp
Definition: DatabaseShardImp.h:32
std::chrono::seconds
ripple::NodeStore::DatabaseShardImp::taskQueue_
std::unique_ptr< TaskQueue > taskQueue_
Definition: DatabaseShardImp.h:210
ripple::NodeStore::DatabaseShardImp::ShardInfo::state
State state
Definition: DatabaseShardImp.h:193
ripple::NodeStore::DatabaseShardImp::setStored
void setStored(std::shared_ptr< Ledger const > const &ledger) override
Notifies the database that the given ledger has been fully acquired and stored.
Definition: DatabaseShardImp.cpp:590
ripple::NodeStore::DatabaseShardImp::secondLatestShardIndex_
boost::optional< std::uint32_t > secondLatestShardIndex_
Definition: DatabaseShardImp.h:261
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::acquire
@ acquire
ripple::NodeStore::DatabaseShardImp::prepareShard
bool prepareShard(std::uint32_t shardIndex) override
Prepare a shard index to be imported into the database.
Definition: DatabaseShardImp.cpp:306
std::lock_guard
STL class.
ripple::NodeStore::DatabaseShardImp::tune
void tune(int size, std::chrono::seconds age) override
Set the maximum number of entries and maximum cache age for both caches.
Definition: DatabaseShardImp.h:170
ripple::NodeStore::DatabaseShardImp::asyncFetch
bool asyncFetch(uint256 const &hash, std::uint32_t seq, std::shared_ptr< NodeObject > &object) override
Fetch an object without waiting.
Definition: DatabaseShardImp.cpp:991
std::function
ripple::NodeStore::DatabaseShardImp::operator=
DatabaseShardImp & operator=(DatabaseShardImp const &)=delete
ripple::NodeStore::DatabaseShardImp::sweep
void sweep() override
Remove expired entries from the positive and negative caches.
Definition: DatabaseShardImp.cpp:1094
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::finalize
@ finalize
ripple::NodeStore::DatabaseShardImp::PathDesignation::historical
@ historical
ripple::NodeStore::DatabaseShardImp::getDesiredAsyncReadCount
int getDesiredAsyncReadCount(std::uint32_t seq) override
Get the maximum number of async reads the node store prefers.
Definition: DatabaseShardImp.cpp:1055
ripple::NodeStore::DatabaseShardImp::firstLedgerSeq
std::uint32_t firstLedgerSeq(std::uint32_t shardIndex) const override
Calculates the first ledger sequence for a given shard index.
Definition: DatabaseShardImp.h:104
ripple::NodeStore::DatabaseShardImp::getCacheHitRate
float getCacheHitRate() override
Get the positive cache hits to total attempts ratio.
Definition: DatabaseShardImp.cpp:1077
ripple::NodeStore::DatabaseShardImp::avgShardFileSz_
std::uint64_t avgShardFileSz_
Definition: DatabaseShardImp.h:248
ripple::base_uint< 256 >
ripple::NodeStore::DatabaseShardImp::status_
std::string status_
Definition: DatabaseShardImp.h:225
ripple::NodeStore::DatabaseShardImp::fetchFrom
std::shared_ptr< NodeObject > fetchFrom(uint256 const &hash, std::uint32_t seq) override
Definition: DatabaseShardImp.cpp:1205
ripple::NodeStore::DatabaseShardImp::getPreShards
std::string getPreShards() override
Get shard indexes being imported.
Definition: DatabaseShardImp.cpp:379
ripple::NodeStore::DatabaseShardImp::getWriteLoad
std::int32_t getWriteLoad() const override
Retrieve the estimated number of pending write operations.
Definition: DatabaseShardImp.cpp:925
ripple::NodeStore::DatabaseShardImp::shardBoundaryIndex
std::uint32_t shardBoundaryIndex(std::lock_guard< std::mutex > const &) const
Definition: DatabaseShardImp.cpp:1603
ripple::Stoppable
Provides an interface for starting and stopping.
Definition: Stoppable.h:200
ripple::NodeStore::DatabaseShardImp::ShardInfo::shard
std::shared_ptr< Shard > shard
Definition: DatabaseShardImp.h:192
ripple::NodeStore::DatabaseShardImp::chooseHistoricalPath
boost::filesystem::path chooseHistoricalPath(std::lock_guard< std::mutex > const &) const
Definition: DatabaseShardImp.cpp:1826
ripple::NodeStore::DatabaseShardImp::initConfig
bool initConfig(std::lock_guard< std::mutex > &)
Definition: DatabaseShardImp.cpp:1117
ripple::NodeStore::DatabaseShardImp::sufficientStorage
bool sufficientStorage(std::uint32_t numShards, PathDesignation pathDesignation, std::lock_guard< std::mutex > const &) const
Definition: DatabaseShardImp.cpp:1485
ripple::NodeStore::DatabaseShardImp::init_
bool init_
Definition: DatabaseShardImp.h:204
ripple::NodeStore::DatabaseShardImp::getCompleteShards
std::string getCompleteShards() override
Query which complete shards are stored.
Definition: DatabaseShardImp.cpp:645
ripple::NodeStore::DatabaseShardImp::ledgersPerShard
std::uint32_t ledgersPerShard() const override
Definition: DatabaseShardImp.h:85
ripple::NodeStore::DatabaseShardImp::shards_
std::map< std::uint32_t, ShardInfo > shards_
Definition: DatabaseShardImp.h:213
ripple::NodeStore::DatabaseShardImp::~DatabaseShardImp
~DatabaseShardImp() override
Definition: DatabaseShardImp.cpp:64
ripple::NodeStore::DatabaseShardImp::dir_
boost::filesystem::path dir_
Definition: DatabaseShardImp.h:219
ripple::NodeStore::DatabaseShardImp::updateStatus
void updateStatus(std::lock_guard< std::mutex > &)
Definition: DatabaseShardImp.cpp:1445
ripple::NodeStore::seqToShardIndex
constexpr std::uint32_t seqToShardIndex(std::uint32_t seq, std::uint32_t ledgersPerShard=DatabaseShard::ledgersPerShardDefault)
Definition: DatabaseShard.h:190
ripple::NodeStore::DatabaseShardImp::removeFailedShard
void removeFailedShard(std::shared_ptr< Shard > &shard)
Definition: DatabaseShardImp.cpp:1576
ripple::NodeStore::DatabaseShard
A collection of historical shards.
Definition: DatabaseShard.h:37
ripple::NodeStore::DatabaseShardImp::importShard
bool importShard(std::uint32_t shardIndex, boost::filesystem::path const &srcDir) override
Import a shard into the shard database.
Definition: DatabaseShardImp.cpp:398
ripple::NodeStore::DatabaseShardImp::PathDesignation::none
@ none
ripple::NodeStore::DatabaseShardImp::checkHistoricalPaths
bool checkHistoricalPaths() const
Definition: DatabaseShardImp.cpp:1859
ripple::NodeStore::DatabaseShardImp::latestShardIndex_
boost::optional< std::uint32_t > latestShardIndex_
Definition: DatabaseShardImp.h:260
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::NodeStore::Database::earliestLedgerSeq
std::uint32_t earliestLedgerSeq() const
Definition: Database.h:236
ripple::NodeStore::DatabaseShardImp::setFileStats
void setFileStats()
Definition: DatabaseShardImp.cpp:1394
ripple::NodeStore::DatabaseShardImp::acquireIndex_
std::uint32_t acquireIndex_
Definition: DatabaseShardImp.h:216
std::map
STL class.
ripple::NodeStore::Scheduler
Scheduling for asynchronous backend activity.
Definition: ripple/nodestore/Scheduler.h:57
ripple::NodeStore::DatabaseShardImp::findAcquireIndex
boost::optional< std::uint32_t > findAcquireIndex(std::uint32_t validLedgerSeq, std::lock_guard< std::mutex > &)
Definition: DatabaseShardImp.cpp:1226
ripple::NodeStore::DatabaseShardImp::ShardInfo::ShardInfo
ShardInfo()=default
ripple::NodeStore::DatabaseShardImp::init
bool init() override
Initialize the database.
Definition: DatabaseShardImp.cpp:70
ripple::NodeStore::DatabaseShardImp::store
void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq) override
Store the object.
Definition: DatabaseShardImp.cpp:942
ripple::NodeStore::DatabaseShardImp::historicalPaths_
std::vector< boost::filesystem::path > historicalPaths_
Definition: DatabaseShardImp.h:234
ripple::NodeStore::DatabaseShardImp::getRootDir
boost::filesystem::path const & getRootDir() const override
Returns the root database directory.
Definition: DatabaseShardImp.h:120
ripple::NodeStore::DatabaseShardImp::parent_
Stoppable & parent_
Definition: DatabaseShardImp.h:202
ripple::NodeStore::DatabaseShardImp::importMarker_
static constexpr auto importMarker_
Definition: DatabaseShardImp.h:251
ripple::NodeStore::DatabaseShard::ledgersPerShardDefault
static constexpr std::uint32_t ledgersPerShardDefault
The number of ledgers in a shard.
Definition: DatabaseShard.h:186
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NodeStore::DatabaseShardImp::maxHistoricalShards_
std::uint32_t maxHistoricalShards_
Definition: DatabaseShardImp.h:231
ripple::NodeStore::DatabaseShardImp::fetchLedger
std::shared_ptr< Ledger > fetchLedger(uint256 const &hash, std::uint32_t seq) override
Fetch a ledger from the shard store.
Definition: DatabaseShardImp.cpp:507
std
STL namespace.
ripple::NodeStore::DatabaseShardImp::numHistoricalShards
std::uint32_t numHistoricalShards(std::lock_guard< std::mutex > const &lock) const
Definition: DatabaseShardImp.cpp:1616
ripple::NodeStore::DatabaseShardImp::relocateOutdatedShards
void relocateOutdatedShards(std::lock_guard< std::mutex > const &lock)
Definition: DatabaseShardImp.cpp:1630
std::mutex
STL class.
ripple::NodeStore::DatabaseShardImp::validate
void validate() override
Verifies shard store data is valid.
Definition: DatabaseShardImp.cpp:654
ripple::NodeStore::DatabaseShardImp::canAdd_
bool canAdd_
Definition: DatabaseShardImp.h:222
ripple::NodeStore::DatabaseShardImp::DatabaseShardImp
DatabaseShardImp()=delete
std::unique_ptr< nudb::context >
ripple::NodeStore::DatabaseShardImp::prepareForNewShard
boost::optional< PathDesignation > prepareForNewShard(std::uint32_t shardIndex, std::uint32_t numHistoricalShards, std::lock_guard< std::mutex > const &lock)
Definition: DatabaseShardImp.cpp:1794
ripple::NodeStore::DatabaseShardImp::ShardInfo
Definition: DatabaseShardImp.h:176
ripple::NodeStore::DatabaseShardImp::onStop
void onStop() override
Override called when the stop notification is issued.
Definition: DatabaseShardImp.cpp:682
ripple::NodeStore::DatabaseShardImp::ctx_
std::unique_ptr< nudb::context > ctx_
Definition: DatabaseShardImp.h:207
ripple::NodeStore::DatabaseShardImp::storeLedgerInShard
bool storeLedgerInShard(std::shared_ptr< Shard > &shard, std::shared_ptr< Ledger const > const &ledger)
Definition: DatabaseShardImp.cpp:1540
ripple::NodeStore::DatabaseShardImp::backendName_
std::string backendName_
Definition: DatabaseShardImp.h:228