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  std::string const& name,
29  Scheduler& scheduler,
30  int readThreads,
31  Stoppable& parent,
32  std::shared_ptr<Backend> writableBackend,
33  std::shared_ptr<Backend> archiveBackend,
34  Section const& config,
36  : DatabaseRotating(name, parent, scheduler, readThreads, config, j)
37  , writableBackend_(std::move(writableBackend))
38  , archiveBackend_(std::move(archiveBackend))
39 {
40  if (writableBackend_)
41  fdRequired_ += writableBackend_->fdRequired();
42  if (archiveBackend_)
43  fdRequired_ += archiveBackend_->fdRequired();
44  setParent(parent);
45 }
46 
47 void
50  std::string const& writableBackendName)> const& f)
51 {
52  std::lock_guard lock(mutex_);
53 
54  auto newBackend = f(writableBackend_->getName());
55  archiveBackend_->setDeletePath();
56  archiveBackend_ = std::move(writableBackend_);
57  writableBackend_ = std::move(newBackend);
58 }
59 
62 {
63  std::lock_guard lock(mutex_);
64  return writableBackend_->getName();
65 }
66 
69 {
70  std::lock_guard lock(mutex_);
71  return writableBackend_->getWriteLoad();
72 }
73 
74 void
76 {
77  auto const backend = [&] {
78  std::lock_guard lock(mutex_);
79  return writableBackend_;
80  }();
81 
82  importInternal(*backend, source);
83 }
84 
85 bool
87 {
88  auto const backend = [&] {
89  std::lock_guard lock(mutex_);
90  return writableBackend_;
91  }();
92 
93  return Database::storeLedger(*srcLedger, backend);
94 }
95 
96 void
98 {
99  std::lock_guard lock(mutex_);
100  writableBackend_->sync();
101 }
102 
103 void
105  NodeObjectType type,
106  Blob&& data,
107  uint256 const& hash,
109 {
110  auto nObj = NodeObject::createObject(type, std::move(data), hash);
111 
112  auto const backend = [&] {
113  std::lock_guard lock(mutex_);
114  return writableBackend_;
115  }();
116 
117  backend->store(nObj);
118  storeStats(1, nObj->getData().size());
119 }
120 
121 void
123 {
124  // nothing to do
125 }
126 
129  uint256 const& hash,
131  FetchReport& fetchReport)
132 {
133  auto fetch = [&](std::shared_ptr<Backend> const& backend) {
134  Status status;
135  std::shared_ptr<NodeObject> nodeObject;
136  try
137  {
138  status = backend->fetch(hash.data(), &nodeObject);
139  }
140  catch (std::exception const& e)
141  {
142  JLOG(j_.fatal()) << "Exception, " << e.what();
143  Rethrow();
144  }
145 
146  switch (status)
147  {
148  case ok:
149  ++fetchHitCount_;
150  if (nodeObject)
151  fetchSz_ += nodeObject->getData().size();
152  break;
153  case notFound:
154  break;
155  case dataCorrupt:
156  JLOG(j_.fatal()) << "Corrupt NodeObject #" << hash;
157  break;
158  default:
159  JLOG(j_.warn()) << "Unknown status=" << status;
160  break;
161  }
162 
163  return nodeObject;
164  };
165 
166  // See if the node object exists in the cache
167  std::shared_ptr<NodeObject> nodeObject;
168 
169  auto [writable, archive] = [&] {
170  std::lock_guard lock(mutex_);
172  }();
173 
174  // Try to fetch from the writable backend
175  nodeObject = fetch(writable);
176  if (!nodeObject)
177  {
178  // Otherwise try to fetch from the archive backend
179  nodeObject = fetch(archive);
180  if (nodeObject)
181  {
182  {
183  // Refresh the writable backend pointer
184  std::lock_guard lock(mutex_);
185  writable = writableBackend_;
186  }
187 
188  // Update writable backend with data from the archive backend
189  writable->store(nodeObject);
190  }
191  }
192 
193  if (nodeObject)
194  fetchReport.wasFound = true;
195 
196  return nodeObject;
197 }
198 
199 void
202 {
203  auto [writable, archive] = [&] {
204  std::lock_guard lock(mutex_);
206  }();
207 
208  // Iterate the writable backend
209  writable->for_each(f);
210 
211  // Iterate the archive backend
212  archive->for_each(f);
213 }
214 
215 } // namespace NodeStore
216 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:43
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:48
ripple::NodeStore::DatabaseRotatingImp::archiveBackend_
std::shared_ptr< Backend > archiveBackend_
Definition: DatabaseRotatingImp.h:87
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:50
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:122
ripple::NodeStore::Database::fdRequired_
int fdRequired_
Definition: Database.h:240
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:128
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::NodeStore::Database::fetchSz_
std::atomic< std::uint32_t > fetchSz_
Definition: Database.h:243
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:61
ripple::NodeStore::Database::fetchHitCount_
std::atomic< std::uint32_t > fetchHitCount_
Definition: Database.h:242
ripple::base_uint::data
pointer data()
Definition: base_uint.h:113
ripple::Stoppable::setParent
void setParent(Stoppable &parent)
Set the parent of this Stoppable.
Definition: Stoppable.cpp:43
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:68
ripple::Stoppable
Provides an interface for starting and stopping.
Definition: Stoppable.h:201
ripple::NodeStore::Database::importInternal
void importInternal(Backend &dstBackend, Database &srcDB)
Definition: Database.cpp:106
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
ripple::NodeStore::DatabaseRotatingImp::mutex_
std::mutex mutex_
Definition: DatabaseRotatingImp.h:88
ripple::NodeStore::DatabaseRotatingImp::storeLedger
bool storeLedger(std::shared_ptr< Ledger const > const &srcLedger) override
Store a ledger from a different database.
Definition: DatabaseRotatingImp.cpp:86
ripple::NodeStore::DatabaseRotatingImp::sync
void sync() override
Definition: DatabaseRotatingImp.cpp:97
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::DatabaseRotatingImp::import
void import(Database &source) override
Import objects from another database.
Definition: DatabaseRotatingImp.cpp:75
ripple::NodeStore::Database::storeStats
void storeStats(std::uint64_t count, std::uint64_t sz)
Definition: Database.h:249
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:104
ripple::NodeStore::Database::j_
const beast::Journal j_
Definition: Database.h:238
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:200
ripple::NodeStore::DatabaseRotatingImp::writableBackend_
std::shared_ptr< Backend > writableBackend_
Definition: DatabaseRotatingImp.h:86
std::exception::what
T what(T... args)