mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-20 19:56:00 +00:00
write transaction hashes to separate table
This commit is contained in:
@@ -51,6 +51,13 @@ processAsyncWriteResponse(T& requestParams, CassFuture* fut, F func)
|
|||||||
delete &requestParams;
|
delete &requestParams;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template <class T>
|
||||||
|
void
|
||||||
|
processAsyncWrite(CassFuture* fut, void* cbData)
|
||||||
|
{
|
||||||
|
T& requestParams = *static_cast<T*>(cbData);
|
||||||
|
processAsyncWriteResponse(requestParams, fut, requestParams.retry);
|
||||||
|
}
|
||||||
// Process the result of an asynchronous write. Retry on error
|
// Process the result of an asynchronous write. Retry on error
|
||||||
// @param fut cassandra future associated with the write
|
// @param fut cassandra future associated with the write
|
||||||
// @param cbData struct that holds the request parameters
|
// @param cbData struct that holds the request parameters
|
||||||
@@ -217,6 +224,54 @@ flatMapReadObjectCallback(CassFuture* fut, void* cbData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T, class F>
|
||||||
|
struct CallbackData
|
||||||
|
{
|
||||||
|
CassandraBackend const* backend;
|
||||||
|
T data;
|
||||||
|
F retry;
|
||||||
|
uint32_t currentRetries;
|
||||||
|
std::atomic<int> refs = 1;
|
||||||
|
|
||||||
|
CallbackData(CassandraBackend const* b, T&& d, F f)
|
||||||
|
: backend(b), data(std::move(d)), retry(f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
CassandraBackend::writeTransaction(
|
||||||
|
std::string&& hash,
|
||||||
|
uint32_t seq,
|
||||||
|
std::string&& transaction,
|
||||||
|
std::string&& metadata) const
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(trace) << "Writing txn to cassandra";
|
||||||
|
std::string hashCpy = hash;
|
||||||
|
auto func = [this](auto& params, bool retry) {
|
||||||
|
CassandraStatement statement{insertLedgerTransaction_};
|
||||||
|
statement.bindInt(params.data.first);
|
||||||
|
statement.bindBytes(params.data.second);
|
||||||
|
executeAsyncWrite(
|
||||||
|
statement,
|
||||||
|
processAsyncWrite<
|
||||||
|
typename std::remove_reference<decltype(params)>::type>,
|
||||||
|
params,
|
||||||
|
retry);
|
||||||
|
};
|
||||||
|
auto* lgrSeqToHash =
|
||||||
|
new CallbackData(this, std::make_pair(seq, std::move(hashCpy)), func);
|
||||||
|
WriteTransactionCallbackData* data = new WriteTransactionCallbackData(
|
||||||
|
this,
|
||||||
|
std::move(hash),
|
||||||
|
seq,
|
||||||
|
std::move(transaction),
|
||||||
|
std::move(metadata));
|
||||||
|
|
||||||
|
writeTransaction(*data, false);
|
||||||
|
func(*lgrSeqToHash, false);
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<LedgerRange>
|
std::optional<LedgerRange>
|
||||||
CassandraBackend::fetchLedgerRange() const
|
CassandraBackend::fetchLedgerRange() const
|
||||||
{
|
{
|
||||||
@@ -243,21 +298,8 @@ CassandraBackend::fetchLedgerRange() const
|
|||||||
std::vector<TransactionAndMetadata>
|
std::vector<TransactionAndMetadata>
|
||||||
CassandraBackend::fetchAllTransactionsInLedger(uint32_t ledgerSequence) const
|
CassandraBackend::fetchAllTransactionsInLedger(uint32_t ledgerSequence) const
|
||||||
{
|
{
|
||||||
CassandraStatement statement{selectAllTransactionsInLedger_};
|
auto hashes = fetchAllTransactionHashesInLedger(ledgerSequence);
|
||||||
statement.bindInt(ledgerSequence);
|
return fetchTransactions(hashes);
|
||||||
CassandraResult result = executeSyncRead(statement);
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
BOOST_LOG_TRIVIAL(error) << __func__ << " - no rows";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::vector<TransactionAndMetadata> txns;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
txns.push_back(
|
|
||||||
{result.getBytes(), result.getBytes(), result.getUInt32()});
|
|
||||||
} while (result.nextRow());
|
|
||||||
return txns;
|
|
||||||
}
|
}
|
||||||
std::vector<ripple::uint256>
|
std::vector<ripple::uint256>
|
||||||
CassandraBackend::fetchAllTransactionHashesInLedger(
|
CassandraBackend::fetchAllTransactionHashesInLedger(
|
||||||
@@ -1373,6 +1415,14 @@ CassandraBackend::open(bool readOnly)
|
|||||||
<< " WITH default_time_to_live = " << std::to_string(ttl);
|
<< " WITH default_time_to_live = " << std::to_string(ttl);
|
||||||
if (!executeSimpleStatement(query.str()))
|
if (!executeSimpleStatement(query.str()))
|
||||||
continue;
|
continue;
|
||||||
|
query.str("");
|
||||||
|
query << "CREATE TABLE IF NOT EXISTS " << tablePrefix
|
||||||
|
<< "ledger_transactions"
|
||||||
|
<< " ( ledger_sequence bigint, hash blob, PRIMARY "
|
||||||
|
"KEY(ledger_sequence, hash))"
|
||||||
|
<< " WITH default_time_to_live = " << std::to_string(ttl);
|
||||||
|
if (!executeSimpleStatement(query.str()))
|
||||||
|
continue;
|
||||||
|
|
||||||
query.str("");
|
query.str("");
|
||||||
query << "SELECT * FROM " << tablePrefix << "transactions"
|
query << "SELECT * FROM " << tablePrefix << "transactions"
|
||||||
@@ -1483,6 +1533,12 @@ CassandraBackend::open(bool readOnly)
|
|||||||
"?, ?)";
|
"?, ?)";
|
||||||
if (!insertTransaction_.prepareStatement(query, session_.get()))
|
if (!insertTransaction_.prepareStatement(query, session_.get()))
|
||||||
continue;
|
continue;
|
||||||
|
query.str("");
|
||||||
|
query << "INSERT INTO " << tablePrefix << "ledger_transactions"
|
||||||
|
<< " (ledger_sequence, hash) VALUES "
|
||||||
|
"(?, ?)";
|
||||||
|
if (!insertLedgerTransaction_.prepareStatement(query, session_.get()))
|
||||||
|
continue;
|
||||||
|
|
||||||
query.str("");
|
query.str("");
|
||||||
query << "INSERT INTO " << tablePrefix << "keys"
|
query << "INSERT INTO " << tablePrefix << "keys"
|
||||||
@@ -1519,7 +1575,7 @@ CassandraBackend::open(bool readOnly)
|
|||||||
query, session_.get()))
|
query, session_.get()))
|
||||||
continue;
|
continue;
|
||||||
query.str("");
|
query.str("");
|
||||||
query << "SELECT hash FROM " << tablePrefix << "transactions"
|
query << "SELECT hash FROM " << tablePrefix << "ledger_transactions"
|
||||||
<< " WHERE ledger_sequence = ?";
|
<< " WHERE ledger_sequence = ?";
|
||||||
if (!selectAllTransactionHashesInLedger_.prepareStatement(
|
if (!selectAllTransactionHashesInLedger_.prepareStatement(
|
||||||
query, session_.get()))
|
query, session_.get()))
|
||||||
|
|||||||
@@ -26,13 +26,13 @@
|
|||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <backend/BackendInterface.h>
|
||||||
|
#include <backend/DBHelpers.h>
|
||||||
#include <cassandra.h>
|
#include <cassandra.h>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <backend/BackendInterface.h>
|
|
||||||
#include <backend/DBHelpers.h>
|
|
||||||
|
|
||||||
namespace Backend {
|
namespace Backend {
|
||||||
|
|
||||||
@@ -633,6 +633,7 @@ private:
|
|||||||
// than making a new statement
|
// than making a new statement
|
||||||
CassandraPreparedStatement insertObject_;
|
CassandraPreparedStatement insertObject_;
|
||||||
CassandraPreparedStatement insertTransaction_;
|
CassandraPreparedStatement insertTransaction_;
|
||||||
|
CassandraPreparedStatement insertLedgerTransaction_;
|
||||||
CassandraPreparedStatement selectTransaction_;
|
CassandraPreparedStatement selectTransaction_;
|
||||||
CassandraPreparedStatement selectAllTransactionsInLedger_;
|
CassandraPreparedStatement selectAllTransactionsInLedger_;
|
||||||
CassandraPreparedStatement selectAllTransactionHashesInLedger_;
|
CassandraPreparedStatement selectAllTransactionHashesInLedger_;
|
||||||
@@ -1319,18 +1320,7 @@ public:
|
|||||||
std::string&& hash,
|
std::string&& hash,
|
||||||
uint32_t seq,
|
uint32_t seq,
|
||||||
std::string&& transaction,
|
std::string&& transaction,
|
||||||
std::string&& metadata) const override
|
std::string&& metadata) const override;
|
||||||
{
|
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Writing txn to cassandra";
|
|
||||||
WriteTransactionCallbackData* data = new WriteTransactionCallbackData(
|
|
||||||
this,
|
|
||||||
std::move(hash),
|
|
||||||
seq,
|
|
||||||
std::move(transaction),
|
|
||||||
std::move(metadata));
|
|
||||||
|
|
||||||
writeTransaction(*data, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
startWrites() const override
|
startWrites() const override
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ ReportingETL::runETLPipeline(uint32_t startSequence, int numExtractors)
|
|||||||
uint32_t currentSequence = startSequence;
|
uint32_t currentSequence = startSequence;
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
std::atomic_int per = 4;
|
std::atomic_int per = 100;
|
||||||
auto startTimer = [this, &per]() {
|
auto startTimer = [this, &per]() {
|
||||||
auto innerFunc = [this, &per](auto& f) -> void {
|
auto innerFunc = [this, &per](auto& f) -> void {
|
||||||
std::shared_ptr<boost::asio::steady_timer> timer =
|
std::shared_ptr<boost::asio::steady_timer> timer =
|
||||||
@@ -549,7 +549,8 @@ ReportingETL::runETLPipeline(uint32_t startSequence, int numExtractors)
|
|||||||
};
|
};
|
||||||
innerFunc(innerFunc);
|
innerFunc(innerFunc);
|
||||||
};
|
};
|
||||||
startTimer();
|
// startTimer();
|
||||||
|
|
||||||
auto begin = std::chrono::system_clock::now();
|
auto begin = std::chrono::system_clock::now();
|
||||||
|
|
||||||
while (!writeConflict)
|
while (!writeConflict)
|
||||||
@@ -608,6 +609,7 @@ ReportingETL::runETLPipeline(uint32_t startSequence, int numExtractors)
|
|||||||
deleting_ = false;
|
deleting_ = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (++counter >= per)
|
if (++counter >= per)
|
||||||
{
|
{
|
||||||
std::chrono::milliseconds sleep =
|
std::chrono::milliseconds sleep =
|
||||||
@@ -619,6 +621,7 @@ ReportingETL::runETLPipeline(uint32_t startSequence, int numExtractors)
|
|||||||
counter = 0;
|
counter = 0;
|
||||||
begin = std::chrono::system_clock::now();
|
begin = std::chrono::system_clock::now();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|||||||
17
test.py
17
test.py
@@ -699,11 +699,14 @@ async def ledgers(ip, port, minLedger, maxLedger, transactions, expand, maxCalls
|
|||||||
start = datetime.datetime.now().timestamp()
|
start = datetime.datetime.now().timestamp()
|
||||||
await ws.send(json.dumps({"command":"ledger","ledger_index":int(ledger),"binary":True, "transactions":bool(transactions),"expand":bool(expand)}))
|
await ws.send(json.dumps({"command":"ledger","ledger_index":int(ledger),"binary":True, "transactions":bool(transactions),"expand":bool(expand)}))
|
||||||
res = json.loads(await ws.recv())
|
res = json.loads(await ws.recv())
|
||||||
print(res["header"]["blob"])
|
|
||||||
end = datetime.datetime.now().timestamp()
|
end = datetime.datetime.now().timestamp()
|
||||||
if (end - start) > 0.1:
|
if (end - start) > 0.1:
|
||||||
print("request took more than 100ms")
|
print("request took more than 100ms : " + str(end - start))
|
||||||
numCalls = numCalls + 1
|
numCalls = numCalls + 1
|
||||||
|
if "error" in res:
|
||||||
|
print(res["error"])
|
||||||
|
else:
|
||||||
|
print(res["header"]["blob"])
|
||||||
|
|
||||||
except websockets.exceptions.ConnectionClosedError as e:
|
except websockets.exceptions.ConnectionClosedError as e:
|
||||||
print(e)
|
print(e)
|
||||||
@@ -842,8 +845,13 @@ args = parser.parse_args()
|
|||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
asyncio.set_event_loop(asyncio.new_event_loop())
|
asyncio.set_event_loop(asyncio.new_event_loop())
|
||||||
if(args.ledger is None):
|
rng =asyncio.get_event_loop().run_until_complete(ledger_range(args.ip, args.port))
|
||||||
args.ledger = asyncio.get_event_loop().run_until_complete(ledger_range(args.ip, args.port))[1]
|
if args.ledger is None:
|
||||||
|
args.ledger = rng[1]
|
||||||
|
if args.maxLedger == -1:
|
||||||
|
args.maxLedger = rng[1]
|
||||||
|
if args.minLedger == -1:
|
||||||
|
args.minLedger = rng[0]
|
||||||
if args.action == "fee":
|
if args.action == "fee":
|
||||||
asyncio.get_event_loop().run_until_complete(fee(args.ip, args.port))
|
asyncio.get_event_loop().run_until_complete(fee(args.ip, args.port))
|
||||||
elif args.action == "server_info":
|
elif args.action == "server_info":
|
||||||
@@ -891,6 +899,7 @@ def run(args):
|
|||||||
end = datetime.datetime.now().timestamp()
|
end = datetime.datetime.now().timestamp()
|
||||||
num = int(args.numRunners) * int(args.numCalls)
|
num = int(args.numRunners) * int(args.numCalls)
|
||||||
print("Completed " + str(num) + " in " + str(end - start) + " seconds. Throughput = " + str(num / (end - start)) + " calls per second")
|
print("Completed " + str(num) + " in " + str(end - start) + " seconds. Throughput = " + str(num / (end - start)) + " calls per second")
|
||||||
|
print("Latency = " + str((end - start) / int(args.numCalls)) + " seconds")
|
||||||
elif args.action == "ledger_entries":
|
elif args.action == "ledger_entries":
|
||||||
keys = []
|
keys = []
|
||||||
ledger_index = 0
|
ledger_index = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user