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  bool duplicate)
130 {
131  auto fetch = [&](std::shared_ptr<Backend> const& backend) {
132  Status status;
133  std::shared_ptr<NodeObject> nodeObject;
134  try
135  {
136  status = backend->fetch(hash.data(), &nodeObject);
137  }
138  catch (std::exception const& e)
139  {
140  JLOG(j_.fatal()) << "Exception, " << e.what();
141  Rethrow();
142  }
143 
144  switch (status)
145  {
146  case ok:
147  case notFound:
148  break;
149  case dataCorrupt:
150  JLOG(j_.fatal()) << "Corrupt NodeObject #" << hash;
151  break;
152  default:
153  JLOG(j_.warn()) << "Unknown status=" << status;
154  break;
155  }
156 
157  return nodeObject;
158  };
159 
160  // See if the node object exists in the cache
161  std::shared_ptr<NodeObject> nodeObject;
162 
163  auto [writable, archive] = [&] {
164  std::lock_guard lock(mutex_);
166  }();
167 
168  // Try to fetch from the writable backend
169  nodeObject = fetch(writable);
170  if (!nodeObject)
171  {
172  // Otherwise try to fetch from the archive backend
173  nodeObject = fetch(archive);
174  if (nodeObject)
175  {
176  {
177  // Refresh the writable backend pointer
178  std::lock_guard lock(mutex_);
179  writable = writableBackend_;
180  }
181 
182  // Update writable backend with data from the archive backend
183  if (duplicate)
184  writable->store(nodeObject);
185  }
186  }
187 
188  if (nodeObject)
189  fetchReport.wasFound = true;
190 
191  return nodeObject;
192 }
193 
194 void
197 {
198  auto [writable, archive] = [&] {
199  std::lock_guard lock(mutex_);
201  }();
202 
203  // Iterate the writable backend
204  writable->for_each(f);
205 
206  // Iterate the archive backend
207  archive->for_each(f);
208 }
209 
210 } // namespace NodeStore
211 } // 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:51
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::DatabaseRotatingImp::fetchNodeObject
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, std::uint32_t, FetchReport &fetchReport, bool duplicate) override
Definition: DatabaseRotatingImp.cpp:125
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
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
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::base_uint::data
pointer data()
Definition: base_uint.h:122
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:213
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:333
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
Store the object.
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:195
ripple::NodeStore::DatabaseRotatingImp::writableBackend_
std::shared_ptr< Backend > writableBackend_
Definition: DatabaseRotatingImp.h:83
std::exception::what
T what(T... args)