mirror of
https://github.com/XRPLF/clio.git
synced 2026-04-29 15:37:53 +00:00
Add assertion that terminate clio (#994)
Fixes #893. Also added termination handler to print backtrace on crash, so fixes #929.
This commit is contained in:
3
CMake/deps/libbacktrace.cmake
Normal file
3
CMake/deps/libbacktrace.cmake
Normal file
@@ -0,0 +1,3 @@
|
||||
target_compile_definitions(clio PUBLIC BOOST_STACKTRACE_LINK)
|
||||
target_compile_definitions(clio PUBLIC BOOST_STACKTRACE_USE_BACKTRACE)
|
||||
find_package(libbacktrace REQUIRED)
|
||||
@@ -44,6 +44,7 @@ include (CMake/deps/OpenSSL.cmake)
|
||||
include (CMake/deps/Threads.cmake)
|
||||
include (CMake/deps/libfmt.cmake)
|
||||
include (CMake/deps/cassandra.cmake)
|
||||
include (CMake/deps/libbacktrace.cmake)
|
||||
|
||||
# TODO: Include directory will be wrong when installed.
|
||||
target_include_directories (clio PUBLIC src)
|
||||
@@ -56,11 +57,14 @@ target_link_libraries (clio
|
||||
PUBLIC Boost::system
|
||||
PUBLIC Boost::log
|
||||
PUBLIC Boost::log_setup
|
||||
PUBLIC Boost::stacktrace_backtrace
|
||||
PUBLIC cassandra-cpp-driver::cassandra-cpp-driver
|
||||
PUBLIC fmt::fmt
|
||||
PUBLIC OpenSSL::Crypto
|
||||
PUBLIC OpenSSL::SSL
|
||||
PUBLIC xrpl::libxrpl
|
||||
PUBLIC dl
|
||||
PUBLIC libbacktrace::libbacktrace
|
||||
|
||||
INTERFACE Threads::Threads
|
||||
)
|
||||
@@ -143,7 +147,9 @@ target_sources (clio PRIVATE
|
||||
src/util/prometheus/Metrics.cpp
|
||||
src/util/prometheus/Prometheus.cpp
|
||||
src/util/Random.cpp
|
||||
src/util/Taggable.cpp)
|
||||
src/util/Taggable.cpp
|
||||
src/util/TerminationHandler.cpp
|
||||
)
|
||||
|
||||
# Clio server
|
||||
add_executable (clio_server src/main/Main.cpp)
|
||||
@@ -167,6 +173,7 @@ if (tests)
|
||||
unittests/DOSGuardTests.cpp
|
||||
unittests/SubscriptionTests.cpp
|
||||
unittests/SubscriptionManagerTests.cpp
|
||||
unittests/util/AssertTests.cpp
|
||||
unittests/util/TestObject.cpp
|
||||
unittests/util/StringUtils.cpp
|
||||
unittests/util/prometheus/CounterTests.cpp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||
import re
|
||||
|
||||
|
||||
class Clio(ConanFile):
|
||||
name = 'clio'
|
||||
@@ -11,7 +11,7 @@ class Clio(ConanFile):
|
||||
settings = 'os', 'compiler', 'build_type', 'arch'
|
||||
options = {
|
||||
'fPIC': [True, False],
|
||||
'verbose': [True, False],
|
||||
'verbose': [True, False],
|
||||
'tests': [True, False], # build unit tests; create `clio_tests` binary
|
||||
'docs': [True, False], # doxygen API docs; create custom target 'docs'
|
||||
'packaging': [True, False], # create distribution packages
|
||||
@@ -27,6 +27,7 @@ class Clio(ConanFile):
|
||||
'grpc/1.50.1',
|
||||
'openssl/1.1.1u',
|
||||
'xrpl/2.0.0-rc1',
|
||||
'libbacktrace/cci.20210118'
|
||||
]
|
||||
|
||||
default_options = {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <data/BackendCounters.h>
|
||||
#include <util/Assert.h>
|
||||
|
||||
#include <util/prometheus/Prometheus.h>
|
||||
|
||||
@@ -161,7 +162,10 @@ BackendCounters::AsyncOperationCounters::registerStarted(std::uint64_t const cou
|
||||
void
|
||||
BackendCounters::AsyncOperationCounters::registerFinished(std::uint64_t const count)
|
||||
{
|
||||
assert(pendingCounter_.get().value() >= static_cast<std::int64_t>(count));
|
||||
ASSERT(
|
||||
pendingCounter_.get().value() >= static_cast<std::int64_t>(count),
|
||||
"Finished operations can't be more than pending"
|
||||
);
|
||||
pendingCounter_.get() -= count;
|
||||
completedCounter_.get() += count;
|
||||
}
|
||||
@@ -175,7 +179,9 @@ BackendCounters::AsyncOperationCounters::registerRetry(std::uint64_t count)
|
||||
void
|
||||
BackendCounters::AsyncOperationCounters::registerError(std::uint64_t count)
|
||||
{
|
||||
assert(pendingCounter_.get().value() >= static_cast<std::int64_t>(count));
|
||||
ASSERT(
|
||||
pendingCounter_.get().value() >= static_cast<std::int64_t>(count), "Error operations can't be more than pending"
|
||||
);
|
||||
pendingCounter_.get() -= count;
|
||||
errorCounter_.get() += count;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <data/BackendInterface.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/log/Logger.h>
|
||||
|
||||
#include <ripple/protocol/Indexes.h>
|
||||
@@ -43,7 +44,7 @@ BackendInterface::finishWrites(std::uint32_t const ledgerSequence)
|
||||
void
|
||||
BackendInterface::writeLedgerObject(std::string&& key, std::uint32_t const seq, std::string&& blob)
|
||||
{
|
||||
assert(key.size() == sizeof(ripple::uint256));
|
||||
ASSERT(key.size() == sizeof(ripple::uint256), "Key must be 256 bits");
|
||||
doWriteLedgerObject(std::move(key), seq, std::move(blob));
|
||||
}
|
||||
|
||||
@@ -188,7 +189,7 @@ BackendInterface::fetchBookOffers(
|
||||
}
|
||||
auto nextKey = ripple::keylet::page(uTipIndex, next);
|
||||
auto nextDir = fetchLedgerObject(nextKey.key, ledgerSequence, yield);
|
||||
assert(nextDir);
|
||||
ASSERT(nextDir.has_value(), "Next dir must exist");
|
||||
offerDir->blob = *nextDir;
|
||||
offerDir->key = nextKey.key;
|
||||
}
|
||||
@@ -200,7 +201,7 @@ BackendInterface::fetchBookOffers(
|
||||
for (size_t i = 0; i < keys.size() && i < limit; ++i) {
|
||||
LOG(gLog.trace()) << "Key = " << ripple::strHex(keys[i]) << " blob = " << ripple::strHex(objs[i])
|
||||
<< " ledgerSequence = " << ledgerSequence;
|
||||
assert(!objs[i].empty());
|
||||
ASSERT(!objs[i].empty(), "Ledger object can't be empty");
|
||||
page.offers.push_back({keys[i], objs[i]});
|
||||
}
|
||||
auto end = std::chrono::system_clock::now();
|
||||
@@ -234,7 +235,14 @@ void
|
||||
BackendInterface::updateRange(uint32_t newMax)
|
||||
{
|
||||
std::scoped_lock const lck(rngMtx_);
|
||||
assert(!range || newMax >= range->maxSequence);
|
||||
|
||||
ASSERT(
|
||||
!range || newMax >= range->maxSequence,
|
||||
"Range shouldn't exist yet or newMax should be greater. newMax = {}, range->maxSequence = {}",
|
||||
newMax,
|
||||
range->maxSequence
|
||||
);
|
||||
|
||||
if (!range) {
|
||||
range = {newMax, newMax};
|
||||
} else {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <data/cassandra/Schema.h>
|
||||
#include <data/cassandra/SettingsProvider.h>
|
||||
#include <data/cassandra/impl/ExecutionStrategy.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/LedgerUtils.h>
|
||||
#include <util/Profiler.h>
|
||||
#include <util/log/Logger.h>
|
||||
@@ -622,7 +623,7 @@ public:
|
||||
);
|
||||
});
|
||||
|
||||
assert(numHashes == results.size());
|
||||
ASSERT(numHashes == results.size(), "Number of hashes and results must match");
|
||||
LOG(log_.debug()) << "Fetched " << numHashes << " transactions from Cassandra in " << timeDiff
|
||||
<< " milliseconds";
|
||||
return results;
|
||||
@@ -735,8 +736,8 @@ public:
|
||||
{
|
||||
LOG(log_.trace()) << "Writing successor. key = " << key.size() << " bytes. "
|
||||
<< " seq = " << std::to_string(seq) << " successor = " << successor.size() << " bytes.";
|
||||
assert(!key.empty());
|
||||
assert(!successor.empty());
|
||||
ASSERT(!key.empty(), "Key must not be empty");
|
||||
ASSERT(!successor.empty(), "Successor must not be empty");
|
||||
|
||||
executor_.write(schema_->insertSuccessor, std::move(key), seq, std::move(successor));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
/** @file */
|
||||
#pragma once
|
||||
|
||||
#include <util/Assert.h>
|
||||
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/protocol/SField.h>
|
||||
@@ -233,7 +235,7 @@ getBookBase(T const& key)
|
||||
{
|
||||
static constexpr size_t KEY_SIZE = 24;
|
||||
|
||||
assert(key.size() == ripple::uint256::size());
|
||||
ASSERT(key.size() == ripple::uint256::size(), "Invalid key size {}", key.size());
|
||||
|
||||
ripple::uint256 ret;
|
||||
for (size_t i = 0; i < KEY_SIZE; ++i)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <data/LedgerCache.h>
|
||||
#include <util/Assert.h>
|
||||
|
||||
namespace data {
|
||||
|
||||
@@ -37,7 +38,12 @@ LedgerCache::update(std::vector<LedgerObject> const& objs, uint32_t seq, bool is
|
||||
{
|
||||
std::scoped_lock const lck{mtx_};
|
||||
if (seq > latestSeq_) {
|
||||
assert(seq == latestSeq_ + 1 || latestSeq_ == 0);
|
||||
ASSERT(
|
||||
seq == latestSeq_ + 1 || latestSeq_ == 0,
|
||||
"New sequense must be either next or first. seq = {}, latestSeq_ = {}",
|
||||
seq,
|
||||
latestSeq_
|
||||
);
|
||||
latestSeq_ = seq;
|
||||
}
|
||||
for (auto const& obj : objs) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <data/cassandra/Handle.h>
|
||||
#include <data/cassandra/Types.h>
|
||||
#include <data/cassandra/impl/AsyncExecutor.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/Expected.h>
|
||||
#include <util/log/Logger.h>
|
||||
|
||||
@@ -400,7 +401,7 @@ public:
|
||||
numReadRequestsOutstanding_ -= statements.size();
|
||||
|
||||
if (errorsCount > 0) {
|
||||
assert(errorsCount <= statements.size());
|
||||
ASSERT(errorsCount <= statements.size(), "Errors number cannot exceed statements number");
|
||||
counters_->registerReadError(errorsCount);
|
||||
counters_->registerReadFinished(statements.size() - errorsCount);
|
||||
throw DatabaseTimeout{};
|
||||
@@ -422,8 +423,18 @@ public:
|
||||
}
|
||||
);
|
||||
|
||||
assert(futures.size() == statements.size());
|
||||
assert(results.size() == statements.size());
|
||||
ASSERT(
|
||||
futures.size() == statements.size(),
|
||||
"Futures size must be equal to statements size. Got {} and {}",
|
||||
futures.size(),
|
||||
statements.size()
|
||||
);
|
||||
ASSERT(
|
||||
results.size() == statements.size(),
|
||||
"Results size must be equal to statements size. Got {} and {}",
|
||||
results.size(),
|
||||
statements.size()
|
||||
);
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -455,10 +466,7 @@ private:
|
||||
decrementOutstandingRequestCount()
|
||||
{
|
||||
// sanity check
|
||||
if (numWriteRequestsOutstanding_ == 0) {
|
||||
assert(false);
|
||||
throw std::runtime_error("decrementing num outstanding below 0");
|
||||
}
|
||||
ASSERT(numWriteRequestsOutstanding_ > 0, "Decrementing num outstanding below 0");
|
||||
size_t const cur = (--numWriteRequestsOutstanding_);
|
||||
{
|
||||
// mutex lock required to prevent race condition around spurious
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <util/Assert.h>
|
||||
|
||||
namespace etl {
|
||||
/**
|
||||
@@ -209,7 +210,7 @@ public:
|
||||
inline std::vector<ripple::uint256>
|
||||
getMarkers(size_t numMarkers)
|
||||
{
|
||||
assert(numMarkers <= 256);
|
||||
ASSERT(numMarkers <= 256, "Number of markers must be <= 256. Got: {}", numMarkers);
|
||||
|
||||
unsigned char const incr = 256 / numMarkers;
|
||||
|
||||
@@ -222,4 +223,4 @@ getMarkers(size_t numMarkers)
|
||||
}
|
||||
return markers;
|
||||
}
|
||||
} // namespace etl
|
||||
} // namespace etl
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <etl/ETLService.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/Constants.h>
|
||||
|
||||
#include <ripple/protocol/LedgerHeader.h>
|
||||
@@ -125,7 +126,7 @@ ETLService::monitor()
|
||||
cacheLoader_.load(rng->maxSequence);
|
||||
}
|
||||
|
||||
assert(rng);
|
||||
ASSERT(rng.has_value(), "Ledger range can't be null");
|
||||
uint32_t nextSequence = rng->maxSequence + 1;
|
||||
|
||||
LOG(log_.debug()) << "Database is populated. "
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <etl/ProbingSource.h>
|
||||
#include <etl/Source.h>
|
||||
#include <rpc/RPCHelpers.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/Profiler.h>
|
||||
#include <util/Random.h>
|
||||
#include <util/log/Logger.h>
|
||||
@@ -206,7 +207,7 @@ bool
|
||||
LoadBalancer::shouldPropagateTxnStream(Source* in) const
|
||||
{
|
||||
for (auto& src : sources_) {
|
||||
assert(src);
|
||||
ASSERT(src != nullptr, "Source is nullptr");
|
||||
|
||||
// We pick the first Source encountered that is connected
|
||||
if (src->isConnected())
|
||||
|
||||
@@ -794,7 +794,7 @@ private:
|
||||
uint32_t const sequence = std::stoll(minAndMax[0]);
|
||||
pairs.emplace_back(sequence, sequence);
|
||||
} else {
|
||||
assert(minAndMax.size() == 2);
|
||||
ASSERT(minAndMax.size() == 2, "Min and max should be of size 2. Got size = {}", minAndMax.size());
|
||||
uint32_t const min = std::stoll(minAndMax[0]);
|
||||
uint32_t const max = std::stoll(minAndMax[1]);
|
||||
pairs.emplace_back(min, max);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <data/BackendInterface.h>
|
||||
#include <etl/NFTHelpers.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/log/Logger.h>
|
||||
|
||||
#include <ripple/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
|
||||
@@ -60,7 +61,12 @@ public:
|
||||
<< " . prefix = " << ripple::strHex(std::string(1, prefix))
|
||||
<< " . nextPrefix_ = " << ripple::strHex(std::string(1, nextPrefix_));
|
||||
|
||||
assert(nextPrefix_ > prefix || nextPrefix_ == 0x00);
|
||||
ASSERT(
|
||||
nextPrefix_ > prefix || nextPrefix_ == 0x00,
|
||||
"Next prefix must be greater than current prefix. Got: nextPrefix_ = {}, prefix = {}",
|
||||
nextPrefix_,
|
||||
prefix
|
||||
);
|
||||
|
||||
cur_ = std::make_unique<org::xrpl::rpc::v1::GetLedgerDataResponse>();
|
||||
next_ = std::make_unique<org::xrpl::rpc::v1::GetLedgerDataResponse>();
|
||||
|
||||
@@ -134,10 +134,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (cache_.get().isFull()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
ASSERT(!cache_.get().isFull(), "Cache must not be full. seq = {}", seq);
|
||||
|
||||
if (!clioPeers_.empty()) {
|
||||
boost::asio::spawn(ioContext_.get(), [this, seq](boost::asio::yield_context yield) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <etl/SystemState.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/Profiler.h>
|
||||
#include <util/log/Logger.h>
|
||||
|
||||
@@ -76,7 +77,7 @@ public:
|
||||
void
|
||||
waitTillFinished()
|
||||
{
|
||||
assert(thread_.joinable());
|
||||
ASSERT(thread_.joinable(), "Extractor thread must be joinable");
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <etl/NFTHelpers.h>
|
||||
#include <etl/SystemState.h>
|
||||
#include <etl/impl/LedgerFetcher.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/LedgerUtils.h>
|
||||
#include <util/Profiler.h>
|
||||
#include <util/log/Logger.h>
|
||||
@@ -152,8 +153,7 @@ public:
|
||||
// check that database is actually empty
|
||||
auto rng = backend_->hardFetchLedgerRangeNoThrow();
|
||||
if (rng) {
|
||||
LOG(log_.fatal()) << "Database is not empty";
|
||||
assert(false);
|
||||
ASSERT(false, "Database is not empty");
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -189,50 +189,48 @@ public:
|
||||
size_t numWrites = 0;
|
||||
backend_->cache().setFull();
|
||||
|
||||
auto seconds =
|
||||
::util::timed<std::chrono::seconds>([this, edgeKeys = &edgeKeys, sequence, &numWrites]() {
|
||||
for (auto& key : *edgeKeys) {
|
||||
LOG(log_.debug()) << "Writing edge key = " << ripple::strHex(key);
|
||||
auto succ =
|
||||
backend_->cache().getSuccessor(*ripple::uint256::fromVoidChecked(key), sequence);
|
||||
if (succ)
|
||||
backend_->writeSuccessor(std::move(key), sequence, uint256ToString(succ->key));
|
||||
}
|
||||
auto seconds = ::util::timed<std::chrono::seconds>([this, edgeKeys = &edgeKeys, sequence, &numWrites] {
|
||||
for (auto& key : *edgeKeys) {
|
||||
LOG(log_.debug()) << "Writing edge key = " << ripple::strHex(key);
|
||||
auto succ = backend_->cache().getSuccessor(*ripple::uint256::fromVoidChecked(key), sequence);
|
||||
if (succ)
|
||||
backend_->writeSuccessor(std::move(key), sequence, uint256ToString(succ->key));
|
||||
}
|
||||
|
||||
ripple::uint256 prev = data::firstKey;
|
||||
while (auto cur = backend_->cache().getSuccessor(prev, sequence)) {
|
||||
assert(cur);
|
||||
if (prev == data::firstKey)
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(cur->key));
|
||||
ripple::uint256 prev = data::firstKey;
|
||||
while (auto cur = backend_->cache().getSuccessor(prev, sequence)) {
|
||||
ASSERT(cur.has_value(), "Succesor for key {} must exist", ripple::strHex(prev));
|
||||
if (prev == data::firstKey)
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(cur->key));
|
||||
|
||||
if (isBookDir(cur->key, cur->blob)) {
|
||||
auto base = getBookBase(cur->key);
|
||||
// make sure the base is not an actual object
|
||||
if (!backend_->cache().get(cur->key, sequence)) {
|
||||
auto succ = backend_->cache().getSuccessor(base, sequence);
|
||||
assert(succ);
|
||||
if (succ->key == cur->key) {
|
||||
LOG(log_.debug()) << "Writing book successor = " << ripple::strHex(base)
|
||||
<< " - " << ripple::strHex(cur->key);
|
||||
if (isBookDir(cur->key, cur->blob)) {
|
||||
auto base = getBookBase(cur->key);
|
||||
// make sure the base is not an actual object
|
||||
if (!backend_->cache().get(cur->key, sequence)) {
|
||||
auto succ = backend_->cache().getSuccessor(base, sequence);
|
||||
ASSERT(succ.has_value(), "Book base {} must have a successor", ripple::strHex(base));
|
||||
if (succ->key == cur->key) {
|
||||
LOG(log_.debug()) << "Writing book successor = " << ripple::strHex(base) << " - "
|
||||
<< ripple::strHex(cur->key);
|
||||
|
||||
backend_->writeSuccessor(
|
||||
uint256ToString(base), sequence, uint256ToString(cur->key)
|
||||
);
|
||||
}
|
||||
backend_->writeSuccessor(
|
||||
uint256ToString(base), sequence, uint256ToString(cur->key)
|
||||
);
|
||||
}
|
||||
|
||||
++numWrites;
|
||||
}
|
||||
|
||||
prev = cur->key;
|
||||
static constexpr std::size_t LOG_INTERVAL = 100000;
|
||||
if (numWrites % LOG_INTERVAL == 0 && numWrites != 0)
|
||||
LOG(log_.info()) << "Wrote " << numWrites << " book successors";
|
||||
++numWrites;
|
||||
}
|
||||
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::lastKey));
|
||||
++numWrites;
|
||||
});
|
||||
prev = cur->key;
|
||||
static constexpr std::size_t LOG_INTERVAL = 100000;
|
||||
if (numWrites % LOG_INTERVAL == 0 && numWrites != 0)
|
||||
LOG(log_.info()) << "Wrote " << numWrites << " book successors";
|
||||
}
|
||||
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::lastKey));
|
||||
++numWrites;
|
||||
});
|
||||
|
||||
LOG(log_.info()) << "Looping through cache and submitting all writes took " << seconds
|
||||
<< " seconds. numWrites = " << std::to_string(numWrites);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <data/BackendInterface.h>
|
||||
#include <etl/SystemState.h>
|
||||
#include <feed/SubscriptionManager.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/LedgerUtils.h>
|
||||
#include <util/log/Logger.h>
|
||||
|
||||
@@ -115,7 +116,7 @@ public:
|
||||
return backend_->fetchLedgerBySequence(ledgerSequence, yield);
|
||||
});
|
||||
|
||||
assert(lgr);
|
||||
ASSERT(lgr.has_value(), "Ledger must exist in database. Ledger sequence = {}", ledgerSequence);
|
||||
publish(*lgr);
|
||||
|
||||
return true;
|
||||
@@ -157,7 +158,7 @@ public:
|
||||
std::optional<ripple::Fees> fees = data::synchronousAndRetryOnTimeout([&](auto yield) {
|
||||
return backend_->fetchFees(lgrInfo.seq, yield);
|
||||
});
|
||||
assert(fees);
|
||||
ASSERT(fees.has_value(), "Fees must exist for ledger {}", lgrInfo.seq);
|
||||
|
||||
std::vector<data::TransactionAndMetadata> transactions =
|
||||
data::synchronousAndRetryOnTimeout([&](auto yield) {
|
||||
@@ -165,7 +166,7 @@ public:
|
||||
});
|
||||
|
||||
auto const ledgerRange = backend_->fetchLedgerRange();
|
||||
assert(ledgerRange);
|
||||
ASSERT(ledgerRange.has_value(), "Ledger range must exist");
|
||||
|
||||
std::string const range =
|
||||
std::to_string(ledgerRange->minSequence) + "-" + std::to_string(ledgerRange->maxSequence);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <etl/SystemState.h>
|
||||
#include <etl/impl/AmendmentBlock.h>
|
||||
#include <etl/impl/LedgerLoader.h>
|
||||
#include <util/Assert.h>
|
||||
#include <util/LedgerUtils.h>
|
||||
#include <util/Profiler.h>
|
||||
#include <util/log/Logger.h>
|
||||
@@ -113,7 +114,7 @@ public:
|
||||
void
|
||||
waitTillFinished()
|
||||
{
|
||||
assert(thread_.joinable());
|
||||
ASSERT(thread_.joinable(), "Transformer thread must be joinable");
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
@@ -228,7 +229,7 @@ private:
|
||||
|
||||
for (auto& obj : *(rawData.mutable_ledger_objects()->mutable_objects())) {
|
||||
auto key = ripple::uint256::fromVoidChecked(obj.key());
|
||||
assert(key);
|
||||
ASSERT(key.has_value(), "Failed to deserialize key from void");
|
||||
|
||||
cacheUpdates.push_back({*key, {obj.mutable_data()->begin(), obj.mutable_data()->end()}});
|
||||
LOG(log_.debug()) << "key = " << ripple::strHex(*key) << " - mod type = " << obj.mod_type();
|
||||
@@ -245,7 +246,7 @@ private:
|
||||
|
||||
if (isDeleted) {
|
||||
auto const old = backend_->cache().get(*key, lgrInfo.seq - 1);
|
||||
assert(old);
|
||||
ASSERT(old.has_value(), "Deleted object must be in cache");
|
||||
checkBookBase = isBookDir(*key, *old);
|
||||
} else {
|
||||
checkBookBase = isBookDir(*key, *blob);
|
||||
@@ -256,7 +257,11 @@ private:
|
||||
|
||||
auto const bookBase = getBookBase(*key);
|
||||
auto const oldFirstDir = backend_->cache().getSuccessor(bookBase, lgrInfo.seq - 1);
|
||||
assert(oldFirstDir);
|
||||
ASSERT(
|
||||
oldFirstDir.has_value(),
|
||||
"Book base must have a successor for lgrInfo.seq - 1 = {}",
|
||||
lgrInfo.seq - 1
|
||||
);
|
||||
|
||||
// We deleted the first directory, or we added a directory prior to the old first
|
||||
// directory
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <feed/SubscriptionManager.h>
|
||||
#include <rpc/BookChangesHelper.h>
|
||||
#include <rpc/RPCHelpers.h>
|
||||
#include <util/Assert.h>
|
||||
|
||||
namespace feed {
|
||||
|
||||
@@ -77,13 +78,13 @@ SubscriptionManager::subLedger(boost::asio::yield_context yield, SessionPtrType
|
||||
subscribeHelper(session, ledgerSubscribers_, [this](SessionPtrType session) { unsubLedger(session); });
|
||||
|
||||
auto ledgerRange = backend_->fetchLedgerRange();
|
||||
assert(ledgerRange);
|
||||
ASSERT(ledgerRange.has_value(), "Ledger range must be valid");
|
||||
auto lgrInfo = backend_->fetchLedgerBySequence(ledgerRange->maxSequence, yield);
|
||||
assert(lgrInfo);
|
||||
ASSERT(lgrInfo.has_value(), "Ledger must be valid");
|
||||
|
||||
std::optional<ripple::Fees> fees;
|
||||
fees = backend_->fetchFees(lgrInfo->seq, yield);
|
||||
assert(fees);
|
||||
ASSERT(fees.has_value(), "Fees must be valid");
|
||||
|
||||
std::string const range = std::to_string(ledgerRange->minSequence) + "-" + std::to_string(ledgerRange->maxSequence);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <rpc/Counters.h>
|
||||
#include <rpc/RPCEngine.h>
|
||||
#include <rpc/common/impl/HandlerProvider.h>
|
||||
#include <util/TerminationHandler.h>
|
||||
#include <util/config/Config.h>
|
||||
#include <util/prometheus/Prometheus.h>
|
||||
#include <web/RPCServerHandler.h>
|
||||
@@ -147,6 +148,7 @@ start(io_context& ioc, std::uint32_t numThreads)
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
try {
|
||||
util::setTerminationHandler();
|
||||
auto const configPath = parseCli(argc, argv);
|
||||
auto const config = ConfigReader::open(configPath);
|
||||
if (!config) {
|
||||
@@ -218,4 +220,8 @@ try {
|
||||
return EXIT_SUCCESS;
|
||||
} catch (std::exception const& e) {
|
||||
LOG(LogService::fatal()) << "Exit on exception: " << e.what();
|
||||
return EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
LOG(LogService::fatal()) << "Exit on exception: unknown";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <rpc/RPCHelpers.h>
|
||||
#include <rpc/common/Types.h>
|
||||
#include <rpc/common/Validators.h>
|
||||
#include <util/Assert.h>
|
||||
|
||||
namespace feed {
|
||||
class SubscriptionManager;
|
||||
@@ -129,7 +130,7 @@ private:
|
||||
} else if (stream == "book_changes") {
|
||||
subscriptions_->unsubBookChanges(session);
|
||||
} else {
|
||||
assert(false);
|
||||
ASSERT(false, "Unknown stream: {}", stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
src/util/Assert.h
Normal file
53
src/util/Assert.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/SourceLocation.h>
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<boost::stacktrace::stacktrace> : ostream_formatter {};
|
||||
|
||||
namespace util {
|
||||
|
||||
template <typename... Args>
|
||||
constexpr void
|
||||
assertImpl(
|
||||
SourceLocationType const location,
|
||||
char const* expression,
|
||||
bool const condition,
|
||||
fmt::format_string<Args...> format,
|
||||
Args&&... args
|
||||
)
|
||||
{
|
||||
if (!condition) {
|
||||
fmt::println(stderr, "Assertion '{}' failed at {}:{}:", expression, location.file_name(), location.line());
|
||||
fmt::println(stderr, format, std::forward<Args>(args)...);
|
||||
fmt::println(stderr, "Stacktrace:\n{}\n", boost::stacktrace::stacktrace());
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
#define ASSERT(condition, ...) util::assertImpl(CURRENT_SRC_LOCATION, #condition, (condition), __VA_ARGS__)
|
||||
@@ -18,6 +18,8 @@
|
||||
//==============================================================================
|
||||
#pragma once
|
||||
|
||||
#include <util/Assert.h>
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace util {
|
||||
@@ -28,7 +30,7 @@ public:
|
||||
static T
|
||||
uniform(T min, T max)
|
||||
{
|
||||
assert(min <= max);
|
||||
ASSERT(min <= max, "Min cannot be greater than max. min: {}, max: {}", min, max);
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
std::uniform_real_distribution<T> distribution(min, max);
|
||||
return distribution(generator_);
|
||||
|
||||
78
src/util/SourceLocation.h
Normal file
78
src/util/SourceLocation.h
Normal file
@@ -0,0 +1,78 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2022, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
|
||||
// this is used by fully compatible compilers like gcc
|
||||
#include <source_location>
|
||||
|
||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
|
||||
// this is used by clang on linux where source_location is still not out of
|
||||
// experimental headers
|
||||
#include <experimental/source_location>
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace util {
|
||||
|
||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
|
||||
using SourceLocationType = std::source_location;
|
||||
|
||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
|
||||
using SourceLocationType = std::experimental::source_location;
|
||||
|
||||
#else
|
||||
// A workaround for AppleClang that is lacking source_location atm.
|
||||
// TODO: remove this workaround when all compilers catch up to c++20
|
||||
class SourceLocation {
|
||||
char const* file_;
|
||||
std::size_t line_;
|
||||
|
||||
public:
|
||||
constexpr SourceLocation(char const* file, std::size_t line) : file_{file}, line_{line}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr std::string_view
|
||||
file_name() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
|
||||
constexpr std::size_t
|
||||
line() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
};
|
||||
using SourceLocationType = SourceLocation;
|
||||
#define SOURCE_LOCATION_OLD_API
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace util
|
||||
|
||||
#if defined(SOURCE_LOCATION_OLD_API)
|
||||
#define CURRENT_SRC_LOCATION util::SourceLocationType(__FILE__, __LINE__)
|
||||
#else
|
||||
#define CURRENT_SRC_LOCATION util::SourceLocationType::current()
|
||||
#endif
|
||||
50
src/util/TerminationHandler.cpp
Normal file
50
src/util/TerminationHandler.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <util/TerminationHandler.h>
|
||||
#include <util/log/Logger.h>
|
||||
|
||||
#include <boost/stacktrace.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace util {
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
terminationHandler()
|
||||
{
|
||||
try {
|
||||
LOG(LogService::fatal()) << "Exit on terminate. Backtrace:\n" << boost::stacktrace::stacktrace();
|
||||
} catch (...) {
|
||||
LOG(LogService::fatal()) << "Exit on terminate. Can't get backtrace.";
|
||||
}
|
||||
std::abort();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
setTerminationHandler()
|
||||
{
|
||||
std::set_terminate(terminationHandler);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
27
src/util/TerminationHandler.h
Normal file
27
src/util/TerminationHandler.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace util {
|
||||
|
||||
void
|
||||
setTerminationHandler();
|
||||
|
||||
} // namespace util
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/SourceLocation.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/json.hpp>
|
||||
@@ -35,58 +37,10 @@
|
||||
#include <boost/log/utility/setup/file.hpp>
|
||||
#include <boost/log/utility/setup/formatter_parser.hpp>
|
||||
|
||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
|
||||
// this is used by fully compatible compilers like gcc
|
||||
#include <source_location>
|
||||
|
||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
|
||||
// this is used by clang on linux where source_location is still not out of
|
||||
// experimental headers
|
||||
#include <experimental/source_location>
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace util {
|
||||
|
||||
class Config;
|
||||
|
||||
#if defined(HAS_SOURCE_LOCATION) && __has_builtin(__builtin_source_location)
|
||||
using SourceLocationType = std::source_location;
|
||||
#define CURRENT_SRC_LOCATION SourceLocationType::current()
|
||||
|
||||
#elif defined(HAS_EXPERIMENTAL_SOURCE_LOCATION)
|
||||
using SourceLocationType = std::experimental::source_location;
|
||||
#define CURRENT_SRC_LOCATION SourceLocationType::current()
|
||||
|
||||
#else
|
||||
// A workaround for AppleClang that is lacking source_location atm.
|
||||
// TODO: remove this workaround when all compilers catch up to c++20
|
||||
class SourceLocation {
|
||||
std::string_view file_;
|
||||
std::size_t line_;
|
||||
|
||||
public:
|
||||
SourceLocation(std::string_view file, std::size_t line) : file_{file}, line_{line}
|
||||
{
|
||||
}
|
||||
|
||||
std::string_view
|
||||
file_name() const
|
||||
{
|
||||
return file_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
line() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
};
|
||||
using SourceLocationType = SourceLocation;
|
||||
#define CURRENT_SRC_LOCATION SourceLocationType(__builtin_FILE(), __builtin_LINE())
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Skips evaluation of expensive argument lists if the given logger is disabled for the required severity level.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/Assert.h>
|
||||
#include <util/prometheus/Metrics.h>
|
||||
#include <util/prometheus/impl/AnyCounterBase.h>
|
||||
|
||||
@@ -64,7 +65,7 @@ struct AnyCounter : MetricBase, detail::AnyCounterBase<NumberType> {
|
||||
AnyCounter&
|
||||
operator+=(ValueType const value)
|
||||
{
|
||||
assert(value >= 0);
|
||||
ASSERT(value >= 0, "Cannot decrease a counter");
|
||||
this->pimpl_->add(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#include <util/prometheus/Counter.h>
|
||||
#include <util/prometheus/Gauge.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace util::prometheus {
|
||||
|
||||
MetricBase::MetricBase(std::string name, std::string labelsString)
|
||||
@@ -52,7 +50,7 @@ toString(MetricType type)
|
||||
case MetricType::SUMMARY:
|
||||
return "summary";
|
||||
default:
|
||||
assert(false);
|
||||
ASSERT(false, "Unknown metric type: {}", static_cast<int>(type));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -85,7 +83,7 @@ MetricsFamily::MetricBuilder MetricsFamily::defaultMetricBuilder =
|
||||
case MetricType::HISTOGRAM:
|
||||
[[fallthrough]];
|
||||
default:
|
||||
assert(false);
|
||||
ASSERT(false, "Unknown metric type: {}", static_cast<int>(type));
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <util/Assert.h>
|
||||
#include <util/prometheus/Prometheus.h>
|
||||
|
||||
namespace util::prometheus {
|
||||
@@ -28,9 +29,7 @@ MetricType&
|
||||
convertBaseTo(MetricBase& metricBase)
|
||||
{
|
||||
auto result = dynamic_cast<MetricType*>(&metricBase);
|
||||
assert(result != nullptr);
|
||||
if (result == nullptr)
|
||||
throw std::runtime_error("Failed to convert metric type");
|
||||
ASSERT(result != nullptr, "Failed to cast metric {} to the requested type", metricBase.name());
|
||||
return *result;
|
||||
}
|
||||
|
||||
@@ -162,7 +161,7 @@ PrometheusService::replaceInstance(std::unique_ptr<util::prometheus::PrometheusI
|
||||
util::prometheus::PrometheusInterface&
|
||||
PrometheusService::instance()
|
||||
{
|
||||
assert(instance_);
|
||||
ASSERT(instance_ != nullptr, "PrometheusService::instance() called before init()");
|
||||
return *instance_;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
#include <util/prometheus/Counter.h>
|
||||
#include <util/prometheus/Gauge.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace util::prometheus {
|
||||
|
||||
class PrometheusInterface {
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/Assert.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
|
||||
namespace util::prometheus::detail {
|
||||
@@ -55,7 +56,7 @@ public:
|
||||
// Move constructor should be used only used during initialization
|
||||
CounterImpl(CounterImpl&& other)
|
||||
{
|
||||
assert(other.value_ == 0);
|
||||
ASSERT(other.value_ == 0, "Move constructor should only be used during initialization");
|
||||
value_ = other.value_.exchange(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/Assert.h>
|
||||
#include <util/config/Config.h>
|
||||
#include <util/log/Logger.h>
|
||||
#include <web/IntervalSweepHandler.h>
|
||||
@@ -172,7 +173,7 @@ public:
|
||||
if (whitelistHandler_.get().isWhiteListed(ip))
|
||||
return;
|
||||
std::scoped_lock const lck{mtx_};
|
||||
assert(ipConnCount_[ip] > 0);
|
||||
ASSERT(ipConnCount_[ip] > 0, "Connection count for ip {} can't be 0", ip);
|
||||
ipConnCount_[ip]--;
|
||||
if (ipConnCount_[ip] == 0)
|
||||
ipConnCount_.erase(ip);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <web/IntervalSweepHandler.h>
|
||||
|
||||
#include <util/Assert.h>
|
||||
#include <util/Constants.h>
|
||||
#include <web/DOSGuard.h>
|
||||
|
||||
@@ -47,9 +48,9 @@ IntervalSweepHandler::~IntervalSweepHandler()
|
||||
void
|
||||
IntervalSweepHandler::setup(web::BaseDOSGuard* guard)
|
||||
{
|
||||
assert(dosGuard_ == nullptr);
|
||||
ASSERT(dosGuard_ == nullptr, "Cannot setup DOS guard more than once");
|
||||
dosGuard_ = guard;
|
||||
assert(dosGuard_ != nullptr);
|
||||
ASSERT(dosGuard_ != nullptr, "DOS guard must be not null");
|
||||
|
||||
createTimer();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <rpc/Errors.h>
|
||||
#include <util/Assert.h>
|
||||
#include <web/interface/ConnectionBase.h>
|
||||
|
||||
#include <boost/beast/http.hpp>
|
||||
@@ -82,7 +83,9 @@ public:
|
||||
case rpc::ClioError::rpcMALFORMED_ADDRESS:
|
||||
case rpc::ClioError::rpcINVALID_HOT_WALLET:
|
||||
case rpc::ClioError::rpcFIELD_NOT_FOUND_TRANSACTION:
|
||||
assert(false); // this should never happen
|
||||
ASSERT(
|
||||
false, "Unknown rpc error code {}", static_cast<int>(*clioCode)
|
||||
); // this should never happen
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <util/Assert.h>
|
||||
#include <util/Fixtures.h>
|
||||
#include <util/config/Config.h>
|
||||
|
||||
@@ -192,7 +193,7 @@ struct Custom {
|
||||
friend Custom
|
||||
tag_invoke(json::value_to_tag<Custom>, json::value const& value)
|
||||
{
|
||||
assert(value.is_object());
|
||||
ASSERT(value.is_object(), "Value must be an object");
|
||||
auto const& obj = value.as_object();
|
||||
return {obj.at("str").as_string().c_str(), obj.at("int").as_int64(), obj.at("bool").as_bool()};
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <util/TerminationHandler.h>
|
||||
#include <util/prometheus/Prometheus.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -23,6 +25,7 @@
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
util::setTerminationHandler();
|
||||
PrometheusService::init();
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
|
||||
@@ -225,6 +225,7 @@ TEST_F(BackendCountersMockPrometheusTest, registerWriteFinished)
|
||||
makeMock<GaugeInt>("backend_operations_current_number", "{operation=\"write_async\",status=\"pending\"}");
|
||||
auto& completedCounter =
|
||||
makeMock<CounterInt>("backend_operations_total_number", "{operation=\"write_async\",status=\"completed\"}");
|
||||
EXPECT_CALL(pendingCounter, value()).WillOnce(testing::Return(1));
|
||||
EXPECT_CALL(pendingCounter, add(-1));
|
||||
EXPECT_CALL(completedCounter, add(1));
|
||||
counters->registerWriteFinished();
|
||||
@@ -252,6 +253,7 @@ TEST_F(BackendCountersMockPrometheusTest, registerReadFinished)
|
||||
makeMock<GaugeInt>("backend_operations_current_number", "{operation=\"read_async\",status=\"pending\"}");
|
||||
auto& completedCounter =
|
||||
makeMock<CounterInt>("backend_operations_total_number", "{operation=\"read_async\",status=\"completed\"}");
|
||||
EXPECT_CALL(pendingCounter, value()).WillOnce(testing::Return(1));
|
||||
EXPECT_CALL(pendingCounter, add(-1));
|
||||
EXPECT_CALL(completedCounter, add(1));
|
||||
counters->registerReadFinished();
|
||||
@@ -271,6 +273,7 @@ TEST_F(BackendCountersMockPrometheusTest, registerReadError)
|
||||
makeMock<GaugeInt>("backend_operations_current_number", "{operation=\"read_async\",status=\"pending\"}");
|
||||
auto& errorCounter =
|
||||
makeMock<CounterInt>("backend_operations_total_number", "{operation=\"read_async\",status=\"error\"}");
|
||||
EXPECT_CALL(pendingCounter, value()).WillOnce(testing::Return(1));
|
||||
EXPECT_CALL(pendingCounter, add(-1));
|
||||
EXPECT_CALL(errorCounter, add(1));
|
||||
counters->registerReadError();
|
||||
|
||||
32
unittests/util/AssertTests.cpp
Normal file
32
unittests/util/AssertTests.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <util/Assert.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(AssertTests, assertTrue)
|
||||
{
|
||||
EXPECT_NO_THROW(ASSERT(true, "Should not fail"));
|
||||
}
|
||||
|
||||
TEST(AssertTests, assertFalse)
|
||||
{
|
||||
EXPECT_DEATH({ ASSERT(false, "failure"); }, "failure");
|
||||
}
|
||||
@@ -78,8 +78,7 @@ struct MockPrometheusImpl : PrometheusInterface {
|
||||
}
|
||||
auto* basePtr = it->second.get();
|
||||
auto* metricPtr = dynamic_cast<MetricType*>(basePtr);
|
||||
if (metricPtr == nullptr)
|
||||
throw std::runtime_error("Wrong metric type");
|
||||
ASSERT(metricPtr != nullptr, "Wrong metric type");
|
||||
return *metricPtr;
|
||||
}
|
||||
|
||||
@@ -101,8 +100,7 @@ struct MockPrometheusImpl : PrometheusInterface {
|
||||
}
|
||||
auto* ptr = metrics.emplace(key, std::move(metric)).first->second.get();
|
||||
auto metricPtr = dynamic_cast<MetricType*>(ptr);
|
||||
if (metricPtr == nullptr)
|
||||
throw std::runtime_error("Wrong metric type");
|
||||
ASSERT(metricPtr != nullptr, "Wrong metric type");
|
||||
return *metricPtr;
|
||||
}
|
||||
|
||||
@@ -137,8 +135,7 @@ struct WithMockPrometheus : virtual ::testing::Test {
|
||||
mockPrometheus()
|
||||
{
|
||||
auto* ptr = dynamic_cast<MockPrometheusImpl*>(&PrometheusService::instance());
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error("Wrong prometheus type");
|
||||
ASSERT(ptr != nullptr, "Wrong prometheus type");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
@@ -147,8 +144,7 @@ struct WithMockPrometheus : virtual ::testing::Test {
|
||||
makeMock(std::string name, std::string labelsString)
|
||||
{
|
||||
auto* mockPrometheusPtr = dynamic_cast<MockPrometheusImpl*>(&PrometheusService::instance());
|
||||
if (mockPrometheusPtr == nullptr)
|
||||
throw std::runtime_error("Wrong prometheus type");
|
||||
ASSERT(mockPrometheusPtr != nullptr, "Wrong prometheus type");
|
||||
|
||||
std::string const key = name + labelsString;
|
||||
mockPrometheusPtr->makeMetric<MetricType>(std::move(name), std::move(labelsString));
|
||||
@@ -159,7 +155,7 @@ struct WithMockPrometheus : virtual ::testing::Test {
|
||||
} else if constexpr (std::is_same_v<typename MetricType::ValueType, double>) {
|
||||
return mockPrometheusPtr->counterDoubleImpls[key];
|
||||
}
|
||||
throw std::runtime_error("Wrong metric type");
|
||||
ASSERT(false, "Wrong metric type");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user