rippled
DatabaseRotatingImp.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/app/ledger/Ledger.h>
21 #include <ripple/nodestore/impl/DatabaseRotatingImp.h>
22 #include <ripple/protocol/HashPrefix.h>
23 
24 namespace ripple {
25 namespace NodeStore {
26 
28  Scheduler& scheduler,
29  int readThreads,
30  std::shared_ptr<Backend> writableBackend,
31  std::shared_ptr<Backend> archiveBackend,
32  Section const& config,
34  : DatabaseRotating(scheduler, readThreads, config, j)
35  , writableBackend_(std::move(writableBackend))
36  , archiveBackend_(std::move(archiveBackend))
37 {
38  if (writableBackend_)
39  fdRequired_ += writableBackend_->fdRequired();
40  if (archiveBackend_)
41  fdRequired_ += archiveBackend_->fdRequired();
42 }
43 
44 void
47  std::string const& writableBackendName)> const& f)
48 {
49  std::lock_guard lock(mutex_);
50 
51  auto newBackend = f(writableBackend_->getName());
52  archiveBackend_->setDeletePath();
53  archiveBackend_ = std::move(writableBackend_);
54  writableBackend_ = std::move(newBackend);
55 }
56 
59 {
60  std::lock_guard lock(mutex_);
61  return writableBackend_->getName();
62 }
63 
66 {
67  std::lock_guard lock(mutex_);
68  return writableBackend_->getWriteLoad();
69 }
70 
71 void
73 {
74  auto const backend = [&] {
75  std::lock_guard lock(mutex_);
76  return writableBackend_;
77  }();
78 
79  importInternal(*backend, source);
80 }
81 
82 bool
84 {
85  auto const backend = [&] {
86  std::lock_guard lock(mutex_);
87  return writableBackend_;
88  }();
89 
90  return Database::storeLedger(*srcLedger, backend);
91 }
92 
93 void
95 {
96  std::lock_guard lock(mutex_);
97  writableBackend_->sync();
98 }
99 
100 void
102  NodeObjectType type,
103  Blob&& data,
104  uint256 const& hash,
106 {
107  auto nObj = NodeObject::createObject(type, std::move(data), hash);
108 
109  auto const backend = [&] {
110  std::lock_guard lock(mutex_);
111  return writableBackend_;
112  }();
113 
114  backend->store(nObj);
115  storeStats(1, nObj->getData().size());
116 }
117 
118 void
120 {
121  // nothing to do
122 }
123 
126  uint256 const& hash,
128  FetchReport& fetchReport)
129 {
130  auto fetch = [&](std::shared_ptr<Backend> const& backend) {
131  Status status;
132  std::shared_ptr<NodeObject> nodeObject;
133  try
134  {
135  status = backend->fetch(hash.data(), &nodeObject);
136  }
137  catch (std::exception const& e)
138  {
139  JLOG(j_.fatal()) << "Exception, " << e.what();
140  Rethrow();
141  }
142 
143  switch (status)
144  {
145  case ok:
146  ++fetchHitCount_;
147  if (nodeObject)
148  fetchSz_ += nodeObject->getData().size();
149  break;
150  case notFound:
151  break;
152  case dataCorrupt:
153  JLOG(j_.fatal()) << "Corrupt NodeObject #" << hash;
154  break;
155  default:
156  JLOG(j_.warn()) << "Unknown status=" << status;
157  break;
158  }
159 
160  return nodeObject;
161  };
162 
163  // See if the node object exists in the cache
164  std::shared_ptr<NodeObject> nodeObject;
165 
166  auto [writable, archive] = [&] {
167  std::lock_guard lock(mutex_);
169  }();
170 
171  // Try to fetch from the writable backend
172  nodeObject = fetch(writable);
173  if (!nodeObject)
174  {
175  // Otherwise try to fetch from the archive backend
176  nodeObject = fetch(archive);
177  if (nodeObject)
178  {
179  {
180  // Refresh the writable backend pointer
181  std::lock_guard lock(mutex_);
182  writable = writableBackend_;
183  }
184 
185  // Update writable backend with data from the archive backend
186  writable->store(nodeObject);
187  }
188  }
189 
190  if (nodeObject)
191  fetchReport.wasFound = true;
192 
193  return nodeObject;
194 }
195 
196 void
199 {
200  auto [writable, archive] = [&] {
201  std::lock_guard lock(mutex_);
203  }();
204 
205  // Iterate the writable backend
206  writable->for_each(f);
207 
208  // Iterate the archive backend
209  archive->for_each(f);
210 }
211 
212 } // namespace NodeStore
213 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::NodeStore::DatabaseRotatingImp::rotateWithLock
void rotateWithLock(std::function< std::unique_ptr< NodeStore::Backend >(std::string const &writableBackendName)> const &f) override
Rotates the backends.
Definition: DatabaseRotatingImp.cpp:45
ripple::NodeStore::DatabaseRotatingImp::importDatabase
void importDatabase(Database &source) override
Import objects from another database.
Definition: DatabaseRotatingImp.cpp:72
ripple::NodeStore::DatabaseRotatingImp::archiveBackend_
std::shared_ptr< Backend > archiveBackend_
Definition: DatabaseRotatingImp.h:84
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:52
std::string
STL class.
std::shared_ptr
STL class.
std::exception
STL class.
ripple::NodeStore::ok
@ ok
Definition: nodestore/Types.h:45
ripple::NodeStore::DatabaseRotatingImp::sweep
void sweep() override
Remove expired entries from the positive and negative caches.
Definition: DatabaseRotatingImp.cpp:119
ripple::NodeStore::Database::fdRequired_
int fdRequired_
Definition: Database.h:303
std::vector< unsigned char >
ripple::NodeObjectType
NodeObjectType
The types of node objects.
Definition: NodeObject.h:32
ripple::NodeObject::createObject
static std::shared_ptr< NodeObject > createObject(NodeObjectType type, Blob &&data, uint256 const &hash)
Create an object from fields.
Definition: NodeObject.cpp:37
ripple::NodeStore::DatabaseRotatingImp::DatabaseRotatingImp
DatabaseRotatingImp()=delete
ripple::NodeStore::DatabaseRotatingImp::fetchNodeObject
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, std::uint32_t, FetchReport &fetchReport) override
Definition: DatabaseRotatingImp.cpp:125
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::NodeStore::Database::fetchSz_
std::atomic< std::uint32_t > fetchSz_
Definition: Database.h:306
std::lock_guard
STL class.
ripple::NodeStore::FetchReport
Contains information about a fetch operation.
Definition: ripple/nodestore/Scheduler.h:32
std::function
ripple::NodeStore::DatabaseRotatingImp::getName
std::string getName() const override
Retrieve the name associated with this backend.
Definition: DatabaseRotatingImp.cpp:58
ripple::NodeStore::Database::fetchHitCount_
std::atomic< std::uint32_t > fetchHitCount_
Definition: Database.h:305
ripple::base_uint::data
pointer data()
Definition: base_uint.h:115
ripple::NodeStore::notFound
@ notFound
Definition: nodestore/Types.h:46
ripple::base_uint< 256 >
ripple::NodeStore::DatabaseRotatingImp::getWriteLoad
std::int32_t getWriteLoad() const override
Retrieve the estimated number of pending write operations.
Definition: DatabaseRotatingImp.cpp:65
ripple::NodeStore::Database::importInternal
void importInternal(Backend &dstBackend, Database &srcDB)
Definition: Database.cpp:119
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
ripple::NodeStore::DatabaseRotatingImp::mutex_
std::mutex mutex_
Definition: DatabaseRotatingImp.h:85
ripple::NodeStore::DatabaseRotatingImp::storeLedger
bool storeLedger(std::shared_ptr< Ledger const > const &srcLedger) override
Store a ledger from a different database.
Definition: DatabaseRotatingImp.cpp:83
ripple::NodeStore::DatabaseRotatingImp::sync
void sync() override
Definition: DatabaseRotatingImp.cpp:94
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::NodeStore::dataCorrupt
@ dataCorrupt
Definition: nodestore/Types.h:47
std::int32_t
ripple::NodeStore::DatabaseRotating
Definition: DatabaseRotating.h:33
ripple::NodeStore::Scheduler
Scheduling for asynchronous backend activity.
Definition: ripple/nodestore/Scheduler.h:60
ripple::NodeStore::Database::storeStats
void storeStats(std::uint64_t count, std::uint64_t sz)
Definition: Database.h:328
ripple::NodeStore::Status
Status
Return codes from Backend operations.
Definition: nodestore/Types.h:44
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NodeStore::Database::storeLedger
virtual bool storeLedger(std::shared_ptr< Ledger const > const &srcLedger)=0
Store a ledger from a different database.
ripple::NodeStore::DatabaseRotatingImp::store
void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t) override
Definition: DatabaseRotatingImp.cpp:101
ripple::NodeStore::Database::j_
const beast::Journal j_
Definition: Database.h:301
ripple::NodeStore::FetchReport::wasFound
bool wasFound
Definition: ripple/nodestore/Scheduler.h:40
std
STL namespace.
std::make_pair
T make_pair(T... args)
std::unique_ptr
STL class.
ripple::NodeStore::DatabaseRotatingImp::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: DatabaseRotatingImp.cpp:197
ripple::NodeStore::DatabaseRotatingImp::writableBackend_
std::shared_ptr< Backend > writableBackend_
Definition: DatabaseRotatingImp.h:83
std::exception::what
T what(T... args)