optimized ledger_data

This commit is contained in:
CJ Cobb
2022-02-10 16:33:14 +00:00
committed by CJ Cobb
parent 16e3c87dcc
commit 7c6979ae57
3 changed files with 66 additions and 21 deletions

View File

@@ -244,6 +244,7 @@ BackendInterface::fetchLedgerPage(
std::optional<ripple::uint256> const& cursor, std::optional<ripple::uint256> const& cursor,
std::uint32_t const ledgerSequence, std::uint32_t const ledgerSequence,
std::uint32_t const limit, std::uint32_t const limit,
bool outOfOrder,
boost::asio::yield_context& yield) const boost::asio::yield_context& yield) const
{ {
LedgerPage page; LedgerPage page;
@@ -254,8 +255,8 @@ BackendInterface::fetchLedgerPage(
ripple::uint256 const& curCursor = keys.size() ? keys.back() ripple::uint256 const& curCursor = keys.size() ? keys.back()
: cursor ? *cursor : cursor ? *cursor
: firstKey; : firstKey;
auto succ = fetchSuccessorKey(curCursor, ledgerSequence, yield); uint32_t seq = outOfOrder ? range->maxSequence : ledgerSequence;
auto succ = fetchSuccessorKey(curCursor, seq, yield);
if (!succ) if (!succ)
break; break;
BOOST_LOG_TRIVIAL(trace) << ripple::strHex(*succ); BOOST_LOG_TRIVIAL(trace) << ripple::strHex(*succ);

View File

@@ -217,6 +217,7 @@ public:
std::optional<ripple::uint256> const& cursor, std::optional<ripple::uint256> const& cursor,
std::uint32_t const ledgerSequence, std::uint32_t const ledgerSequence,
std::uint32_t const limit, std::uint32_t const limit,
bool outOfOrder,
boost::asio::yield_context& yield) const; boost::asio::yield_context& yield) const;
// Fetches the successor to key/index // Fetches the successor to key/index

View File

@@ -45,12 +45,30 @@ doLedgerData(Context const& context)
limit = boost::json::value_to<int>(request.at("limit")); limit = boost::json::value_to<int>(request.at("limit"));
} }
bool outOfOrder = false;
if (request.contains("out_of_order"))
{
if (!request.at("out_of_order").is_bool())
return Status{Error::rpcINVALID_PARAMS, "binaryFlagNotBool"};
outOfOrder = request.at("out_of_order").as_bool();
}
std::optional<ripple::uint256> cursor; std::optional<ripple::uint256> cursor;
std::optional<uint32_t> diffCursor;
if (request.contains("marker")) if (request.contains("marker"))
{ {
if (!request.at("marker").is_string()) if (!request.at("marker").is_string())
{
if (outOfOrder)
{
if (!request.at("marker").is_int64())
return Status{
Error::rpcINVALID_PARAMS, "markerNotStringOrInt"};
diffCursor = value_to<uint32_t>(request.at("marker"));
}
else
return Status{Error::rpcINVALID_PARAMS, "markerNotString"}; return Status{Error::rpcINVALID_PARAMS, "markerNotString"};
}
BOOST_LOG_TRIVIAL(debug) << __func__ << " : parsing marker"; BOOST_LOG_TRIVIAL(debug) << __func__ << " : parsing marker";
@@ -64,15 +82,8 @@ doLedgerData(Context const& context)
return *status; return *status;
auto lgrInfo = std::get<ripple::LedgerInfo>(v); auto lgrInfo = std::get<ripple::LedgerInfo>(v);
Backend::LedgerPage page;
auto start = std::chrono::system_clock::now();
page = context.backend->fetchLedgerPage(
cursor, lgrInfo.seq, limit, context.yield);
auto end = std::chrono::system_clock::now();
boost::json::object header; boost::json::object header;
// no cursor means this is the first call, so we return header info
if (!cursor) if (!cursor)
{ {
if (binary) if (binary)
@@ -104,23 +115,55 @@ doLedgerData(Context const& context)
response["ledger"] = header; response["ledger"] = header;
} }
} }
response["ledger_hash"] = ripple::strHex(lgrInfo.hash); response["ledger_hash"] = ripple::strHex(lgrInfo.hash);
response["ledger_index"] = lgrInfo.seq; response["ledger_index"] = lgrInfo.seq;
boost::json::array objects; auto start = std::chrono::system_clock::now();
std::vector<Backend::LedgerObject>& results = page.objects; std::vector<Backend::LedgerObject> results;
std::optional<ripple::uint256> const& returnedCursor = page.cursor; if (diffCursor)
if (returnedCursor)
{ {
response["marker"] = ripple::strHex(*returnedCursor); assert(outOfOrder);
BOOST_LOG_TRIVIAL(debug) auto diff =
<< __func__ << " cursor = " << ripple::strHex(*returnedCursor); context.backend->fetchLedgerDiff(*diffCursor, context.yield);
std::vector<ripple::uint256> keys;
for (auto&& [key, object] : diff)
{
if (!object.size())
{
keys.push_back(std::move(key));
} }
}
auto objs = context.backend->fetchLedgerObjects(
keys, lgrInfo.seq, context.yield);
for (size_t i = 0; i < objs.size(); ++i)
{
auto&& obj = objs[i];
results.push_back({std::move(keys[i]), std::move(obj)});
}
if (*diffCursor > lgrInfo.seq)
response["marker"] = *diffCursor - 1;
}
else
{
auto page = context.backend->fetchLedgerPage(
cursor, lgrInfo.seq, limit, outOfOrder, context.yield);
results = std::move(page.objects);
if (page.cursor)
response["marker"] = ripple::strHex(*(page.cursor));
else if (outOfOrder)
response["marker"] =
context.backend->fetchLedgerRange()->maxSequence;
}
auto end = std::chrono::system_clock::now();
auto time =
std::chrono::duration_cast<std::chrono::microseconds>(end - start)
.count();
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< __func__ << " number of results = " << results.size(); << __func__ << " number of results = " << results.size()
<< " fetched in " << time << "microseconds";
boost::json::array objects;
for (auto const& [key, object] : results) for (auto const& [key, object] : results)
{ {
ripple::STLedgerEntry sle{ ripple::STLedgerEntry sle{