3#include "data/LedgerHeaderCache.hpp"
4#include "data/Types.hpp"
5#include "data/cassandra/CassandraBackendFamily.hpp"
6#include "data/cassandra/CassandraSchema.hpp"
7#include "data/cassandra/Concepts.hpp"
8#include "data/cassandra/Handle.hpp"
9#include "data/cassandra/SettingsProvider.hpp"
10#include "data/cassandra/Types.hpp"
11#include "data/cassandra/impl/ExecutionStrategy.hpp"
12#include "util/log/Logger.hpp"
14#include <boost/asio/spawn.hpp>
15#include <boost/json/object.hpp>
16#include <boost/uuid/string_generator.hpp>
17#include <boost/uuid/uuid.hpp>
19#include <fmt/format.h>
20#include <xrpl/basics/Blob.h>
21#include <xrpl/basics/base_uint.h>
22#include <xrpl/basics/strHex.h>
23#include <xrpl/protocol/AccountID.h>
24#include <xrpl/protocol/Indexes.h>
25#include <xrpl/protocol/LedgerHeader.h>
26#include <xrpl/protocol/nft.h>
49 typename FetchLedgerCacheType = FetchLedgerCache>
52 ExecutionStrategyType,
53 CassandraSchema<SettingsProviderType>,
54 FetchLedgerCacheType> {
57 ExecutionStrategyType,
59 FetchLedgerCacheType>;
63 using DefaultCassandraFamily::executor_;
64 using DefaultCassandraFamily::ledgerSequence_;
65 using DefaultCassandraFamily::log_;
66 using DefaultCassandraFamily::range_;
67 using DefaultCassandraFamily::schema_;
73 using DefaultCassandraFamily::DefaultCassandraFamily;
87 schema_->updateLedgerRange, ledgerSequence_,
false, ledgerSequence_
92 schema_->updateLedgerRange.bind(ledgerSequence_,
true, ledgerSequence_ - 1)
94 LOG(log_.warn()) <<
"Update failed for ledger " << ledgerSequence_;
98 LOG(log_.info()) <<
"Committed ledger " << ledgerSequence_;
104 xrpl::AccountID
const& issuer,
105 std::optional<std::uint32_t>
const& taxon,
106 std::uint32_t
const ledgerSequence,
107 std::uint32_t
const limit,
108 std::optional<xrpl::uint256>
const& cursorIn,
109 boost::asio::yield_context yield
114 Statement
const idQueryStatement = [&taxon, &issuer, &cursorIn, &limit,
this]() {
115 if (taxon.has_value()) {
116 auto r = schema_->selectNFTIDsByIssuerTaxon.bind(issuer);
118 r.bindAt(2, cursorIn.value_or(xrpl::uint256(0)));
119 r.bindAt(3,
Limit{limit});
123 auto r = schema_->selectNFTIDsByIssuer.bind(issuer);
127 cursorIn.has_value() ? xrpl::nft::toUInt32(xrpl::nft::getTaxon(*cursorIn)) : 0,
128 cursorIn.value_or(xrpl::uint256(0))
131 r.bindAt(2,
Limit{limit});
136 auto const res = executor_.read(yield, idQueryStatement);
138 auto const& idQueryResults = res.value();
139 if (not idQueryResults.hasRows()) {
140 LOG(log_.debug()) <<
"No rows returned";
144 std::vector<xrpl::uint256> nftIDs;
146 nftIDs.push_back(nftID);
151 if (nftIDs.size() == limit)
152 ret.cursor = nftIDs.back();
154 std::vector<Statement> selectNFTStatements;
155 selectNFTStatements.reserve(nftIDs.size());
160 std::back_inserter(selectNFTStatements),
161 [&](
auto const& nftID) {
return schema_->selectNFT.bind(nftID, ledgerSequence); }
164 auto const nftInfos = executor_.readEach(yield, selectNFTStatements);
166 std::vector<Statement> selectNFTURIStatements;
167 selectNFTURIStatements.reserve(nftIDs.size());
172 std::back_inserter(selectNFTURIStatements),
173 [&](
auto const& nftID) {
return schema_->selectNFTURI.bind(nftID, ledgerSequence); }
176 auto const nftUris = executor_.readEach(yield, selectNFTURIStatements);
178 for (
auto i = 0u; i < nftIDs.size(); i++) {
179 if (
auto const maybeRow = nftInfos[i].
template get<uint32_t, xrpl::AccountID, bool>();
180 maybeRow.has_value()) {
181 auto [seq, owner, isBurned] = *maybeRow;
182 NFT nft(nftIDs[i], seq, owner, isBurned);
183 if (
auto const maybeUri = nftUris[i].
template get<xrpl::Blob>();
184 maybeUri.has_value())
186 ret.nfts.push_back(nft);
192 [[nodiscard]] std::vector<xrpl::uint256>
194 std::uint32_t number,
195 std::uint32_t pageSize,
197 boost::asio::yield_context yield
200 std::vector<xrpl::uint256> liveAccounts;
201 std::optional<xrpl::AccountID> lastItem;
203 while (liveAccounts.size() < number) {
204 Statement
const statement = lastItem
205 ? schema_->selectAccountFromToken.bind(*lastItem,
Limit{pageSize})
206 : schema_->selectAccountFromBeginning.bind(
Limit{pageSize});
208 auto const res = executor_.read(yield, statement);
210 auto const& results = res.value();
211 if (not results.hasRows()) {
212 LOG(log_.debug()) <<
"No rows returned";
216 std::vector<xrpl::uint256> fullAccounts;
218 fullAccounts.push_back(xrpl::keylet::account(account).key);
223 for (
auto i = 0u; i < fullAccounts.size(); i++) {
224 if (not objs[i].empty()) {
225 if (liveAccounts.size() < number) {
226 liveAccounts.push_back(fullAccounts[i]);
233 LOG(log_.error()) <<
"Could not fetch account from account_tx: " << res.error();
242using CassandraBackend = BasicCassandraBackend<SettingsProvider, impl::DefaultExecutionStrategy<>>;
std::vector< xrpl::uint256 > fetchAccountRoots(std::uint32_t number, std::uint32_t pageSize, std::uint32_t seq, boost::asio::yield_context yield) const override
Fetch the specified number of account root object indexes by page, the accounts need to exist for seq...
Definition CassandraBackend.hpp:193
NFTsAndCursor fetchNFTsByIssuer(xrpl::AccountID const &issuer, std::optional< std::uint32_t > const &taxon, std::uint32_t const ledgerSequence, std::uint32_t const limit, std::optional< xrpl::uint256 > const &cursorIn, boost::asio::yield_context yield) const override
Fetches all NFTs issued by a given address.
Definition CassandraBackend.hpp:103
BasicCassandraBackend(BasicCassandraBackend &&)=delete
Move constructor is deleted because handle_ is shared by reference with executor.
bool doFinishWrites() override
The implementation should wait for all pending writes to finish.
Definition CassandraBackend.hpp:81
CassandraBackendFamily(SettingsProviderType settingsProvider, data::LedgerCacheInterface &cache, bool readOnly)
Definition CassandraBackendFamily.hpp:95
void waitForWritesToFinish() override
Definition CassandraBackendFamily.hpp:213
std::vector< Blob > doFetchLedgerObjects(std::vector< xrpl::uint256 > const &keys, std::uint32_t const sequence, boost::asio::yield_context yield) const override
Definition CassandraBackendFamily.hpp:727
bool executeSyncUpdate(Statement statement)
Definition CassandraBackendFamily.hpp:1107
Manages the DB schema and provides access to prepared statements.
Definition CassandraSchema.hpp:22
The requirements of an execution strategy.
Definition Concepts.hpp:35
The requirements of a settings provider.
Definition Concepts.hpp:24
This namespace implements a wrapper for the Cassandra C++ driver.
Definition CassandraBackendFamily.hpp:47
impl::ResultExtractor< Types... > extract(Handle::ResultType const &result)
Extracts the results into series of std::tuple<Types...> by creating a simple wrapper with an STL inp...
Definition Handle.hpp:314
Represents a NFToken.
Definition Types.hpp:161
Represents a bundle of NFTs with a cursor to the next page.
Definition Types.hpp:227
A strong type wrapper for int32_t.
Definition Types.hpp:38