rippled
RelationalDBInterfacePostgres.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2020 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/AcceptedLedger.h>
21 #include <ripple/app/ledger/LedgerMaster.h>
22 #include <ripple/app/ledger/LedgerToJson.h>
23 #include <ripple/app/ledger/TransactionMaster.h>
24 #include <ripple/app/main/Application.h>
25 #include <ripple/app/misc/Manifest.h>
26 #include <ripple/app/misc/impl/AccountTxPaging.h>
27 #include <ripple/app/rdb/RelationalDBInterface_nodes.h>
28 #include <ripple/app/rdb/RelationalDBInterface_postgres.h>
29 #include <ripple/app/rdb/backend/RelationalDBInterfacePostgres.h>
30 #include <ripple/basics/BasicConfig.h>
31 #include <ripple/basics/StringUtilities.h>
32 #include <ripple/core/DatabaseCon.h>
33 #include <ripple/core/Pg.h>
34 #include <ripple/core/SociDB.h>
35 #include <ripple/json/to_string.h>
36 #include <ripple/nodestore/DatabaseShard.h>
37 #include <boost/algorithm/string.hpp>
38 #include <boost/range/adaptor/transformed.hpp>
39 #include <soci/sqlite3/soci-sqlite3.h>
40 
41 namespace ripple {
42 
44 {
45 public:
47  Application& app,
48  Config const& config,
49  JobQueue& jobQueue)
50  : app_(app)
51  , j_(app_.journal("PgPool"))
52  , pgPool_(
53 #ifdef RIPPLED_REPORTING
54  make_PgPool(config.section("ledger_tx_tables"), j_)
55 #endif
56  )
57  {
58  assert(config.reporting());
59 #ifdef RIPPLED_REPORTING
60  if (config.reporting() && !config.reportingReadOnly()) // use pg
61  {
62  initSchema(pgPool_);
63  }
64 #endif
65  }
66 
67  void
68  stop() override
69  {
70 #ifdef RIPPLED_REPORTING
71  pgPool_->stop();
72 #endif
73  }
74 
75  void
76  sweep() override;
77 
79  getMinLedgerSeq() override;
80 
82  getMaxLedgerSeq() override;
83 
85  getCompleteLedgers() override;
86 
88  getValidatedLedgerAge() override;
89 
90  bool
92  LedgerInfo const& info,
93  std::vector<AccountTransactionsData> const& accountTxData) override;
94 
96  getLedgerInfoByIndex(LedgerIndex ledgerSeq) override;
97 
99  getNewestLedgerInfo() override;
100 
102  getLedgerInfoByHash(uint256 const& ledgerHash) override;
103 
104  uint256
105  getHashByIndex(LedgerIndex ledgerIndex) override;
106 
108  getHashesByIndex(LedgerIndex ledgerIndex) override;
109 
111  getHashesByIndex(LedgerIndex minSeq, LedgerIndex maxSeq) override;
112 
114  getTxHashes(LedgerIndex seq) override;
115 
117  getTxHistory(LedgerIndex startIndex) override;
118 
120  getAccountTx(AccountTxArgs const& args) override;
121 
123  locateTransaction(uint256 const& id) override;
124 
125  bool
126  ledgerDbHasSpace(Config const& config) override;
127 
128  bool
129  transactionDbHasSpace(Config const& config) override;
130 
131  bool
132  isCaughtUp(std::string& reason) override;
133 
134 private:
138 
139  bool
140  dbHasSpace(Config const& config);
141 };
142 
143 void
145 {
146 #ifdef RIPPLED_REPORTING
147  pgPool_->idleSweeper();
148 #endif
149 }
150 
153 {
155 }
156 
159 {
161 }
162 
165 {
167 }
168 
171 {
173 }
174 
175 bool
177  LedgerInfo const& info,
178  std::vector<AccountTransactionsData> const& accountTxData)
179 {
180  return ripple::writeLedgerAndTransactions(pgPool_, info, accountTxData, j_);
181 }
182 
185 {
186  return ripple::getLedgerInfoByIndex(pgPool_, ledgerSeq, app_);
187 }
188 
191 {
193 }
194 
197 {
198  return ripple::getLedgerInfoByHash(pgPool_, ledgerHash, app_);
199 }
200 
201 uint256
203 {
204  return ripple::getHashByIndex(pgPool_, ledgerIndex, app_);
205 }
206 
209 {
210  LedgerHashPair p;
212  pgPool_, ledgerIndex, p.ledgerHash, p.parentHash, app_))
213  return {};
214  return p;
215 }
216 
219  LedgerIndex minSeq,
220  LedgerIndex maxSeq)
221 {
222  return ripple::getHashesByIndex(pgPool_, minSeq, maxSeq, app_);
223 }
224 
227 {
228  return ripple::getTxHashes(pgPool_, seq, app_);
229 }
230 
233 {
234  return ripple::getTxHistory(pgPool_, startIndex, app_, j_);
235 }
236 
239 {
240  return ripple::getAccountTx(pgPool_, args, app_, j_);
241 }
242 
245 {
247 }
248 
249 bool
251 {
252  /* Postgres server could be running on a different machine. */
253 
254  return true;
255 }
256 
257 bool
259 {
260  return dbHasSpace(config);
261 }
262 
263 bool
265 {
266  return dbHasSpace(config);
267 }
268 
271  Application& app,
272  Config const& config,
273  JobQueue& jobQueue)
274 {
275  return std::make_unique<RelationalDBInterfacePostgresImp>(
276  app, config, jobQueue);
277 }
278 bool
280 {
281 #ifdef RIPPLED_REPORTING
282  using namespace std::chrono_literals;
283  auto age = PgQuery(pgPool_)("SELECT age()");
284  if (!age || age.isNull())
285  {
286  reason = "No ledgers in database";
287  return false;
288  }
289  if (std::chrono::seconds{age.asInt()} > 3min)
290  {
291  reason = "No recently-published ledger";
292  return false;
293  }
294 #endif
295  return true;
296 }
297 
298 } // namespace ripple
ripple::RelationalDBInterfacePostgresImp::locateTransaction
Transaction::Locator locateTransaction(uint256 const &id) override
locateTransaction Returns information used to locate a transaction.
Definition: RelationalDBInterfacePostgres.cpp:244
ripple::getLedgerInfoByIndex
std::optional< LedgerInfo > getLedgerInfoByIndex(soci::session &session, LedgerIndex ledgerSeq, beast::Journal j)
getLedgerInfoByIndex Returns ledger by its sequence.
Definition: RelationalDBInterface_nodes.cpp:455
ripple::Application
Definition: Application.h:115
ripple::RelationalDBInterfacePostgresImp::ledgerDbHasSpace
bool ledgerDbHasSpace(Config const &config) override
ledgerDbHasSpace Checks if ledger database has available space.
Definition: RelationalDBInterfacePostgres.cpp:258
ripple::RelationalDBInterfacePostgresImp::dbHasSpace
bool dbHasSpace(Config const &config)
Definition: RelationalDBInterfacePostgres.cpp:250
ripple::RelationalDBInterface::AccountTxArgs
Definition: RelationalDBInterface.h:96
ripple::getAccountTx
std::pair< AccountTxResult, RPC::Status > getAccountTx(std::shared_ptr< PgPool > const &pgPool, AccountTxArgs const &args, Application &app, beast::Journal j)
getAccountTx Get last account transactions specifies by passed argumenrs structure.
Definition: RelationalDBInterface_postgres.cpp:542
std::string
STL class.
std::shared_ptr< PgPool >
ripple::getTxHistory
std::pair< std::vector< std::shared_ptr< Transaction > >, int > getTxHistory(soci::session &session, Application &app, LedgerIndex startIndex, int quantity, bool count)
getTxHistory Returns given number of most recent transactions starting from given number of entry.
Definition: RelationalDBInterface_nodes.cpp:615
ripple::getHashByIndex
uint256 getHashByIndex(soci::session &session, LedgerIndex ledgerIndex)
getHashByIndex Returns hash of ledger with given sequence.
Definition: RelationalDBInterface_nodes.cpp:509
ripple::RelationalDBInterfacePostgresImp::getNewestLedgerInfo
std::optional< LedgerInfo > getNewestLedgerInfo() override
getNewestLedgerInfo Returns info of newest saved ledger.
Definition: RelationalDBInterfacePostgres.cpp:190
std::pair
ripple::RelationalDBInterfacePostgresImp::RelationalDBInterfacePostgresImp
RelationalDBInterfacePostgresImp(Application &app, Config const &config, JobQueue &jobQueue)
Definition: RelationalDBInterfacePostgres.cpp:46
std::vector
STL class.
std::chrono::seconds
ripple::getLedgerInfoByHash
std::optional< LedgerInfo > getLedgerInfoByHash(soci::session &session, uint256 const &ledgerHash, beast::Journal j)
getLedgerInfoByHash Returns info of ledger with given hash.
Definition: RelationalDBInterface_nodes.cpp:498
ripple::locateTransaction
Transaction::Locator locateTransaction(std::shared_ptr< PgPool > const &pgPool, uint256 const &id, Application &app)
locateTransaction Returns information used to locate a transaction.
Definition: RelationalDBInterface_postgres.cpp:657
ripple::RelationalDBInterfacePostgresImp::getAccountTx
std::pair< AccountTxResult, RPC::Status > getAccountTx(AccountTxArgs const &args) override
getAccountTx Get last account transactions specifies by passed argumenrs structure.
Definition: RelationalDBInterfacePostgres.cpp:238
ripple::RelationalDBInterfacePostgres
Definition: RelationalDBInterfacePostgres.h:27
ripple::getRelationalDBInterfacePostgres
std::unique_ptr< RelationalDBInterface > getRelationalDBInterfacePostgres(Application &app, Config const &config, JobQueue &jobQueue)
Definition: RelationalDBInterfacePostgres.cpp:270
ripple::getCompleteLedgers
std::string getCompleteLedgers(std::shared_ptr< PgPool > const &pgPool)
getCompleteLedgers Returns string which contains list of completed ledgers
Definition: RelationalDBInterface_postgres.cpp:61
ripple::RelationalDBInterfacePostgresImp::getTxHistory
std::vector< std::shared_ptr< Transaction > > getTxHistory(LedgerIndex startIndex) override
getTxHistory Returns most recent 20 transactions starting from given number or entry.
Definition: RelationalDBInterfacePostgres.cpp:232
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:75
ripple::writeLedgerAndTransactions
bool writeLedgerAndTransactions(std::shared_ptr< PgPool > const &pgPool, LedgerInfo const &info, std::vector< AccountTransactionsData > const &accountTxData, beast::Journal &j)
writeLedgerAndTransactions Write new ledger and transaction data to Postgres.
Definition: RelationalDBInterface_postgres.cpp:762
ripple::getValidatedLedgerAge
std::chrono::seconds getValidatedLedgerAge(std::shared_ptr< PgPool > const &pgPool, beast::Journal j)
getValidatedLedgerAge Returns age of last validated ledger
Definition: RelationalDBInterface_postgres.cpp:72
ripple::Config::reporting
bool reporting() const
Definition: Config.h:308
ripple::LedgerHashPair::ledgerHash
uint256 ledgerHash
Definition: RelationalDBInterface.h:38
ripple::Transaction::Locator
Definition: Transaction.h:315
ripple::Config
Definition: Config.h:68
ripple::LedgerHashPair
Definition: RelationalDBInterface.h:36
ripple::RelationalDBInterfacePostgresImp::stop
void stop() override
There is only one implementation of this interface: RelationalDBInterfacePostgresImp.
Definition: RelationalDBInterfacePostgres.cpp:68
ripple::RelationalDBInterfacePostgresImp
Definition: RelationalDBInterfacePostgres.cpp:43
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
std::map
STL class.
ripple::RelationalDBInterfacePostgresImp::getLedgerInfoByHash
std::optional< LedgerInfo > getLedgerInfoByHash(uint256 const &ledgerHash) override
Definition: RelationalDBInterfacePostgres.cpp:196
ripple::RelationalDBInterfacePostgresImp::getTxHashes
std::vector< uint256 > getTxHashes(LedgerIndex seq) override
getTxHashes Returns vector of tx hashes by given ledger sequence.
Definition: RelationalDBInterfacePostgres.cpp:226
ripple::RelationalDBInterfacePostgresImp::getMaxLedgerSeq
std::optional< LedgerIndex > getMaxLedgerSeq() override
getMaxLedgerSeq Returns maximum ledger sequence in Ledgers table.
Definition: RelationalDBInterfacePostgres.cpp:158
ripple::JobQueue
A pool of threads to perform work.
Definition: JobQueue.h:55
ripple::RelationalDBInterfacePostgresImp::getValidatedLedgerAge
std::chrono::seconds getValidatedLedgerAge() override
getValidatedLedgerAge Returns age of last validated ledger.
Definition: RelationalDBInterfacePostgres.cpp:170
ripple::RelationalDBInterfacePostgresImp::j_
beast::Journal j_
Definition: RelationalDBInterfacePostgres.cpp:136
ripple::RelationalDBInterfacePostgresImp::getCompleteLedgers
std::string getCompleteLedgers() override
getCompleteLedgers Returns string which contains list of completed ledgers.
Definition: RelationalDBInterfacePostgres.cpp:164
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::RelationalDBInterfacePostgresImp::sweep
void sweep() override
sweep Sweep the database.
Definition: RelationalDBInterfacePostgres.cpp:144
ripple::RelationalDBInterfacePostgresImp::getLedgerInfoByIndex
std::optional< LedgerInfo > getLedgerInfoByIndex(LedgerIndex ledgerSeq) override
getLedgerInfoByIndex Returns ledger by its sequence.
Definition: RelationalDBInterfacePostgres.cpp:184
ripple::getHashesByIndex
std::optional< LedgerHashPair > getHashesByIndex(soci::session &session, LedgerIndex ledgerIndex, beast::Journal j)
getHashesByIndex Returns hash of the ledger and hash of parent ledger for the ledger of given sequenc...
Definition: RelationalDBInterface_nodes.cpp:539
ripple::RelationalDBInterfacePostgresImp::transactionDbHasSpace
bool transactionDbHasSpace(Config const &config) override
transactionDbHasSpace Checks if transaction database has available space.
Definition: RelationalDBInterfacePostgres.cpp:264
ripple::LedgerHashPair::parentHash
uint256 parentHash
Definition: RelationalDBInterface.h:39
ripple::RelationalDBInterfacePostgresImp::isCaughtUp
bool isCaughtUp(std::string &reason) override
isCaughtUp returns whether the database is caught up with the network
Definition: RelationalDBInterfacePostgres.cpp:279
std::optional
ripple::LedgerInfo
Information about the notional ledger backing the view.
Definition: ReadView.h:84
ripple::Config::reportingReadOnly
bool reportingReadOnly() const
Definition: Config.h:320
ripple::getMinLedgerSeq
std::optional< LedgerIndex > getMinLedgerSeq(soci::session &session, TableType type)
getMinLedgerSeq Returns minimum ledger sequence in given table.
Definition: RelationalDBInterface_nodes.cpp:121
std::unique_ptr
STL class.
ripple::RelationalDBInterfacePostgresImp::getHashesByIndex
std::optional< LedgerHashPair > getHashesByIndex(LedgerIndex ledgerIndex) override
getHashesByIndex Returns hash of the ledger and hash of parent ledger for the ledger of given sequenc...
Definition: RelationalDBInterfacePostgres.cpp:208
ripple::RelationalDBInterfacePostgresImp::app_
Application & app_
Definition: RelationalDBInterfacePostgres.cpp:135
ripple::getNewestLedgerInfo
std::optional< LedgerInfo > getNewestLedgerInfo(soci::session &session, beast::Journal j)
getNewestLedgerInfo Returns info of newest saved ledger.
Definition: RelationalDBInterface_nodes.cpp:466
ripple::RelationalDBInterfacePostgresImp::writeLedgerAndTransactions
bool writeLedgerAndTransactions(LedgerInfo const &info, std::vector< AccountTransactionsData > const &accountTxData) override
writeLedgerAndTransactions Write new ledger and transaction data into database.
Definition: RelationalDBInterfacePostgres.cpp:176
ripple::getMaxLedgerSeq
std::optional< LedgerIndex > getMaxLedgerSeq(soci::session &session, TableType type)
getMaxLedgerSeq Returns maximum ledger sequence in given table.
Definition: RelationalDBInterface_nodes.cpp:131
ripple::RelationalDBInterfacePostgresImp::getHashByIndex
uint256 getHashByIndex(LedgerIndex ledgerIndex) override
getHashByIndex Returns hash of ledger with given sequence.
Definition: RelationalDBInterfacePostgres.cpp:202
ripple::RelationalDBInterfacePostgresImp::pgPool_
std::shared_ptr< PgPool > pgPool_
Definition: RelationalDBInterfacePostgres.cpp:137
ripple::RelationalDBInterfacePostgresImp::getMinLedgerSeq
std::optional< LedgerIndex > getMinLedgerSeq() override
getMinLedgerSeq Returns minimum ledger sequence in Ledgers table.
Definition: RelationalDBInterfacePostgres.cpp:152
ripple::getTxHashes
std::vector< uint256 > getTxHashes(std::shared_ptr< PgPool > const &pgPool, LedgerIndex seq, Application &app)
getTxHashes Returns vector of tx hashes by given ledger sequence
Definition: RelationalDBInterface_postgres.cpp:330