mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
Merge pull request #1122 from jagerman/deabseil-mutexes
De-abseil, part 2: mutex, locks, (most) time
This commit is contained in:
commit
60f92f2f45
122 changed files with 492 additions and 8602 deletions
|
@ -3,7 +3,6 @@
|
||||||
#include <util/logging/logger.hpp>
|
#include <util/logging/logger.hpp>
|
||||||
#include <util/logging/ostream_logger.hpp>
|
#include <util/logging/ostream_logger.hpp>
|
||||||
|
|
||||||
#include <absl/synchronization/mutex.h>
|
|
||||||
#include <cxxopts.hpp>
|
#include <cxxopts.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -110,10 +109,6 @@ namespace
|
||||||
int
|
int
|
||||||
main(int argc, char* argv[])
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
#ifdef LOKINET_DEBUG
|
|
||||||
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
cxxopts::Options options(
|
cxxopts::Options options(
|
||||||
"lokinetctl",
|
"lokinetctl",
|
||||||
|
|
|
@ -102,10 +102,6 @@ main(int argc, char *argv[])
|
||||||
// SetUnhandledExceptionFilter(win32_signal_handler);
|
// SetUnhandledExceptionFilter(win32_signal_handler);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LOKINET_DEBUG
|
|
||||||
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
cxxopts::Options options(
|
cxxopts::Options options(
|
||||||
"lokinet",
|
"lokinet",
|
||||||
|
|
|
@ -23,38 +23,19 @@ namespace llarp
|
||||||
struct Config;
|
struct Config;
|
||||||
struct Crypto;
|
struct Crypto;
|
||||||
struct CryptoManager;
|
struct CryptoManager;
|
||||||
struct MetricsConfig;
|
|
||||||
struct RouterContact;
|
struct RouterContact;
|
||||||
namespace thread
|
namespace thread
|
||||||
{
|
{
|
||||||
class ThreadPool;
|
class ThreadPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
class DefaultManagerGuard;
|
|
||||||
class PublisherScheduler;
|
|
||||||
} // namespace metrics
|
|
||||||
|
|
||||||
namespace thread
|
|
||||||
{
|
|
||||||
class Scheduler;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Context
|
struct Context
|
||||||
{
|
{
|
||||||
/// get context from main pointer
|
/// get context from main pointer
|
||||||
static Context *
|
static Context *
|
||||||
Get(llarp_main *);
|
Get(llarp_main *);
|
||||||
|
|
||||||
Context();
|
Context() = default;
|
||||||
~Context();
|
|
||||||
|
|
||||||
// These come first, in this order.
|
|
||||||
// This ensures we get metric collection on shutdown
|
|
||||||
std::unique_ptr< thread::Scheduler > m_scheduler;
|
|
||||||
std::unique_ptr< metrics::DefaultManagerGuard > m_metricsManager;
|
|
||||||
std::unique_ptr< metrics::PublisherScheduler > m_metricsPublisher;
|
|
||||||
|
|
||||||
std::unique_ptr< Crypto > crypto;
|
std::unique_ptr< Crypto > crypto;
|
||||||
std::unique_ptr< CryptoManager > cryptoManager;
|
std::unique_ptr< CryptoManager > cryptoManager;
|
||||||
|
@ -123,9 +104,6 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
ReloadConfig();
|
ReloadConfig();
|
||||||
|
|
||||||
void
|
|
||||||
setupMetrics(const MetricsConfig &metricsConfig);
|
|
||||||
|
|
||||||
std::string configfile;
|
std::string configfile;
|
||||||
std::string pidfile;
|
std::string pidfile;
|
||||||
std::unique_ptr< std::promise< void > > closeWaiter;
|
std::unique_ptr< std::promise< void > > closeWaiter;
|
||||||
|
|
|
@ -4,21 +4,11 @@ set(LIB_UTIL_SRC
|
||||||
config/config.cpp
|
config/config.cpp
|
||||||
config/ini.cpp
|
config/ini.cpp
|
||||||
config/key_manager.cpp
|
config/key_manager.cpp
|
||||||
constants/defaults.cpp
|
|
||||||
constants/limits.cpp
|
constants/limits.cpp
|
||||||
constants/link_layer.cpp
|
|
||||||
constants/path.cpp
|
|
||||||
constants/proto.cpp
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp
|
${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp
|
||||||
util/aligned.cpp
|
|
||||||
util/bencode.cpp
|
util/bencode.cpp
|
||||||
util/bits.cpp
|
|
||||||
util/buffer.cpp
|
util/buffer.cpp
|
||||||
util/codel.cpp
|
|
||||||
util/common.cpp
|
|
||||||
util/encode.cpp
|
util/encode.cpp
|
||||||
util/endian.cpp
|
|
||||||
util/decaying_hashset.cpp
|
|
||||||
util/fs.cpp
|
util/fs.cpp
|
||||||
util/json.cpp
|
util/json.cpp
|
||||||
util/logging/android_logger.cpp
|
util/logging/android_logger.cpp
|
||||||
|
@ -31,32 +21,14 @@ set(LIB_UTIL_SRC
|
||||||
util/logging/win32_logger.cpp
|
util/logging/win32_logger.cpp
|
||||||
util/lokinet_init.c
|
util/lokinet_init.c
|
||||||
util/mem.cpp
|
util/mem.cpp
|
||||||
util/meta/memfn_traits.cpp
|
|
||||||
util/meta/memfn.cpp
|
|
||||||
util/meta/object.cpp
|
|
||||||
util/meta/traits.cpp
|
|
||||||
util/meta/variant.cpp
|
|
||||||
util/metrics/core.cpp
|
|
||||||
util/metrics/json_publisher.cpp
|
|
||||||
util/metrics/metrics.cpp
|
|
||||||
util/metrics/metrictank_publisher.cpp
|
|
||||||
util/metrics/stream_publisher.cpp
|
|
||||||
util/metrics/types.cpp
|
|
||||||
util/printer.cpp
|
util/printer.cpp
|
||||||
util/status.cpp
|
|
||||||
util/stopwatch.cpp
|
|
||||||
util/str.cpp
|
util/str.cpp
|
||||||
util/string_view.cpp
|
|
||||||
util/thread/logic.cpp
|
util/thread/logic.cpp
|
||||||
util/thread/queue_manager.cpp
|
util/thread/queue_manager.cpp
|
||||||
util/thread/queue.cpp
|
|
||||||
util/thread/scheduler.cpp
|
|
||||||
util/thread/thread_pool.cpp
|
util/thread/thread_pool.cpp
|
||||||
util/thread/threading.cpp
|
util/thread/threading.cpp
|
||||||
util/thread/threadpool.cpp
|
util/thread/threadpool.cpp
|
||||||
util/thread/timerqueue.cpp
|
|
||||||
util/time.cpp
|
util/time.cpp
|
||||||
util/types.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(${UTIL_LIB} STATIC ${LIB_UTIL_SRC})
|
add_library(${UTIL_LIB} STATIC ${LIB_UTIL_SRC})
|
||||||
|
@ -70,7 +42,7 @@ endif()
|
||||||
|
|
||||||
target_link_libraries(${UTIL_LIB} PUBLIC ${CRYPTOGRAPHY_LIB} ${LOG_LIB} ${CURL_LIBRARIES})
|
target_link_libraries(${UTIL_LIB} PUBLIC ${CRYPTOGRAPHY_LIB} ${LOG_LIB} ${CURL_LIBRARIES})
|
||||||
target_link_libraries(${UTIL_LIB} PUBLIC
|
target_link_libraries(${UTIL_LIB} PUBLIC
|
||||||
absl::synchronization absl::flat_hash_map absl::container
|
absl::time absl::hash
|
||||||
nlohmann_json::nlohmann_json
|
nlohmann_json::nlohmann_json
|
||||||
ghc_filesystem
|
ghc_filesystem
|
||||||
optional-lite
|
optional-lite
|
||||||
|
@ -78,7 +50,7 @@ target_link_libraries(${UTIL_LIB} PUBLIC
|
||||||
|
|
||||||
# cut back on fluff
|
# cut back on fluff
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
target_link_libraries(${UTIL_LIB} PUBLIC absl::variant absl::strings)
|
target_link_libraries(${UTIL_LIB} PUBLIC absl::strings)
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
|
@ -126,15 +98,12 @@ if(WIN32)
|
||||||
target_link_libraries(${PLATFORM_LIB} PUBLIC iphlpapi)
|
target_link_libraries(${PLATFORM_LIB} PUBLIC iphlpapi)
|
||||||
endif()
|
endif()
|
||||||
set(DNSLIB_SRC
|
set(DNSLIB_SRC
|
||||||
dns/dns.cpp
|
|
||||||
dns/message.cpp
|
dns/message.cpp
|
||||||
dns/name.cpp
|
dns/name.cpp
|
||||||
dns/query.cpp
|
|
||||||
dns/question.cpp
|
dns/question.cpp
|
||||||
dns/rr.cpp
|
dns/rr.cpp
|
||||||
dns/serialize.cpp
|
dns/serialize.cpp
|
||||||
dns/server.cpp
|
dns/server.cpp
|
||||||
dns/string.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(CONSENSUS_SRC
|
set(CONSENSUS_SRC
|
||||||
|
@ -146,19 +115,13 @@ set(LIB_SRC
|
||||||
${DNSLIB_SRC}
|
${DNSLIB_SRC}
|
||||||
bootstrap.cpp
|
bootstrap.cpp
|
||||||
context.cpp
|
context.cpp
|
||||||
crypto/constants.cpp
|
|
||||||
crypto/crypto_libsodium.cpp
|
crypto/crypto_libsodium.cpp
|
||||||
crypto/crypto_noop.cpp
|
|
||||||
crypto/crypto.cpp
|
crypto/crypto.cpp
|
||||||
crypto/encrypted_frame.cpp
|
crypto/encrypted_frame.cpp
|
||||||
crypto/encrypted.cpp
|
|
||||||
crypto/types.cpp
|
crypto/types.cpp
|
||||||
dht/bucket.cpp
|
|
||||||
dht/context.cpp
|
dht/context.cpp
|
||||||
dht/dht.cpp
|
dht/dht.cpp
|
||||||
dht/explorenetworkjob.cpp
|
dht/explorenetworkjob.cpp
|
||||||
dht/kademlia.cpp
|
|
||||||
dht/key.cpp
|
|
||||||
dht/localtaglookup.cpp
|
dht/localtaglookup.cpp
|
||||||
dht/localrouterlookup.cpp
|
dht/localrouterlookup.cpp
|
||||||
dht/localserviceaddresslookup.cpp
|
dht/localserviceaddresslookup.cpp
|
||||||
|
@ -168,21 +131,16 @@ set(LIB_SRC
|
||||||
dht/messages/gotintro.cpp
|
dht/messages/gotintro.cpp
|
||||||
dht/messages/gotrouter.cpp
|
dht/messages/gotrouter.cpp
|
||||||
dht/messages/pubintro.cpp
|
dht/messages/pubintro.cpp
|
||||||
dht/node.cpp
|
|
||||||
dht/publishservicejob.cpp
|
dht/publishservicejob.cpp
|
||||||
dht/recursiverouterlookup.cpp
|
dht/recursiverouterlookup.cpp
|
||||||
dht/serviceaddresslookup.cpp
|
dht/serviceaddresslookup.cpp
|
||||||
dht/taglookup.cpp
|
dht/taglookup.cpp
|
||||||
dht/tx.cpp
|
|
||||||
dht/txholder.cpp
|
|
||||||
dht/txowner.cpp
|
|
||||||
exit/context.cpp
|
exit/context.cpp
|
||||||
exit/endpoint.cpp
|
exit/endpoint.cpp
|
||||||
exit/exit_messages.cpp
|
exit/exit_messages.cpp
|
||||||
exit/policy.cpp
|
exit/policy.cpp
|
||||||
exit/session.cpp
|
exit/session.cpp
|
||||||
handlers/exit.cpp
|
handlers/exit.cpp
|
||||||
handlers/null.cpp
|
|
||||||
handlers/tun.cpp
|
handlers/tun.cpp
|
||||||
hook/shell.cpp
|
hook/shell.cpp
|
||||||
iwp/iwp.cpp
|
iwp/iwp.cpp
|
||||||
|
@ -190,15 +148,11 @@ set(LIB_SRC
|
||||||
iwp/message_buffer.cpp
|
iwp/message_buffer.cpp
|
||||||
iwp/session.cpp
|
iwp/session.cpp
|
||||||
link/factory.cpp
|
link/factory.cpp
|
||||||
link/i_link_manager.cpp
|
|
||||||
link/link_manager.cpp
|
link/link_manager.cpp
|
||||||
link/server.cpp
|
link/server.cpp
|
||||||
link/session.cpp
|
|
||||||
messages/dht_immediate.cpp
|
messages/dht_immediate.cpp
|
||||||
messages/discard.cpp
|
|
||||||
messages/link_intro.cpp
|
messages/link_intro.cpp
|
||||||
messages/link_message_parser.cpp
|
messages/link_message_parser.cpp
|
||||||
messages/link_message.cpp
|
|
||||||
messages/relay.cpp
|
messages/relay.cpp
|
||||||
messages/relay_commit.cpp
|
messages/relay_commit.cpp
|
||||||
messages/relay_status.cpp
|
messages/relay_status.cpp
|
||||||
|
@ -207,30 +161,22 @@ set(LIB_SRC
|
||||||
nodedb.cpp
|
nodedb.cpp
|
||||||
path/ihophandler.cpp
|
path/ihophandler.cpp
|
||||||
path/path_context.cpp
|
path/path_context.cpp
|
||||||
path/path_types.cpp
|
|
||||||
path/path.cpp
|
path/path.cpp
|
||||||
path/pathbuilder.cpp
|
path/pathbuilder.cpp
|
||||||
path/pathset.cpp
|
path/pathset.cpp
|
||||||
path/transit_hop.cpp
|
path/transit_hop.cpp
|
||||||
pow.cpp
|
pow.cpp
|
||||||
profiling.cpp
|
profiling.cpp
|
||||||
router/abstractrouter.cpp
|
|
||||||
router/i_outbound_message_handler.cpp
|
|
||||||
router/outbound_message_handler.cpp
|
router/outbound_message_handler.cpp
|
||||||
router/i_outbound_session_maker.cpp
|
|
||||||
router/outbound_session_maker.cpp
|
router/outbound_session_maker.cpp
|
||||||
router/i_rc_lookup_handler.cpp
|
|
||||||
router/rc_lookup_handler.cpp
|
router/rc_lookup_handler.cpp
|
||||||
router/i_gossiper.cpp
|
|
||||||
router/rc_gossiper.cpp
|
router/rc_gossiper.cpp
|
||||||
router/router.cpp
|
router/router.cpp
|
||||||
router_contact.cpp
|
router_contact.cpp
|
||||||
router_id.cpp
|
router_id.cpp
|
||||||
router_version.cpp
|
router_version.cpp
|
||||||
routing/dht_message.cpp
|
routing/dht_message.cpp
|
||||||
routing/handler.cpp
|
|
||||||
routing/message_parser.cpp
|
routing/message_parser.cpp
|
||||||
routing/message.cpp
|
|
||||||
routing/path_confirm_message.cpp
|
routing/path_confirm_message.cpp
|
||||||
routing/path_latency_message.cpp
|
routing/path_latency_message.cpp
|
||||||
routing/path_transfer_message.cpp
|
routing/path_transfer_message.cpp
|
||||||
|
@ -243,7 +189,6 @@ set(LIB_SRC
|
||||||
service/endpoint_state.cpp
|
service/endpoint_state.cpp
|
||||||
service/endpoint_util.cpp
|
service/endpoint_util.cpp
|
||||||
service/endpoint.cpp
|
service/endpoint.cpp
|
||||||
service/handler.cpp
|
|
||||||
service/hidden_service_address_lookup.cpp
|
service/hidden_service_address_lookup.cpp
|
||||||
service/identity.cpp
|
service/identity.cpp
|
||||||
service/info.cpp
|
service/info.cpp
|
||||||
|
@ -251,14 +196,12 @@ set(LIB_SRC
|
||||||
service/intro.cpp
|
service/intro.cpp
|
||||||
service/lookup.cpp
|
service/lookup.cpp
|
||||||
service/outbound_context.cpp
|
service/outbound_context.cpp
|
||||||
service/pendingbuffer.cpp
|
|
||||||
service/protocol.cpp
|
service/protocol.cpp
|
||||||
service/router_lookup_job.cpp
|
service/router_lookup_job.cpp
|
||||||
service/sendcontext.cpp
|
service/sendcontext.cpp
|
||||||
service/session.cpp
|
service/session.cpp
|
||||||
service/tag_lookup_job.cpp
|
service/tag_lookup_job.cpp
|
||||||
service/tag.cpp
|
service/tag.cpp
|
||||||
service/vanity.cpp
|
|
||||||
)
|
)
|
||||||
if(TESTNET)
|
if(TESTNET)
|
||||||
set(LIB_SRC ${LIB_SRC} testnet.c)
|
set(LIB_SRC ${LIB_SRC} testnet.c)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <util/logging/logger_syslog.hpp>
|
#include <util/logging/logger_syslog.hpp>
|
||||||
#include <util/logging/logger.hpp>
|
#include <util/logging/logger.hpp>
|
||||||
#include <util/mem.hpp>
|
#include <util/mem.hpp>
|
||||||
#include <util/meta/memfn.hpp>
|
|
||||||
#include <util/str.hpp>
|
#include <util/str.hpp>
|
||||||
#include <util/lokinet_init.h>
|
#include <util/lokinet_init.h>
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <constants/defaults.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <constants/link_layer.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <constants/path.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <constants/proto.hpp>
|
|
|
@ -11,12 +11,6 @@
|
||||||
#include <router/router.hpp>
|
#include <router/router.hpp>
|
||||||
#include <service/context.hpp>
|
#include <service/context.hpp>
|
||||||
#include <util/logging/logger.h>
|
#include <util/logging/logger.h>
|
||||||
#include <util/meta/memfn.hpp>
|
|
||||||
#include <util/metrics/json_publisher.hpp>
|
|
||||||
#include <util/metrics/metrics.hpp>
|
|
||||||
#include <util/metrics/metrictank_publisher.hpp>
|
|
||||||
#include <util/metrics/stream_publisher.hpp>
|
|
||||||
#include <util/thread/scheduler.hpp>
|
|
||||||
|
|
||||||
#include <absl/strings/str_split.h>
|
#include <absl/strings/str_split.h>
|
||||||
#include <cxxopts.hpp>
|
#include <cxxopts.hpp>
|
||||||
|
@ -28,14 +22,6 @@
|
||||||
|
|
||||||
namespace llarp
|
namespace llarp
|
||||||
{
|
{
|
||||||
Context::Context() = default;
|
|
||||||
|
|
||||||
Context::~Context()
|
|
||||||
{
|
|
||||||
if(m_scheduler)
|
|
||||||
m_scheduler->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Context::CallSafe(std::function< void(void) > f)
|
Context::CallSafe(std::function< void(void) > f)
|
||||||
{
|
{
|
||||||
|
@ -73,90 +59,9 @@ namespace llarp
|
||||||
|
|
||||||
nodedb_dir = config->netdb.nodedbDir();
|
nodedb_dir = config->netdb.nodedbDir();
|
||||||
|
|
||||||
if(!config->metrics.disableMetrics)
|
|
||||||
{
|
|
||||||
auto &metricsConfig = config->metrics;
|
|
||||||
auto &tags = metricsConfig.metricTags;
|
|
||||||
tags["netid"] = config->router.netId();
|
|
||||||
tags["nickname"] = config->router.nickname();
|
|
||||||
setupMetrics(metricsConfig);
|
|
||||||
if(!config->metrics.disableMetricLogs)
|
|
||||||
{
|
|
||||||
m_metricsManager->instance()->addGlobalPublisher(
|
|
||||||
std::make_shared< metrics::StreamPublisher >(std::cerr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Context::setupMetrics(const MetricsConfig &metricsConfig)
|
|
||||||
{
|
|
||||||
if(!m_scheduler)
|
|
||||||
{
|
|
||||||
m_scheduler = std::make_unique< thread::Scheduler >();
|
|
||||||
}
|
|
||||||
if(!m_metricsManager)
|
|
||||||
{
|
|
||||||
m_metricsManager = std::make_unique< metrics::DefaultManagerGuard >();
|
|
||||||
}
|
|
||||||
if(!m_metricsPublisher)
|
|
||||||
{
|
|
||||||
m_metricsPublisher = std::make_unique< metrics::PublisherScheduler >(
|
|
||||||
*m_scheduler, m_metricsManager->instance());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!metricsConfig.jsonMetricsPath.native().empty())
|
|
||||||
{
|
|
||||||
m_metricsManager->instance()->addGlobalPublisher(
|
|
||||||
std::make_shared< metrics::JsonPublisher >(
|
|
||||||
std::bind(&metrics::JsonPublisher::directoryPublisher,
|
|
||||||
std::placeholders::_1, metricsConfig.jsonMetricsPath)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!metricsConfig.metricTankHost.empty())
|
|
||||||
{
|
|
||||||
if(std::getenv("LOKINET_ENABLE_METRIC_TANK"))
|
|
||||||
{
|
|
||||||
static std::string WARNING = R"(
|
|
||||||
__ ___ ____ _ _ ___ _ _ ____
|
|
||||||
\ \ / / \ | _ \| \ | |_ _| \ | |/ ___|
|
|
||||||
\ \ /\ / / _ \ | |_) | \| || || \| | | _
|
|
||||||
\ V V / ___ \| _ <| |\ || || |\ | |_| |
|
|
||||||
\_/\_/_/ \_\_| \_\_| \_|___|_| \_|\____|
|
|
||||||
|
|
||||||
This Lokinet session is not private!!
|
|
||||||
|
|
||||||
Sending connection metrics to metrictank!!
|
|
||||||
__ ___ ____ _ _ ___ _ _ ____
|
|
||||||
\ \ / / \ | _ \| \ | |_ _| \ | |/ ___|
|
|
||||||
\ \ /\ / / _ \ | |_) | \| || || \| | | _
|
|
||||||
\ V V / ___ \| _ <| |\ || || |\ | |_| |
|
|
||||||
\_/\_/_/ \_\_| \_\_| \_|___|_| \_|\____|
|
|
||||||
|
|
||||||
)";
|
|
||||||
|
|
||||||
std::cerr << WARNING << '\n';
|
|
||||||
|
|
||||||
std::pair< std::string, std::string > split =
|
|
||||||
absl::StrSplit(metricsConfig.metricTankHost, ':');
|
|
||||||
|
|
||||||
m_metricsManager->instance()->addGlobalPublisher(
|
|
||||||
std::make_shared< metrics::MetricTankPublisher >(
|
|
||||||
metricsConfig.metricTags, split.first, stoi(split.second)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "metrictank host specified, but "
|
|
||||||
"LOKINET_ENABLE_METRIC_TANK not set, skipping\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_metricsPublisher->setDefault(absl::Seconds(30));
|
|
||||||
|
|
||||||
m_scheduler->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Context::SetPIDFile(const std::string &fname)
|
Context::SetPIDFile(const std::string &fname)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <crypto/constants.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <crypto/crypto_noop.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <crypto/encrypted.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dht/bucket.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dht/kademlia.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dht/key.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dht/node.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dht/tx.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dht/txholder.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dht/txowner.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dns/dns.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dns/query.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <dns/string.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <handlers/null.hpp>
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include <iwp/linklayer.hpp>
|
#include <iwp/linklayer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <router/abstractrouter.hpp>
|
#include <router/abstractrouter.hpp>
|
||||||
#include <util/meta/memfn.hpp>
|
|
||||||
|
|
||||||
namespace llarp
|
namespace llarp
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace llarp
|
||||||
bool isNewSession = false;
|
bool isNewSession = false;
|
||||||
if(itr == m_AuthedAddrs.end())
|
if(itr == m_AuthedAddrs.end())
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t lock, m_PendingMutex);
|
Lock_t lock(m_PendingMutex);
|
||||||
if(m_Pending.count(from) == 0)
|
if(m_Pending.count(from) == 0)
|
||||||
{
|
{
|
||||||
if(not permitInbound)
|
if(not permitInbound)
|
||||||
|
@ -60,7 +60,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t lock, m_AuthedLinksMutex);
|
Lock_t lock(m_AuthedLinksMutex);
|
||||||
auto range = m_AuthedLinks.equal_range(itr->second);
|
auto range = m_AuthedLinks.equal_range(itr->second);
|
||||||
session = range.first->second;
|
session = range.first->second;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <link/i_link_manager.hpp>
|
|
|
@ -76,7 +76,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
LinkManager::AddLink(LinkLayer_ptr link, bool inbound)
|
LinkManager::AddLink(LinkLayer_ptr link, bool inbound)
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
if(inbound)
|
if(inbound)
|
||||||
{
|
{
|
||||||
|
@ -128,7 +128,7 @@ namespace llarp
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
LogInfo("stopping links");
|
LogInfo("stopping links");
|
||||||
stopping = true;
|
stopping = true;
|
||||||
|
@ -145,7 +145,7 @@ namespace llarp
|
||||||
if(stopping)
|
if(stopping)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
m_PersistingSessions[remote] =
|
m_PersistingSessions[remote] =
|
||||||
std::max(until, m_PersistingSessions[remote]);
|
std::max(until, m_PersistingSessions[remote]);
|
||||||
|
@ -297,7 +297,7 @@ namespace llarp
|
||||||
std::vector< RouterID > sessionsNeeded;
|
std::vector< RouterID > sessionsNeeded;
|
||||||
|
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
auto itr = m_PersistingSessions.begin();
|
auto itr = m_PersistingSessions.begin();
|
||||||
while(itr != m_PersistingSessions.end())
|
while(itr != m_PersistingSessions.end())
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
ILinkLayer::HasSessionTo(const RouterID& id)
|
ILinkLayer::HasSessionTo(const RouterID& id)
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
return m_AuthedLinks.find(id) != m_AuthedLinks.end();
|
return m_AuthedLinks.find(id) != m_AuthedLinks.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
std::vector< std::shared_ptr< ILinkSession > > sessions;
|
std::vector< std::shared_ptr< ILinkSession > > sessions;
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
if(m_AuthedLinks.size() == 0)
|
if(m_AuthedLinks.size() == 0)
|
||||||
return;
|
return;
|
||||||
const size_t sz = randint() % m_AuthedLinks.size();
|
const size_t sz = randint() % m_AuthedLinks.size();
|
||||||
|
@ -84,7 +84,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
std::shared_ptr< ILinkSession > session;
|
std::shared_ptr< ILinkSession > session;
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
auto itr = m_AuthedLinks.find(pk);
|
auto itr = m_AuthedLinks.find(pk);
|
||||||
if(itr == m_AuthedLinks.end())
|
if(itr == m_AuthedLinks.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -98,7 +98,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
std::vector< std::shared_ptr< ILinkSession > > sessions;
|
std::vector< std::shared_ptr< ILinkSession > > sessions;
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
auto itr = m_AuthedLinks.begin();
|
auto itr = m_AuthedLinks.begin();
|
||||||
while(itr != m_AuthedLinks.end())
|
while(itr != m_AuthedLinks.end())
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ namespace llarp
|
||||||
std::vector< std::shared_ptr< ILinkSession > > closedPending;
|
std::vector< std::shared_ptr< ILinkSession > > closedPending;
|
||||||
auto _now = Now();
|
auto _now = Now();
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
auto itr = m_AuthedLinks.begin();
|
auto itr = m_AuthedLinks.begin();
|
||||||
while(itr != m_AuthedLinks.end())
|
while(itr != m_AuthedLinks.end())
|
||||||
{
|
{
|
||||||
|
@ -156,7 +156,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
|
Lock_t l(m_PendingMutex);
|
||||||
|
|
||||||
auto itr = m_Pending.begin();
|
auto itr = m_Pending.begin();
|
||||||
while(itr != m_Pending.end())
|
while(itr != m_Pending.end())
|
||||||
|
@ -176,7 +176,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
for(const auto& r : closedSessions)
|
for(const auto& r : closedSessions)
|
||||||
{
|
{
|
||||||
if(m_AuthedLinks.count(r) == 0)
|
if(m_AuthedLinks.count(r) == 0)
|
||||||
|
@ -196,8 +196,8 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
ILinkLayer::MapAddr(const RouterID& pk, ILinkSession* s)
|
ILinkLayer::MapAddr(const RouterID& pk, ILinkSession* s)
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l_authed, m_AuthedLinksMutex);
|
Lock_t l_authed(m_AuthedLinksMutex);
|
||||||
ACQUIRE_LOCK(Lock_t l_pending, m_PendingMutex);
|
Lock_t l_pending(m_PendingMutex);
|
||||||
llarp::Addr addr = s->GetRemoteEndpoint();
|
llarp::Addr addr = s->GetRemoteEndpoint();
|
||||||
auto itr = m_Pending.find(addr);
|
auto itr = m_Pending.find(addr);
|
||||||
if(itr != m_Pending.end())
|
if(itr != m_Pending.end())
|
||||||
|
@ -237,7 +237,7 @@ namespace llarp
|
||||||
std::vector< util::StatusObject > pending, established;
|
std::vector< util::StatusObject > pending, established;
|
||||||
|
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
|
Lock_t l(m_PendingMutex);
|
||||||
std::transform(m_Pending.cbegin(), m_Pending.cend(),
|
std::transform(m_Pending.cbegin(), m_Pending.cend(),
|
||||||
std::back_inserter(pending),
|
std::back_inserter(pending),
|
||||||
[](const auto& item) -> util::StatusObject {
|
[](const auto& item) -> util::StatusObject {
|
||||||
|
@ -245,7 +245,7 @@ namespace llarp
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
std::transform(m_AuthedLinks.cbegin(), m_AuthedLinks.cend(),
|
std::transform(m_AuthedLinks.cbegin(), m_AuthedLinks.cend(),
|
||||||
std::back_inserter(established),
|
std::back_inserter(established),
|
||||||
[](const auto& item) -> util::StatusObject {
|
[](const auto& item) -> util::StatusObject {
|
||||||
|
@ -265,7 +265,7 @@ namespace llarp
|
||||||
ILinkLayer::TryEstablishTo(RouterContact rc)
|
ILinkLayer::TryEstablishTo(RouterContact rc)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
if(m_AuthedLinks.count(rc.pubkey) >= MaxSessionsPerKey)
|
if(m_AuthedLinks.count(rc.pubkey) >= MaxSessionsPerKey)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ namespace llarp
|
||||||
return false;
|
return false;
|
||||||
const llarp::Addr addr(to);
|
const llarp::Addr addr(to);
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
|
Lock_t l(m_PendingMutex);
|
||||||
if(m_Pending.count(addr) >= MaxSessionsPerKey)
|
if(m_Pending.count(addr) >= MaxSessionsPerKey)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ namespace llarp
|
||||||
ILinkLayer::Tick(llarp_time_t now)
|
ILinkLayer::Tick(llarp_time_t now)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
auto itr = m_AuthedLinks.begin();
|
auto itr = m_AuthedLinks.begin();
|
||||||
while(itr != m_AuthedLinks.end())
|
while(itr != m_AuthedLinks.end())
|
||||||
{
|
{
|
||||||
|
@ -311,7 +311,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
|
Lock_t l(m_PendingMutex);
|
||||||
auto itr = m_Pending.begin();
|
auto itr = m_Pending.begin();
|
||||||
while(itr != m_Pending.end())
|
while(itr != m_Pending.end())
|
||||||
{
|
{
|
||||||
|
@ -338,7 +338,7 @@ namespace llarp
|
||||||
if(m_Logic && tick_id)
|
if(m_Logic && tick_id)
|
||||||
m_Logic->remove_call(tick_id);
|
m_Logic->remove_call(tick_id);
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
auto itr = m_AuthedLinks.begin();
|
auto itr = m_AuthedLinks.begin();
|
||||||
while(itr != m_AuthedLinks.end())
|
while(itr != m_AuthedLinks.end())
|
||||||
{
|
{
|
||||||
|
@ -347,7 +347,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_PendingMutex);
|
Lock_t l(m_PendingMutex);
|
||||||
auto itr = m_Pending.begin();
|
auto itr = m_Pending.begin();
|
||||||
while(itr != m_Pending.end())
|
while(itr != m_Pending.end())
|
||||||
{
|
{
|
||||||
|
@ -362,7 +362,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
static constexpr llarp_time_t CloseGraceWindow = 500;
|
static constexpr llarp_time_t CloseGraceWindow = 500;
|
||||||
const auto now = Now();
|
const auto now = Now();
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
RouterID r = remote;
|
RouterID r = remote;
|
||||||
llarp::LogInfo("Closing all to ", r);
|
llarp::LogInfo("Closing all to ", r);
|
||||||
auto range = m_AuthedLinks.equal_range(r);
|
auto range = m_AuthedLinks.equal_range(r);
|
||||||
|
@ -379,7 +379,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
ILinkLayer::KeepAliveSessionTo(const RouterID& remote)
|
ILinkLayer::KeepAliveSessionTo(const RouterID& remote)
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
auto range = m_AuthedLinks.equal_range(remote);
|
auto range = m_AuthedLinks.equal_range(remote);
|
||||||
auto itr = range.first;
|
auto itr = range.first;
|
||||||
while(itr != range.second)
|
while(itr != range.second)
|
||||||
|
@ -396,7 +396,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
std::shared_ptr< ILinkSession > s;
|
std::shared_ptr< ILinkSession > s;
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t l, m_AuthedLinksMutex);
|
Lock_t l(m_AuthedLinksMutex);
|
||||||
auto range = m_AuthedLinks.equal_range(remote);
|
auto range = m_AuthedLinks.equal_range(remote);
|
||||||
auto itr = range.first;
|
auto itr = range.first;
|
||||||
// pick lowest backlog session
|
// pick lowest backlog session
|
||||||
|
@ -445,7 +445,7 @@ namespace llarp
|
||||||
ILinkLayer::PutSession(const std::shared_ptr< ILinkSession >& s)
|
ILinkLayer::PutSession(const std::shared_ptr< ILinkSession >& s)
|
||||||
{
|
{
|
||||||
static constexpr size_t MaxSessionsPerEndpoint = 5;
|
static constexpr size_t MaxSessionsPerEndpoint = 5;
|
||||||
ACQUIRE_LOCK(Lock_t lock, m_PendingMutex);
|
Lock_t lock(m_PendingMutex);
|
||||||
llarp::Addr addr = s->GetRemoteEndpoint();
|
llarp::Addr addr = s->GetRemoteEndpoint();
|
||||||
if(m_Pending.count(addr) >= MaxSessionsPerEndpoint)
|
if(m_Pending.count(addr) >= MaxSessionsPerEndpoint)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -74,12 +74,11 @@ namespace llarp
|
||||||
|
|
||||||
void
|
void
|
||||||
ForEachSession(std::function< void(const ILinkSession*) > visit,
|
ForEachSession(std::function< void(const ILinkSession*) > visit,
|
||||||
bool randomize = false) const
|
bool randomize = false) const EXCLUDES(m_AuthedLinksMutex);
|
||||||
LOCKS_EXCLUDED(m_AuthedLinksMutex);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ForEachSession(std::function< void(ILinkSession*) > visit)
|
ForEachSession(std::function< void(ILinkSession*) > visit)
|
||||||
LOCKS_EXCLUDED(m_AuthedLinksMutex);
|
EXCLUDES(m_AuthedLinksMutex);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
udp_tick(llarp_udp_io* udp);
|
udp_tick(llarp_udp_io* udp);
|
||||||
|
@ -120,7 +119,7 @@ namespace llarp
|
||||||
Name() const = 0;
|
Name() const = 0;
|
||||||
|
|
||||||
util::StatusObject
|
util::StatusObject
|
||||||
ExtractStatus() const LOCKS_EXCLUDED(m_AuthedLinksMutex);
|
ExtractStatus() const EXCLUDES(m_AuthedLinksMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
CloseSessionTo(const RouterID& remote);
|
CloseSessionTo(const RouterID& remote);
|
||||||
|
@ -138,7 +137,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
VisitSessionByPubkey(const RouterID& pk,
|
VisitSessionByPubkey(const RouterID& pk,
|
||||||
std::function< bool(ILinkSession*) > visit)
|
std::function< bool(ILinkSession*) > visit)
|
||||||
LOCKS_EXCLUDED(m_AuthedLinksMutex);
|
EXCLUDES(m_AuthedLinksMutex);
|
||||||
|
|
||||||
virtual uint16_t
|
virtual uint16_t
|
||||||
Rank() const = 0;
|
Rank() const = 0;
|
||||||
|
@ -196,13 +195,13 @@ namespace llarp
|
||||||
|
|
||||||
/// called by link session to remove a pending session who is timed out
|
/// called by link session to remove a pending session who is timed out
|
||||||
// void
|
// void
|
||||||
// RemovePending(ILinkSession* s) LOCKS_EXCLUDED(m_PendingMutex);
|
// RemovePending(ILinkSession* s) EXCLUDES(m_PendingMutex);
|
||||||
|
|
||||||
/// count the number of sessions that are yet to be fully connected
|
/// count the number of sessions that are yet to be fully connected
|
||||||
size_t
|
size_t
|
||||||
NumberOfPendingSessions() const
|
NumberOfPendingSessions() const
|
||||||
{
|
{
|
||||||
ACQUIRE_LOCK(Lock_t lock, m_PendingMutex);
|
Lock_t lock(m_PendingMutex);
|
||||||
return m_Pending.size();
|
return m_Pending.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <link/session.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <messages/discard.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <messages/link_message.hpp>
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <router_contact.hpp>
|
#include <router_contact.hpp>
|
||||||
#include <util/buffer.hpp>
|
#include <util/buffer.hpp>
|
||||||
#include <util/logging/logger.hpp>
|
#include <util/logging/logger.hpp>
|
||||||
#include <util/metrics/metrics.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -69,12 +68,10 @@ namespace llarp
|
||||||
}
|
}
|
||||||
// create the message to parse based off message type
|
// create the message to parse based off message type
|
||||||
llarp::LogDebug("inbound message ", *strbuf.cur);
|
llarp::LogDebug("inbound message ", *strbuf.cur);
|
||||||
bool isLIM = false;
|
|
||||||
switch(*strbuf.cur)
|
switch(*strbuf.cur)
|
||||||
{
|
{
|
||||||
case 'i':
|
case 'i':
|
||||||
msg = &holder->i;
|
msg = &holder->i;
|
||||||
isLIM = true;
|
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
msg = &holder->d;
|
msg = &holder->d;
|
||||||
|
@ -98,12 +95,6 @@ namespace llarp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isLIM)
|
|
||||||
{
|
|
||||||
metrics::integerTick(msg->Name(), "RX", 1, "id",
|
|
||||||
RouterID(from->GetPubKey()).ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->session = from;
|
msg->session = from;
|
||||||
firstkey = false;
|
firstkey = false;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -43,14 +43,14 @@ llarp_nodedb::Remove(const llarp::RouterID &pk)
|
||||||
void
|
void
|
||||||
llarp_nodedb::Clear()
|
llarp_nodedb::Clear()
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
entries.clear();
|
entries.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
llarp_nodedb::Get(const llarp::RouterID &pk, llarp::RouterContact &result)
|
llarp_nodedb::Get(const llarp::RouterID &pk, llarp::RouterContact &result)
|
||||||
{
|
{
|
||||||
llarp::util::Lock l(&access);
|
llarp::util::Lock l(access);
|
||||||
auto itr = entries.find(pk);
|
auto itr = entries.find(pk);
|
||||||
if(itr == entries.end())
|
if(itr == entries.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -71,7 +71,7 @@ llarp_nodedb::RemoveIf(
|
||||||
{
|
{
|
||||||
std::set< std::string > files;
|
std::set< std::string > files;
|
||||||
{
|
{
|
||||||
llarp::util::Lock l(&access);
|
llarp::util::Lock l(access);
|
||||||
auto itr = entries.begin();
|
auto itr = entries.begin();
|
||||||
while(itr != entries.end())
|
while(itr != entries.end())
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,7 @@ llarp_nodedb::RemoveIf(
|
||||||
bool
|
bool
|
||||||
llarp_nodedb::Has(const llarp::RouterID &pk)
|
llarp_nodedb::Has(const llarp::RouterID &pk)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
return entries.find(pk) != entries.end();
|
return entries.find(pk) != entries.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ std::vector< llarp::RouterContact >
|
||||||
llarp_nodedb::FindClosestTo(const llarp::dht::Key_t &location,
|
llarp_nodedb::FindClosestTo(const llarp::dht::Key_t &location,
|
||||||
uint32_t numRouters)
|
uint32_t numRouters)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
std::vector< const llarp::RouterContact * > all;
|
std::vector< const llarp::RouterContact * > all;
|
||||||
|
|
||||||
all.reserve(entries.size());
|
all.reserve(entries.size());
|
||||||
|
@ -180,7 +180,7 @@ llarp_nodedb::UpdateAsyncIfNewer(llarp::RouterContact rc,
|
||||||
std::shared_ptr< llarp::Logic > logic,
|
std::shared_ptr< llarp::Logic > logic,
|
||||||
std::function< void(void) > completionHandler)
|
std::function< void(void) > completionHandler)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
auto itr = entries.find(rc.pubkey);
|
auto itr = entries.find(rc.pubkey);
|
||||||
if(itr == entries.end() || itr->second.rc.OtherIsNewer(rc))
|
if(itr == entries.end() || itr->second.rc.OtherIsNewer(rc))
|
||||||
{
|
{
|
||||||
|
@ -201,7 +201,7 @@ llarp_nodedb::UpdateAsyncIfNewer(llarp::RouterContact rc,
|
||||||
bool
|
bool
|
||||||
llarp_nodedb::Insert(const llarp::RouterContact &rc)
|
llarp_nodedb::Insert(const llarp::RouterContact &rc)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
auto itr = entries.find(rc.pubkey.as_array());
|
auto itr = entries.find(rc.pubkey.as_array());
|
||||||
if(itr != entries.end())
|
if(itr != entries.end())
|
||||||
entries.erase(itr);
|
entries.erase(itr);
|
||||||
|
@ -241,7 +241,7 @@ void
|
||||||
llarp_nodedb::SaveAll()
|
llarp_nodedb::SaveAll()
|
||||||
{
|
{
|
||||||
std::array< byte_t, MAX_RC_SIZE > tmp;
|
std::array< byte_t, MAX_RC_SIZE > tmp;
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
for(const auto &item : entries)
|
for(const auto &item : entries)
|
||||||
{
|
{
|
||||||
llarp_buffer_t buf(tmp);
|
llarp_buffer_t buf(tmp);
|
||||||
|
@ -307,7 +307,7 @@ llarp_nodedb::loadfile(const fs::path &fpath)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
entries.emplace(rc.pubkey.as_array(), rc);
|
entries.emplace(rc.pubkey.as_array(), rc);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -316,7 +316,7 @@ llarp_nodedb::loadfile(const fs::path &fpath)
|
||||||
void
|
void
|
||||||
llarp_nodedb::visit(std::function< bool(const llarp::RouterContact &) > visit)
|
llarp_nodedb::visit(std::function< bool(const llarp::RouterContact &) > visit)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
auto itr = entries.begin();
|
auto itr = entries.begin();
|
||||||
while(itr != entries.end())
|
while(itr != entries.end())
|
||||||
{
|
{
|
||||||
|
@ -331,7 +331,7 @@ llarp_nodedb::VisitInsertedBefore(
|
||||||
std::function< void(const llarp::RouterContact &) > visit,
|
std::function< void(const llarp::RouterContact &) > visit,
|
||||||
llarp_time_t insertedAfter)
|
llarp_time_t insertedAfter)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
auto itr = entries.begin();
|
auto itr = entries.begin();
|
||||||
while(itr != entries.end())
|
while(itr != entries.end())
|
||||||
{
|
{
|
||||||
|
@ -487,14 +487,14 @@ llarp_nodedb::LoadAll()
|
||||||
size_t
|
size_t
|
||||||
llarp_nodedb::num_loaded() const
|
llarp_nodedb::num_loaded() const
|
||||||
{
|
{
|
||||||
absl::ReaderMutexLock l(&access);
|
auto l = llarp::util::shared_lock(access);
|
||||||
return entries.size();
|
return entries.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
llarp_nodedb::select_random_exit(llarp::RouterContact &result)
|
llarp_nodedb::select_random_exit(llarp::RouterContact &result)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
const auto sz = entries.size();
|
const auto sz = entries.size();
|
||||||
auto itr = entries.begin();
|
auto itr = entries.begin();
|
||||||
if(sz < 3)
|
if(sz < 3)
|
||||||
|
@ -529,7 +529,7 @@ bool
|
||||||
llarp_nodedb::select_random_hop(const llarp::RouterContact &prev,
|
llarp_nodedb::select_random_hop(const llarp::RouterContact &prev,
|
||||||
llarp::RouterContact &result, size_t N)
|
llarp::RouterContact &result, size_t N)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
/// checking for "guard" status for N = 0 is done by caller inside of
|
/// checking for "guard" status for N = 0 is done by caller inside of
|
||||||
/// pathbuilder's scope
|
/// pathbuilder's scope
|
||||||
size_t sz = entries.size();
|
size_t sz = entries.size();
|
||||||
|
@ -575,7 +575,7 @@ bool
|
||||||
llarp_nodedb::select_random_hop_excluding(
|
llarp_nodedb::select_random_hop_excluding(
|
||||||
llarp::RouterContact &result, const std::set< llarp::RouterID > &exclude)
|
llarp::RouterContact &result, const std::set< llarp::RouterID > &exclude)
|
||||||
{
|
{
|
||||||
llarp::util::Lock lock(&access);
|
llarp::util::Lock lock(access);
|
||||||
/// checking for "guard" status for N = 0 is done by caller inside of
|
/// checking for "guard" status for N = 0 is done by caller inside of
|
||||||
/// pathbuilder's scope
|
/// pathbuilder's scope
|
||||||
const size_t sz = entries.size();
|
const size_t sz = entries.size();
|
||||||
|
|
|
@ -6,10 +6,9 @@
|
||||||
#include <util/common.hpp>
|
#include <util/common.hpp>
|
||||||
#include <util/fs.hpp>
|
#include <util/fs.hpp>
|
||||||
#include <util/thread/threading.hpp>
|
#include <util/thread/threading.hpp>
|
||||||
|
#include <util/thread/annotations.hpp>
|
||||||
#include <dht/key.hpp>
|
#include <dht/key.hpp>
|
||||||
|
|
||||||
#include <absl/base/thread_annotations.h>
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -86,28 +85,27 @@ struct llarp_nodedb
|
||||||
ShouldSaveToDisk(llarp_time_t now = 0) const;
|
ShouldSaveToDisk(llarp_time_t now = 0) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Remove(const llarp::RouterID &pk) LOCKS_EXCLUDED(access);
|
Remove(const llarp::RouterID &pk) EXCLUDES(access);
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoveIf(std::function< bool(const llarp::RouterContact &) > filter)
|
RemoveIf(std::function< bool(const llarp::RouterContact &) > filter)
|
||||||
LOCKS_EXCLUDED(access);
|
EXCLUDES(access);
|
||||||
|
|
||||||
void
|
void
|
||||||
Clear() LOCKS_EXCLUDED(access);
|
Clear() EXCLUDES(access);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Get(const llarp::RouterID &pk, llarp::RouterContact &result)
|
Get(const llarp::RouterID &pk, llarp::RouterContact &result) EXCLUDES(access);
|
||||||
LOCKS_EXCLUDED(access);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Has(const llarp::RouterID &pk) LOCKS_EXCLUDED(access);
|
Has(const llarp::RouterID &pk) EXCLUDES(access);
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
getRCFilePath(const llarp::RouterID &pubkey) const;
|
getRCFilePath(const llarp::RouterID &pubkey) const;
|
||||||
|
|
||||||
/// insert without writing to disk
|
/// insert without writing to disk
|
||||||
bool
|
bool
|
||||||
Insert(const llarp::RouterContact &rc) LOCKS_EXCLUDED(access);
|
Insert(const llarp::RouterContact &rc) EXCLUDES(access);
|
||||||
|
|
||||||
/// invokes Insert() asynchronously with an optional completion
|
/// invokes Insert() asynchronously with an optional completion
|
||||||
/// callback
|
/// callback
|
||||||
|
@ -123,7 +121,7 @@ struct llarp_nodedb
|
||||||
UpdateAsyncIfNewer(llarp::RouterContact rc,
|
UpdateAsyncIfNewer(llarp::RouterContact rc,
|
||||||
std::shared_ptr< llarp::Logic > l = nullptr,
|
std::shared_ptr< llarp::Logic > l = nullptr,
|
||||||
std::function< void(void) > completionHandler = nullptr)
|
std::function< void(void) > completionHandler = nullptr)
|
||||||
LOCKS_EXCLUDED(access);
|
EXCLUDES(access);
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
Load(const fs::path &path);
|
Load(const fs::path &path);
|
||||||
|
@ -135,11 +133,11 @@ struct llarp_nodedb
|
||||||
AsyncFlushToDisk();
|
AsyncFlushToDisk();
|
||||||
|
|
||||||
bool
|
bool
|
||||||
loadfile(const fs::path &fpath) LOCKS_EXCLUDED(access);
|
loadfile(const fs::path &fpath) EXCLUDES(access);
|
||||||
|
|
||||||
void
|
void
|
||||||
visit(std::function< bool(const llarp::RouterContact &) > visit)
|
visit(std::function< bool(const llarp::RouterContact &) > visit)
|
||||||
LOCKS_EXCLUDED(access);
|
EXCLUDES(access);
|
||||||
|
|
||||||
void
|
void
|
||||||
set_dir(const char *dir);
|
set_dir(const char *dir);
|
||||||
|
@ -153,32 +151,31 @@ struct llarp_nodedb
|
||||||
/// visit all entries inserted into nodedb cache before a timestamp
|
/// visit all entries inserted into nodedb cache before a timestamp
|
||||||
void
|
void
|
||||||
VisitInsertedBefore(std::function< void(const llarp::RouterContact &) > visit,
|
VisitInsertedBefore(std::function< void(const llarp::RouterContact &) > visit,
|
||||||
llarp_time_t insertedAfter) LOCKS_EXCLUDED(access);
|
llarp_time_t insertedAfter) EXCLUDES(access);
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoveStaleRCs(const std::set< llarp::RouterID > &keep, llarp_time_t cutoff);
|
RemoveStaleRCs(const std::set< llarp::RouterID > &keep, llarp_time_t cutoff);
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
num_loaded() const LOCKS_EXCLUDED(access);
|
num_loaded() const EXCLUDES(access);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
select_random_exit(llarp::RouterContact &rc) LOCKS_EXCLUDED(access);
|
select_random_exit(llarp::RouterContact &rc) EXCLUDES(access);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
select_random_hop(const llarp::RouterContact &prev,
|
select_random_hop(const llarp::RouterContact &prev,
|
||||||
llarp::RouterContact &result, size_t N)
|
llarp::RouterContact &result, size_t N) EXCLUDES(access);
|
||||||
LOCKS_EXCLUDED(access);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
select_random_hop_excluding(llarp::RouterContact &result,
|
select_random_hop_excluding(llarp::RouterContact &result,
|
||||||
const std::set< llarp::RouterID > &exclude)
|
const std::set< llarp::RouterID > &exclude)
|
||||||
LOCKS_EXCLUDED(access);
|
EXCLUDES(access);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ensure_dir(const char *dir);
|
ensure_dir(const char *dir);
|
||||||
|
|
||||||
void
|
void
|
||||||
SaveAll() LOCKS_EXCLUDED(access);
|
SaveAll() EXCLUDES(access);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// struct for async rc verification
|
/// struct for async rc verification
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace llarp
|
||||||
HopHandler_ptr
|
HopHandler_ptr
|
||||||
MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
|
MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
|
||||||
{
|
{
|
||||||
Lock_t lock(&map.first);
|
Lock_t lock(map.first);
|
||||||
auto range = map.second.equal_range(k);
|
auto range = map.second.equal_range(k);
|
||||||
for(auto i = range.first; i != range.second; ++i)
|
for(auto i = range.first; i != range.second; ++i)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +120,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
|
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
|
||||||
{
|
{
|
||||||
Lock_t lock(&map.first);
|
Lock_t lock(map.first);
|
||||||
auto range = map.second.equal_range(k);
|
auto range = map.second.equal_range(k);
|
||||||
for(auto i = range.first; i != range.second; ++i)
|
for(auto i = range.first; i != range.second; ++i)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +135,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
|
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
|
||||||
{
|
{
|
||||||
Lock_t lock(&map.first);
|
Lock_t lock(map.first);
|
||||||
map.second.emplace(k, v);
|
map.second.emplace(k, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +168,8 @@ namespace llarp
|
||||||
PathContext::AddOwnPath(PathSet_ptr set, Path_ptr path)
|
PathContext::AddOwnPath(PathSet_ptr set, Path_ptr path)
|
||||||
{
|
{
|
||||||
set->AddPath(path);
|
set->AddPath(path);
|
||||||
MapPut< SyncOwnedPathsMap_t::Lock_t >(m_OurPaths, path->TXID(), path);
|
MapPut< util::Lock >(m_OurPaths, path->TXID(), path);
|
||||||
MapPut< SyncOwnedPathsMap_t::Lock_t >(m_OurPaths, path->RXID(), path);
|
MapPut< util::Lock >(m_OurPaths, path->RXID(), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -185,7 +185,7 @@ namespace llarp
|
||||||
HopHandler_ptr
|
HopHandler_ptr
|
||||||
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
|
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
|
||||||
{
|
{
|
||||||
auto own = MapGet< SyncOwnedPathsMap_t::Lock_t >(
|
auto own = MapGet< util::Lock >(
|
||||||
m_OurPaths, id,
|
m_OurPaths, id,
|
||||||
[](const Path_ptr) -> bool {
|
[](const Path_ptr) -> bool {
|
||||||
// TODO: is this right?
|
// TODO: is this right?
|
||||||
|
@ -209,7 +209,7 @@ namespace llarp
|
||||||
PathContext::TransitHopPreviousIsRouter(const PathID_t& path,
|
PathContext::TransitHopPreviousIsRouter(const PathID_t& path,
|
||||||
const RouterID& otherRouter)
|
const RouterID& otherRouter)
|
||||||
{
|
{
|
||||||
SyncTransitMap_t::Lock_t lock(&m_TransitPaths.first);
|
SyncTransitMap_t::Lock_t lock(m_TransitPaths.first);
|
||||||
auto itr = m_TransitPaths.second.find(path);
|
auto itr = m_TransitPaths.second.find(path);
|
||||||
if(itr == m_TransitPaths.second.end())
|
if(itr == m_TransitPaths.second.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -233,7 +233,7 @@ namespace llarp
|
||||||
PathContext::GetLocalPathSet(const PathID_t& id)
|
PathContext::GetLocalPathSet(const PathID_t& id)
|
||||||
{
|
{
|
||||||
auto& map = m_OurPaths;
|
auto& map = m_OurPaths;
|
||||||
SyncOwnedPathsMap_t::Lock_t lock(&map.first);
|
util::Lock lock(map.first);
|
||||||
auto itr = map.second.find(id);
|
auto itr = map.second.find(id);
|
||||||
if(itr != map.second.end())
|
if(itr != map.second.end())
|
||||||
{
|
{
|
||||||
|
@ -260,7 +260,7 @@ namespace llarp
|
||||||
const RouterID us(OurRouterID());
|
const RouterID us(OurRouterID());
|
||||||
auto& map = m_TransitPaths;
|
auto& map = m_TransitPaths;
|
||||||
{
|
{
|
||||||
SyncTransitMap_t::Lock_t lock(&map.first);
|
SyncTransitMap_t::Lock_t lock(map.first);
|
||||||
auto range = map.second.equal_range(id);
|
auto range = map.second.equal_range(id);
|
||||||
for(auto i = range.first; i != range.second; ++i)
|
for(auto i = range.first; i != range.second; ++i)
|
||||||
{
|
{
|
||||||
|
@ -300,7 +300,7 @@ namespace llarp
|
||||||
m_PathLimits.Decay(now);
|
m_PathLimits.Decay(now);
|
||||||
|
|
||||||
{
|
{
|
||||||
SyncTransitMap_t::Lock_t lock(&m_TransitPaths.first);
|
SyncTransitMap_t::Lock_t lock(m_TransitPaths.first);
|
||||||
auto& map = m_TransitPaths.second;
|
auto& map = m_TransitPaths.second;
|
||||||
auto itr = map.begin();
|
auto itr = map.begin();
|
||||||
while(itr != map.end())
|
while(itr != map.end())
|
||||||
|
@ -315,7 +315,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
SyncOwnedPathsMap_t::Lock_t lock(&m_OurPaths.first);
|
util::Lock lock(m_OurPaths.first);
|
||||||
auto& map = m_OurPaths.second;
|
auto& map = m_OurPaths.second;
|
||||||
auto itr = map.begin();
|
auto itr = map.begin();
|
||||||
while(itr != map.end())
|
while(itr != map.end())
|
||||||
|
@ -344,7 +344,7 @@ namespace llarp
|
||||||
const RouterID us(OurRouterID());
|
const RouterID us(OurRouterID());
|
||||||
auto& map = m_TransitPaths;
|
auto& map = m_TransitPaths;
|
||||||
{
|
{
|
||||||
SyncTransitMap_t::Lock_t lock(&map.first);
|
SyncTransitMap_t::Lock_t lock(map.first);
|
||||||
auto range = map.second.equal_range(id);
|
auto range = map.second.equal_range(id);
|
||||||
for(auto i = range.first; i != range.second; ++i)
|
for(auto i = range.first; i != range.second; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,9 +122,9 @@ namespace llarp
|
||||||
|
|
||||||
void
|
void
|
||||||
ForEach(std::function< void(const TransitHop_ptr&) > visit)
|
ForEach(std::function< void(const TransitHop_ptr&) > visit)
|
||||||
LOCKS_EXCLUDED(first)
|
EXCLUDES(first)
|
||||||
{
|
{
|
||||||
Lock_t lock(&first);
|
Lock_t lock(first);
|
||||||
for(const auto& item : second)
|
for(const auto& item : second)
|
||||||
visit(item.second);
|
visit(item.second);
|
||||||
}
|
}
|
||||||
|
@ -136,15 +136,13 @@ namespace llarp
|
||||||
|
|
||||||
struct SyncOwnedPathsMap_t
|
struct SyncOwnedPathsMap_t
|
||||||
{
|
{
|
||||||
using Mutex_t = util::Mutex;
|
util::Mutex first; // protects second
|
||||||
using Lock_t = util::Lock;
|
|
||||||
Mutex_t first; // protects second
|
|
||||||
OwnedPathsMap_t second GUARDED_BY(first);
|
OwnedPathsMap_t second GUARDED_BY(first);
|
||||||
|
|
||||||
void
|
void
|
||||||
ForEach(std::function< void(const Path_ptr&) > visit)
|
ForEach(std::function< void(const Path_ptr&) > visit)
|
||||||
{
|
{
|
||||||
Lock_t lock(&first);
|
util::Lock lock(first);
|
||||||
for(const auto& item : second)
|
for(const auto& item : second)
|
||||||
visit(item.second);
|
visit(item.second);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <path/path_types.hpp>
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <profiling.hpp>
|
#include <profiling.hpp>
|
||||||
#include <router/abstractrouter.hpp>
|
#include <router/abstractrouter.hpp>
|
||||||
#include <util/buffer.hpp>
|
#include <util/buffer.hpp>
|
||||||
#include <util/meta/memfn.hpp>
|
|
||||||
#include <util/thread/logic.hpp>
|
#include <util/thread/logic.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
PathSet::ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const
|
PathSet::ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
const size_t required = MinRequiredForRoles(roles);
|
const size_t required = MinRequiredForRoles(roles);
|
||||||
size_t has = 0;
|
size_t has = 0;
|
||||||
for(const auto& item : m_Paths)
|
for(const auto& item : m_Paths)
|
||||||
|
@ -52,7 +52,7 @@ namespace llarp
|
||||||
PathSet::NumPathsExistingAt(llarp_time_t futureTime) const
|
PathSet::NumPathsExistingAt(llarp_time_t futureTime) const
|
||||||
{
|
{
|
||||||
size_t num = 0;
|
size_t num = 0;
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
for(const auto& item : m_Paths)
|
for(const auto& item : m_Paths)
|
||||||
{
|
{
|
||||||
if(item.second->IsReady() && !item.second->Expired(futureTime))
|
if(item.second->IsReady() && !item.second->Expired(futureTime))
|
||||||
|
@ -65,7 +65,7 @@ namespace llarp
|
||||||
PathSet::TickPaths(AbstractRouter* r)
|
PathSet::TickPaths(AbstractRouter* r)
|
||||||
{
|
{
|
||||||
const auto now = llarp::time_now_ms();
|
const auto now = llarp::time_now_ms();
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
for(auto& item : m_Paths)
|
for(auto& item : m_Paths)
|
||||||
{
|
{
|
||||||
item.second->Tick(now, r);
|
item.second->Tick(now, r);
|
||||||
|
@ -75,7 +75,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
PathSet::ExpirePaths(llarp_time_t now, AbstractRouter* router)
|
PathSet::ExpirePaths(llarp_time_t now, AbstractRouter* router)
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
if(m_Paths.size() == 0)
|
if(m_Paths.size() == 0)
|
||||||
return;
|
return;
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
|
@ -95,7 +95,7 @@ namespace llarp
|
||||||
Path_ptr
|
Path_ptr
|
||||||
PathSet::GetEstablishedPathClosestTo(RouterID id, PathRole roles) const
|
PathSet::GetEstablishedPathClosestTo(RouterID id, PathRole roles) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
Path_ptr path = nullptr;
|
Path_ptr path = nullptr;
|
||||||
AlignedBuffer< 32 > dist;
|
AlignedBuffer< 32 > dist;
|
||||||
AlignedBuffer< 32 > to = id;
|
AlignedBuffer< 32 > to = id;
|
||||||
|
@ -119,7 +119,7 @@ namespace llarp
|
||||||
Path_ptr
|
Path_ptr
|
||||||
PathSet::GetNewestPathByRouter(RouterID id, PathRole roles) const
|
PathSet::GetNewestPathByRouter(RouterID id, PathRole roles) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
Path_ptr chosen = nullptr;
|
Path_ptr chosen = nullptr;
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
|
@ -142,7 +142,7 @@ namespace llarp
|
||||||
Path_ptr
|
Path_ptr
|
||||||
PathSet::GetPathByRouter(RouterID id, PathRole roles) const
|
PathSet::GetPathByRouter(RouterID id, PathRole roles) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
Path_ptr chosen = nullptr;
|
Path_ptr chosen = nullptr;
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
|
@ -165,7 +165,7 @@ namespace llarp
|
||||||
Path_ptr
|
Path_ptr
|
||||||
PathSet::GetByEndpointWithID(RouterID ep, PathID_t id) const
|
PathSet::GetByEndpointWithID(RouterID ep, PathID_t id) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
{
|
{
|
||||||
|
@ -181,7 +181,7 @@ namespace llarp
|
||||||
Path_ptr
|
Path_ptr
|
||||||
PathSet::GetPathByID(PathID_t id) const
|
PathSet::GetPathByID(PathID_t id) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
{
|
{
|
||||||
|
@ -195,7 +195,7 @@ namespace llarp
|
||||||
size_t
|
size_t
|
||||||
PathSet::AvailablePaths(PathRole roles) const
|
PathSet::AvailablePaths(PathRole roles) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
|
@ -211,7 +211,7 @@ namespace llarp
|
||||||
size_t
|
size_t
|
||||||
PathSet::NumInStatus(PathStatus st) const
|
PathSet::NumInStatus(PathStatus st) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
|
@ -226,7 +226,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
PathSet::AddPath(Path_ptr path)
|
PathSet::AddPath(Path_ptr path)
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
const auto upstream = path->Upstream(); // RouterID
|
const auto upstream = path->Upstream(); // RouterID
|
||||||
const auto RXID = path->RXID(); // PathID
|
const auto RXID = path->RXID(); // PathID
|
||||||
if(not m_Paths.emplace(std::make_pair(upstream, RXID), path).second)
|
if(not m_Paths.emplace(std::make_pair(upstream, RXID), path).second)
|
||||||
|
@ -240,14 +240,14 @@ namespace llarp
|
||||||
void
|
void
|
||||||
PathSet::RemovePath(Path_ptr path)
|
PathSet::RemovePath(Path_ptr path)
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
m_Paths.erase({path->Upstream(), path->RXID()});
|
m_Paths.erase({path->Upstream(), path->RXID()});
|
||||||
}
|
}
|
||||||
|
|
||||||
Path_ptr
|
Path_ptr
|
||||||
PathSet::GetByUpstream(RouterID remote, PathID_t rxid) const
|
PathSet::GetByUpstream(RouterID remote, PathID_t rxid) const
|
||||||
{
|
{
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
auto itr = m_Paths.find({remote, rxid});
|
auto itr = m_Paths.find({remote, rxid});
|
||||||
if(itr == m_Paths.end())
|
if(itr == m_Paths.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -261,7 +261,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
intros.clear();
|
intros.clear();
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
{
|
{
|
||||||
|
@ -281,7 +281,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
intros.clear();
|
intros.clear();
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
{
|
{
|
||||||
|
@ -350,7 +350,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
intro.Clear();
|
intro.Clear();
|
||||||
bool found = false;
|
bool found = false;
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
{
|
{
|
||||||
|
@ -369,7 +369,7 @@ namespace llarp
|
||||||
PathSet::PickRandomEstablishedPath(PathRole roles) const
|
PathSet::PickRandomEstablishedPath(PathRole roles) const
|
||||||
{
|
{
|
||||||
std::vector< Path_ptr > established;
|
std::vector< Path_ptr > established;
|
||||||
Lock_t l(&m_PathsMutex);
|
Lock_t l(m_PathsMutex);
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
{
|
{
|
||||||
|
|
|
@ -266,7 +266,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
ForEachPath(std::function< void(const Path_ptr&) > visit) const
|
ForEachPath(std::function< void(const Path_ptr&) > visit) const
|
||||||
{
|
{
|
||||||
Lock_t lock(&m_PathsMutex);
|
Lock_t lock(m_PathsMutex);
|
||||||
auto itr = m_Paths.begin();
|
auto itr = m_Paths.begin();
|
||||||
while(itr != m_Paths.end())
|
while(itr != m_Paths.end())
|
||||||
{
|
{
|
||||||
|
|
|
@ -118,7 +118,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
if(m_DisableProfiling.load())
|
if(m_DisableProfiling.load())
|
||||||
return false;
|
return false;
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
auto itr = m_Profiles.find(r);
|
auto itr = m_Profiles.find(r);
|
||||||
if(itr == m_Profiles.end())
|
if(itr == m_Profiles.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -130,7 +130,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
if(m_DisableProfiling.load())
|
if(m_DisableProfiling.load())
|
||||||
return false;
|
return false;
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
auto itr = m_Profiles.find(r);
|
auto itr = m_Profiles.find(r);
|
||||||
if(itr == m_Profiles.end())
|
if(itr == m_Profiles.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -142,7 +142,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
if(m_DisableProfiling.load())
|
if(m_DisableProfiling.load())
|
||||||
return false;
|
return false;
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
auto itr = m_Profiles.find(r);
|
auto itr = m_Profiles.find(r);
|
||||||
if(itr == m_Profiles.end())
|
if(itr == m_Profiles.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -152,7 +152,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
Profiling::Tick()
|
Profiling::Tick()
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
std::for_each(m_Profiles.begin(), m_Profiles.end(),
|
std::for_each(m_Profiles.begin(), m_Profiles.end(),
|
||||||
[](auto& item) { item.second.Tick(); });
|
[](auto& item) { item.second.Tick(); });
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
Profiling::MarkConnectTimeout(const RouterID& r)
|
Profiling::MarkConnectTimeout(const RouterID& r)
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
m_Profiles[r].connectTimeoutCount += 1;
|
m_Profiles[r].connectTimeoutCount += 1;
|
||||||
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
Profiling::MarkConnectSuccess(const RouterID& r)
|
Profiling::MarkConnectSuccess(const RouterID& r)
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
m_Profiles[r].connectGoodCount += 1;
|
m_Profiles[r].connectGoodCount += 1;
|
||||||
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
||||||
}
|
}
|
||||||
|
@ -176,14 +176,14 @@ namespace llarp
|
||||||
void
|
void
|
||||||
Profiling::ClearProfile(const RouterID& r)
|
Profiling::ClearProfile(const RouterID& r)
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
m_Profiles.erase(r);
|
m_Profiles.erase(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Profiling::MarkHopFail(const RouterID& r)
|
Profiling::MarkHopFail(const RouterID& r)
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
m_Profiles[r].pathFailCount += 1;
|
m_Profiles[r].pathFailCount += 1;
|
||||||
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
Profiling::MarkPathFail(path::Path* p)
|
Profiling::MarkPathFail(path::Path* p)
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for(const auto& hop : p->hops)
|
for(const auto& hop : p->hops)
|
||||||
{
|
{
|
||||||
|
@ -208,7 +208,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
Profiling::MarkPathSuccess(path::Path* p)
|
Profiling::MarkPathSuccess(path::Path* p)
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
const auto sz = p->hops.size();
|
const auto sz = p->hops.size();
|
||||||
for(const auto& hop : p->hops)
|
for(const auto& hop : p->hops)
|
||||||
{
|
{
|
||||||
|
@ -220,7 +220,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
Profiling::Save(const char* fname)
|
Profiling::Save(const char* fname)
|
||||||
{
|
{
|
||||||
absl::ReaderMutexLock lock(&m_ProfilesMutex);
|
auto lock = util::shared_lock(m_ProfilesMutex);
|
||||||
size_t sz = (m_Profiles.size() * (RouterProfile::MaxSize + 32 + 8)) + 8;
|
size_t sz = (m_Profiles.size() * (RouterProfile::MaxSize + 32 + 8)) + 8;
|
||||||
|
|
||||||
std::vector< byte_t > tmp(sz, 0);
|
std::vector< byte_t > tmp(sz, 0);
|
||||||
|
@ -247,7 +247,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
Profiling::BEncode(llarp_buffer_t* buf) const
|
Profiling::BEncode(llarp_buffer_t* buf) const
|
||||||
{
|
{
|
||||||
absl::ReaderMutexLock lock(&m_ProfilesMutex);
|
auto lock = util::shared_lock(m_ProfilesMutex);
|
||||||
return BEncodeNoLock(buf);
|
return BEncodeNoLock(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
Profiling::Load(const char* fname)
|
Profiling::Load(const char* fname)
|
||||||
{
|
{
|
||||||
lock_t lock(&m_ProfilesMutex);
|
util::Lock lock(m_ProfilesMutex);
|
||||||
m_Profiles.clear();
|
m_Profiles.clear();
|
||||||
if(!BDecodeReadFromFile(fname, *this))
|
if(!BDecodeReadFromFile(fname, *this))
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,8 +52,7 @@ namespace llarp
|
||||||
|
|
||||||
/// generic variant
|
/// generic variant
|
||||||
bool
|
bool
|
||||||
IsBad(const RouterID& r, uint64_t chances = 8)
|
IsBad(const RouterID& r, uint64_t chances = 8) EXCLUDES(m_ProfilesMutex);
|
||||||
LOCKS_EXCLUDED(m_ProfilesMutex);
|
|
||||||
|
|
||||||
/// check if this router should have paths built over it
|
/// check if this router should have paths built over it
|
||||||
bool
|
bool
|
||||||
|
@ -63,31 +62,31 @@ namespace llarp
|
||||||
/// check if this router should be connected directly to
|
/// check if this router should be connected directly to
|
||||||
bool
|
bool
|
||||||
IsBadForConnect(const RouterID& r, uint64_t chances = 8)
|
IsBadForConnect(const RouterID& r, uint64_t chances = 8)
|
||||||
LOCKS_EXCLUDED(m_ProfilesMutex);
|
EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
MarkConnectTimeout(const RouterID& r) LOCKS_EXCLUDED(m_ProfilesMutex);
|
MarkConnectTimeout(const RouterID& r) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
MarkConnectSuccess(const RouterID& r) LOCKS_EXCLUDED(m_ProfilesMutex);
|
MarkConnectSuccess(const RouterID& r) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
MarkPathFail(path::Path* p) LOCKS_EXCLUDED(m_ProfilesMutex);
|
MarkPathFail(path::Path* p) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
MarkPathSuccess(path::Path* p) LOCKS_EXCLUDED(m_ProfilesMutex);
|
MarkPathSuccess(path::Path* p) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
MarkHopFail(const RouterID& r) LOCKS_EXCLUDED(m_ProfilesMutex);
|
MarkHopFail(const RouterID& r) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
ClearProfile(const RouterID& r) LOCKS_EXCLUDED(m_ProfilesMutex);
|
ClearProfile(const RouterID& r) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
Tick() LOCKS_EXCLUDED(m_ProfilesMutex);
|
Tick() EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BEncode(llarp_buffer_t* buf) const LOCKS_EXCLUDED(m_ProfilesMutex);
|
BEncode(llarp_buffer_t* buf) const EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DecodeKey(const llarp_buffer_t& k,
|
DecodeKey(const llarp_buffer_t& k,
|
||||||
|
@ -95,10 +94,10 @@ namespace llarp
|
||||||
// disabled because we do load -> bencode::BDecodeReadFromFile -> DecodeKey
|
// disabled because we do load -> bencode::BDecodeReadFromFile -> DecodeKey
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Load(const char* fname) LOCKS_EXCLUDED(m_ProfilesMutex);
|
Load(const char* fname) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Save(const char* fname) LOCKS_EXCLUDED(m_ProfilesMutex);
|
Save(const char* fname) EXCLUDES(m_ProfilesMutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ShouldSave(llarp_time_t now) const;
|
ShouldSave(llarp_time_t now) const;
|
||||||
|
@ -111,9 +110,7 @@ namespace llarp
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool
|
bool
|
||||||
BEncodeNoLock(llarp_buffer_t* buf) const
|
BEncodeNoLock(llarp_buffer_t* buf) const REQUIRES_SHARED(m_ProfilesMutex);
|
||||||
SHARED_LOCKS_REQUIRED(m_ProfilesMutex);
|
|
||||||
using lock_t = util::Lock;
|
|
||||||
mutable util::Mutex m_ProfilesMutex; // protects m_Profiles
|
mutable util::Mutex m_ProfilesMutex; // protects m_Profiles
|
||||||
std::map< RouterID, RouterProfile > m_Profiles GUARDED_BY(m_ProfilesMutex);
|
std::map< RouterID, RouterProfile > m_Profiles GUARDED_BY(m_ProfilesMutex);
|
||||||
llarp_time_t m_LastSave = 0;
|
llarp_time_t m_LastSave = 0;
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <router/abstractrouter.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <router/i_gossiper.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <router/i_outbound_message_handler.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <router/i_outbound_session_maker.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <router/i_rc_lookup_handler.hpp>
|
|
|
@ -47,7 +47,7 @@ namespace llarp
|
||||||
|
|
||||||
bool shouldCreateSession = false;
|
bool shouldCreateSession = false;
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
// create queue for <remote> if it doesn't exist, and get iterator
|
// create queue for <remote> if it doesn't exist, and get iterator
|
||||||
auto itr_pair =
|
auto itr_pair =
|
||||||
|
@ -404,7 +404,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
MessageQueue movedMessages;
|
MessageQueue movedMessages;
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
auto itr = pendingSessionMessageQueues.find(router);
|
auto itr = pendingSessionMessageQueues.find(router);
|
||||||
|
|
||||||
if(itr == pendingSessionMessageQueues.end())
|
if(itr == pendingSessionMessageQueues.end())
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace llarp
|
||||||
|
|
||||||
bool
|
bool
|
||||||
QueueMessage(const RouterID &remote, const ILinkMessage *msg,
|
QueueMessage(const RouterID &remote, const ILinkMessage *msg,
|
||||||
SendStatusHandler callback) override LOCKS_EXCLUDED(_mutex);
|
SendStatusHandler callback) override EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
Tick() override;
|
Tick() override;
|
||||||
|
@ -122,7 +122,7 @@ namespace llarp
|
||||||
|
|
||||||
void
|
void
|
||||||
FinalizeSessionRequest(const RouterID &router, SendStatus status)
|
FinalizeSessionRequest(const RouterID &router, SendStatus status)
|
||||||
LOCKS_EXCLUDED(_mutex);
|
EXCLUDES(_mutex);
|
||||||
|
|
||||||
llarp::thread::Queue< MessageQueueEntry > outboundQueue;
|
llarp::thread::Queue< MessageQueueEntry > outboundQueue;
|
||||||
llarp::thread::Queue< PathID_t > removedPaths;
|
llarp::thread::Queue< PathID_t > removedPaths;
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
if(on_result)
|
if(on_result)
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{});
|
auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{});
|
||||||
itr_pair.first->second.push_back(on_result);
|
itr_pair.first->second.push_back(on_result);
|
||||||
|
@ -94,7 +94,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
if(on_result)
|
if(on_result)
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
auto itr_pair = pendingCallbacks.emplace(rc.pubkey, CallbacksQueue{});
|
auto itr_pair = pendingCallbacks.emplace(rc.pubkey, CallbacksQueue{});
|
||||||
itr_pair.first->second.push_back(on_result);
|
itr_pair.first->second.push_back(on_result);
|
||||||
|
@ -112,7 +112,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
OutboundSessionMaker::HavePendingSessionTo(const RouterID &router) const
|
OutboundSessionMaker::HavePendingSessionTo(const RouterID &router) const
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
return pendingSessions.find(router) != pendingSessions.end();
|
return pendingSessions.find(router) != pendingSessions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
OutboundSessionMaker::DoEstablish(const RouterID &router)
|
OutboundSessionMaker::DoEstablish(const RouterID &router)
|
||||||
{
|
{
|
||||||
util::ReleasableLock l(&_mutex);
|
auto l = util::unique_lock(_mutex);
|
||||||
|
|
||||||
auto itr = pendingSessions.find(router);
|
auto itr = pendingSessions.find(router);
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
// TODO: maybe different failure type?
|
// TODO: maybe different failure type?
|
||||||
|
|
||||||
l.Release();
|
l.unlock();
|
||||||
FinalizeRequest(router, SessionResult::NoLink);
|
FinalizeRequest(router, SessionResult::NoLink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ namespace llarp
|
||||||
const RouterContact &rc)
|
const RouterContact &rc)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
util::ReleasableLock l(&_mutex);
|
auto l = util::unique_lock(_mutex);
|
||||||
|
|
||||||
// in case other request found RC for this router after this request was
|
// in case other request found RC for this router after this request was
|
||||||
// made
|
// made
|
||||||
|
@ -207,7 +207,7 @@ namespace llarp
|
||||||
|
|
||||||
if(!link)
|
if(!link)
|
||||||
{
|
{
|
||||||
l.Release();
|
l.unlock();
|
||||||
FinalizeRequest(router, SessionResult::NoLink);
|
FinalizeRequest(router, SessionResult::NoLink);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ namespace llarp
|
||||||
return false;
|
return false;
|
||||||
size_t numPending = 0;
|
size_t numPending = 0;
|
||||||
{
|
{
|
||||||
util::Lock lock(&_mutex);
|
util::Lock lock(_mutex);
|
||||||
if(pendingSessions.find(router) == pendingSessions.end())
|
if(pendingSessions.find(router) == pendingSessions.end())
|
||||||
numPending += pendingSessions.size();
|
numPending += pendingSessions.size();
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
OutboundSessionMaker::CreatePendingSession(const RouterID &router)
|
OutboundSessionMaker::CreatePendingSession(const RouterID &router)
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
pendingSessions.emplace(router, nullptr);
|
pendingSessions.emplace(router, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
CallbacksQueue movedCallbacks;
|
CallbacksQueue movedCallbacks;
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
if(type == SessionResult::Establish)
|
if(type == SessionResult::Establish)
|
||||||
{
|
{
|
||||||
|
@ -338,7 +338,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
pendingSessions.erase(router);
|
pendingSessions.erase(router);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,15 +38,15 @@ namespace llarp
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateSessionTo(const RouterID &router, RouterCallback on_result) override
|
CreateSessionTo(const RouterID &router, RouterCallback on_result) override
|
||||||
LOCKS_EXCLUDED(_mutex);
|
EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateSessionTo(const RouterContact &rc, RouterCallback on_result) override
|
CreateSessionTo(const RouterContact &rc, RouterCallback on_result) override
|
||||||
LOCKS_EXCLUDED(_mutex);
|
EXCLUDES(_mutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HavePendingSessionTo(const RouterID &router) const override
|
HavePendingSessionTo(const RouterID &router) const override
|
||||||
LOCKS_EXCLUDED(_mutex);
|
EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
ConnectToRandomRouters(int numDesired) override;
|
ConnectToRandomRouters(int numDesired) override;
|
||||||
|
@ -55,8 +55,7 @@ namespace llarp
|
||||||
ExtractStatus() const override;
|
ExtractStatus() const override;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ShouldConnectTo(const RouterID &router) const override
|
ShouldConnectTo(const RouterID &router) const override EXCLUDES(_mutex);
|
||||||
LOCKS_EXCLUDED(_mutex);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Init(ILinkManager *linkManager, I_RCLookupHandler *rcLookup,
|
Init(ILinkManager *linkManager, I_RCLookupHandler *rcLookup,
|
||||||
|
@ -77,11 +76,11 @@ namespace llarp
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void
|
void
|
||||||
DoEstablish(const RouterID &router) LOCKS_EXCLUDED(_mutex);
|
DoEstablish(const RouterID &router) EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
GotRouterContact(const RouterID &router, const RouterContact &rc)
|
GotRouterContact(const RouterID &router, const RouterContact &rc)
|
||||||
LOCKS_EXCLUDED(_mutex);
|
EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
InvalidRouter(const RouterID &router);
|
InvalidRouter(const RouterID &router);
|
||||||
|
@ -97,11 +96,11 @@ namespace llarp
|
||||||
VerifyRC(const RouterContact rc);
|
VerifyRC(const RouterContact rc);
|
||||||
|
|
||||||
void
|
void
|
||||||
CreatePendingSession(const RouterID &router) LOCKS_EXCLUDED(_mutex);
|
CreatePendingSession(const RouterID &router) EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
FinalizeRequest(const RouterID &router, const SessionResult type)
|
FinalizeRequest(const RouterID &router, const SessionResult type)
|
||||||
LOCKS_EXCLUDED(_mutex);
|
EXCLUDES(_mutex);
|
||||||
|
|
||||||
mutable util::Mutex _mutex; // protects pendingSessions, pendingCallbacks
|
mutable util::Mutex _mutex; // protects pendingSessions, pendingCallbacks
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <crypto/crypto.hpp>
|
#include <crypto/crypto.hpp>
|
||||||
#include <service/context.hpp>
|
#include <service/context.hpp>
|
||||||
#include <router_contact.hpp>
|
#include <router_contact.hpp>
|
||||||
#include <util/meta/memfn.hpp>
|
|
||||||
#include <util/types.hpp>
|
#include <util/types.hpp>
|
||||||
#include <util/thread/threading.hpp>
|
#include <util/thread/threading.hpp>
|
||||||
#include <nodedb.hpp>
|
#include <nodedb.hpp>
|
||||||
|
@ -24,14 +23,14 @@ namespace llarp
|
||||||
void
|
void
|
||||||
RCLookupHandler::AddValidRouter(const RouterID &router)
|
RCLookupHandler::AddValidRouter(const RouterID &router)
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
whitelistRouters.insert(router);
|
whitelistRouters.insert(router);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RCLookupHandler::RemoveValidRouter(const RouterID &router)
|
RCLookupHandler::RemoveValidRouter(const RouterID &router)
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
whitelistRouters.erase(router);
|
whitelistRouters.erase(router);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
if(routers.empty())
|
if(routers.empty())
|
||||||
return;
|
return;
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
whitelistRouters.clear();
|
whitelistRouters.clear();
|
||||||
for(auto &router : routers)
|
for(auto &router : routers)
|
||||||
|
@ -55,7 +54,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
RCLookupHandler::HaveReceivedWhitelist()
|
RCLookupHandler::HaveReceivedWhitelist()
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
return not whitelistRouters.empty();
|
return not whitelistRouters.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +78,7 @@ namespace llarp
|
||||||
bool shouldDoLookup = false;
|
bool shouldDoLookup = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{});
|
auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{});
|
||||||
|
|
||||||
|
@ -132,7 +131,7 @@ namespace llarp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
if(useWhitelist && whitelistRouters.find(remote) == whitelistRouters.end())
|
if(useWhitelist && whitelistRouters.find(remote) == whitelistRouters.end())
|
||||||
{
|
{
|
||||||
|
@ -178,7 +177,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
RCLookupHandler::GetRandomWhitelistRouter(RouterID &router) const
|
RCLookupHandler::GetRandomWhitelistRouter(RouterID &router) const
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
const auto sz = whitelistRouters.size();
|
const auto sz = whitelistRouters.size();
|
||||||
auto itr = whitelistRouters.begin();
|
auto itr = whitelistRouters.begin();
|
||||||
|
@ -266,7 +265,7 @@ namespace llarp
|
||||||
|
|
||||||
{
|
{
|
||||||
// if we are using a whitelist look up a few routers we don't have
|
// if we are using a whitelist look up a few routers we don't have
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
for(const auto &r : whitelistRouters)
|
for(const auto &r : whitelistRouters)
|
||||||
{
|
{
|
||||||
if(now > _routerLookupTimes[r] + RerequestInterval
|
if(now > _routerLookupTimes[r] + RerequestInterval
|
||||||
|
@ -359,7 +358,7 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
RCLookupHandler::HavePendingLookup(RouterID remote) const
|
RCLookupHandler::HavePendingLookup(RouterID remote) const
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
return pendingCallbacks.find(remote) != pendingCallbacks.end();
|
return pendingCallbacks.find(remote) != pendingCallbacks.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +382,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
CallbacksQueue movedCallbacks;
|
CallbacksQueue movedCallbacks;
|
||||||
{
|
{
|
||||||
util::Lock l(&_mutex);
|
util::Lock l(_mutex);
|
||||||
|
|
||||||
auto itr = pendingCallbacks.find(router);
|
auto itr = pendingCallbacks.find(router);
|
||||||
|
|
||||||
|
|
|
@ -32,32 +32,30 @@ namespace llarp
|
||||||
~RCLookupHandler() override = default;
|
~RCLookupHandler() override = default;
|
||||||
|
|
||||||
void
|
void
|
||||||
AddValidRouter(const RouterID &router) override LOCKS_EXCLUDED(_mutex);
|
AddValidRouter(const RouterID &router) override EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
RemoveValidRouter(const RouterID &router) override LOCKS_EXCLUDED(_mutex);
|
RemoveValidRouter(const RouterID &router) override EXCLUDES(_mutex);
|
||||||
|
|
||||||
void
|
void
|
||||||
SetRouterWhitelist(const std::vector< RouterID > &routers) override
|
SetRouterWhitelist(const std::vector< RouterID > &routers) override
|
||||||
LOCKS_EXCLUDED(_mutex);
|
EXCLUDES(_mutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HaveReceivedWhitelist();
|
HaveReceivedWhitelist();
|
||||||
|
|
||||||
void
|
void
|
||||||
GetRC(const RouterID &router, RCRequestCallback callback,
|
GetRC(const RouterID &router, RCRequestCallback callback,
|
||||||
bool forceLookup = false) override LOCKS_EXCLUDED(_mutex);
|
bool forceLookup = false) override EXCLUDES(_mutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RemoteIsAllowed(const RouterID &remote) const override
|
RemoteIsAllowed(const RouterID &remote) const override EXCLUDES(_mutex);
|
||||||
LOCKS_EXCLUDED(_mutex);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CheckRC(const RouterContact &rc) const override;
|
CheckRC(const RouterContact &rc) const override;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GetRandomWhitelistRouter(RouterID &router) const override
|
GetRandomWhitelistRouter(RouterID &router) const override EXCLUDES(_mutex);
|
||||||
LOCKS_EXCLUDED(_mutex);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc) override;
|
CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc) override;
|
||||||
|
@ -85,14 +83,14 @@ namespace llarp
|
||||||
const std::vector< RouterContact > &results);
|
const std::vector< RouterContact > &results);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HavePendingLookup(RouterID remote) const LOCKS_EXCLUDED(_mutex);
|
HavePendingLookup(RouterID remote) const EXCLUDES(_mutex);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RemoteInBootstrap(const RouterID &remote) const;
|
RemoteInBootstrap(const RouterID &remote) const;
|
||||||
|
|
||||||
void
|
void
|
||||||
FinalizeRequest(const RouterID &router, const RouterContact *const rc,
|
FinalizeRequest(const RouterID &router, const RouterContact *const rc,
|
||||||
RCRequestResult result) LOCKS_EXCLUDED(_mutex);
|
RCRequestResult result) EXCLUDES(_mutex);
|
||||||
|
|
||||||
mutable util::Mutex _mutex; // protects pendingCallbacks, whitelistRouters
|
mutable util::Mutex _mutex; // protects pendingCallbacks, whitelistRouters
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <util/logging/logger_syslog.hpp>
|
#include <util/logging/logger_syslog.hpp>
|
||||||
#include <util/logging/logger.hpp>
|
#include <util/logging/logger.hpp>
|
||||||
#include <util/meta/memfn.hpp>
|
#include <util/meta/memfn.hpp>
|
||||||
#include <util/metrics/metrics.hpp>
|
|
||||||
#include <util/str.hpp>
|
#include <util/str.hpp>
|
||||||
#include <ev/ev.hpp>
|
#include <ev/ev.hpp>
|
||||||
|
|
||||||
|
@ -141,7 +140,7 @@ namespace llarp
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
absl::ReaderMutexLock l(&nodedb()->access);
|
auto l = util::shared_lock(nodedb()->access);
|
||||||
return pick_router(nodedb()->entries);
|
return pick_router(nodedb()->entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,7 +779,6 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
Router::Sign(Signature &sig, const llarp_buffer_t &buf) const
|
Router::Sign(Signature &sig, const llarp_buffer_t &buf) const
|
||||||
{
|
{
|
||||||
metrics::TimerGuard t("Router", "Sign");
|
|
||||||
return CryptoManager::instance()->sign(sig, identity(), buf);
|
return CryptoManager::instance()->sign(sig, identity(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <routing/handler.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <routing/message.hpp>
|
|
|
@ -853,7 +853,7 @@ namespace llarp
|
||||||
{
|
{
|
||||||
if(msg->proto == eProtocolTrafficV4 || msg->proto == eProtocolTrafficV6)
|
if(msg->proto == eProtocolTrafficV4 || msg->proto == eProtocolTrafficV6)
|
||||||
{
|
{
|
||||||
util::Lock l(&m_state->m_InboundTrafficQueueMutex);
|
util::Lock l(m_state->m_InboundTrafficQueueMutex);
|
||||||
m_state->m_InboundTrafficQueue.emplace(msg);
|
m_state->m_InboundTrafficQueue.emplace(msg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -903,7 +903,7 @@ namespace llarp
|
||||||
return false;
|
return false;
|
||||||
{
|
{
|
||||||
LogWarn("invalidating convotag T=", frame.T);
|
LogWarn("invalidating convotag T=", frame.T);
|
||||||
util::Lock lock(&m_state->m_SendQueueMutex);
|
util::Lock lock(m_state->m_SendQueueMutex);
|
||||||
m_state->m_SendQueue.emplace_back(
|
m_state->m_SendQueue.emplace_back(
|
||||||
std::make_shared< const routing::PathTransferMessage >(f,
|
std::make_shared< const routing::PathTransferMessage >(f,
|
||||||
frame.F),
|
frame.F),
|
||||||
|
@ -1080,7 +1080,7 @@ namespace llarp
|
||||||
for(const auto& item : sessions)
|
for(const auto& item : sessions)
|
||||||
item.second.first->FlushDownstream();
|
item.second.first->FlushDownstream();
|
||||||
// send downstream traffic to user for hidden service
|
// send downstream traffic to user for hidden service
|
||||||
util::Lock lock(&m_state->m_InboundTrafficQueueMutex);
|
util::Lock lock(m_state->m_InboundTrafficQueueMutex);
|
||||||
while(not queue.empty())
|
while(not queue.empty())
|
||||||
{
|
{
|
||||||
const auto& msg = queue.top();
|
const auto& msg = queue.top();
|
||||||
|
@ -1106,7 +1106,7 @@ namespace llarp
|
||||||
for(const auto& item : sessions)
|
for(const auto& item : sessions)
|
||||||
item.second.first->FlushUpstream();
|
item.second.first->FlushUpstream();
|
||||||
{
|
{
|
||||||
util::Lock lock(&m_state->m_SendQueueMutex);
|
util::Lock lock(m_state->m_SendQueueMutex);
|
||||||
// send outbound traffic
|
// send outbound traffic
|
||||||
for(const auto& item : m_state->m_SendQueue)
|
for(const auto& item : m_state->m_SendQueue)
|
||||||
{
|
{
|
||||||
|
@ -1206,7 +1206,7 @@ namespace llarp
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Lock lock(&self->m_state->m_SendQueueMutex);
|
util::Lock lock(self->m_state->m_SendQueueMutex);
|
||||||
self->m_state->m_SendQueue.emplace_back(transfer, p);
|
self->m_state->m_SendQueue.emplace_back(transfer, p);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <service/handler.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <service/pendingbuffer.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <service/vanity.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/aligned.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/bits.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/codel.hpp>
|
|
|
@ -28,8 +28,9 @@ namespace llarp
|
||||||
|
|
||||||
template < typename T, typename GetTime, typename PutTime, typename Compare,
|
template < typename T, typename GetTime, typename PutTime, typename Compare,
|
||||||
typename GetNow = GetNowSyscall, typename Mutex_t = util::Mutex,
|
typename GetNow = GetNowSyscall, typename Mutex_t = util::Mutex,
|
||||||
typename Lock_t = util::Lock, llarp_time_t dropMs = 5,
|
typename Lock_t = std::lock_guard< Mutex_t >,
|
||||||
llarp_time_t initialIntervalMs = 100, size_t MaxSize = 1024 >
|
llarp_time_t dropMs = 5, llarp_time_t initialIntervalMs = 100,
|
||||||
|
size_t MaxSize = 1024 >
|
||||||
struct CoDelQueue
|
struct CoDelQueue
|
||||||
{
|
{
|
||||||
CoDelQueue(std::string name, PutTime put, GetNow now)
|
CoDelQueue(std::string name, PutTime put, GetNow now)
|
||||||
|
@ -41,7 +42,7 @@ namespace llarp
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
Size() LOCKS_EXCLUDED(m_QueueMutex)
|
Size() EXCLUDES(m_QueueMutex)
|
||||||
{
|
{
|
||||||
Lock_t lock(m_QueueMutex);
|
Lock_t lock(m_QueueMutex);
|
||||||
return m_QueueIdx;
|
return m_QueueIdx;
|
||||||
|
@ -50,9 +51,9 @@ namespace llarp
|
||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
bool
|
bool
|
||||||
EmplaceIf(std::function< bool(T&) > pred, Args&&... args)
|
EmplaceIf(std::function< bool(T&) > pred, Args&&... args)
|
||||||
LOCKS_EXCLUDED(m_QueueMutex)
|
EXCLUDES(m_QueueMutex)
|
||||||
{
|
{
|
||||||
Lock_t lock(&m_QueueMutex);
|
Lock_t lock(m_QueueMutex);
|
||||||
if(m_QueueIdx == MaxSize)
|
if(m_QueueIdx == MaxSize)
|
||||||
return false;
|
return false;
|
||||||
T* t = &m_Queue[m_QueueIdx];
|
T* t = &m_Queue[m_QueueIdx];
|
||||||
|
@ -73,9 +74,9 @@ namespace llarp
|
||||||
|
|
||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
void
|
void
|
||||||
Emplace(Args&&... args) LOCKS_EXCLUDED(m_QueueMutex)
|
Emplace(Args&&... args) EXCLUDES(m_QueueMutex)
|
||||||
{
|
{
|
||||||
Lock_t lock(&m_QueueMutex);
|
Lock_t lock(m_QueueMutex);
|
||||||
if(m_QueueIdx == MaxSize)
|
if(m_QueueIdx == MaxSize)
|
||||||
return;
|
return;
|
||||||
T* t = &m_Queue[m_QueueIdx];
|
T* t = &m_Queue[m_QueueIdx];
|
||||||
|
@ -95,13 +96,13 @@ namespace llarp
|
||||||
|
|
||||||
template < typename Visit, typename Filter >
|
template < typename Visit, typename Filter >
|
||||||
void
|
void
|
||||||
Process(Visit visitor, Filter f) LOCKS_EXCLUDED(m_QueueMutex)
|
Process(Visit visitor, Filter f) EXCLUDES(m_QueueMutex)
|
||||||
{
|
{
|
||||||
llarp_time_t lowest = std::numeric_limits< llarp_time_t >::max();
|
llarp_time_t lowest = std::numeric_limits< llarp_time_t >::max();
|
||||||
if(_getNow() < nextTickAt)
|
if(_getNow() < nextTickAt)
|
||||||
return;
|
return;
|
||||||
// llarp::LogInfo("CoDelQueue::Process - start at ", start);
|
// llarp::LogInfo("CoDelQueue::Process - start at ", start);
|
||||||
Lock_t lock(&m_QueueMutex);
|
Lock_t lock(m_QueueMutex);
|
||||||
auto start = firstPut;
|
auto start = firstPut;
|
||||||
|
|
||||||
if(m_QueueIdx == 1)
|
if(m_QueueIdx == 1)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/common.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/decaying_hashset.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/endian.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/meta/memfn.hpp>
|
|
|
@ -1,88 +1,68 @@
|
||||||
#ifndef LLARP_UTIL_MEMFN
|
#ifndef LLARP_UTIL_MEMFN
|
||||||
#define LLARP_UTIL_MEMFN
|
#define LLARP_UTIL_MEMFN
|
||||||
|
|
||||||
#include <util/meta/memfn_traits.hpp>
|
#include <type_traits>
|
||||||
#include <util/meta/object.hpp>
|
|
||||||
#include <util/meta/traits.hpp>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace llarp
|
namespace llarp
|
||||||
{
|
{
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
template < typename Obj >
|
// Wraps a member function and instance into a callable object that invokes
|
||||||
struct MemFnDereference
|
// the method (non-const overload).
|
||||||
|
template <
|
||||||
|
typename Return, typename Class, typename Derived, typename... Arg,
|
||||||
|
typename =
|
||||||
|
std::enable_if_t< std::is_base_of< Class, Derived >::value > >
|
||||||
|
auto
|
||||||
|
memFn(Return (Class::*f)(Arg...), Derived* self)
|
||||||
{
|
{
|
||||||
// clang-format off
|
return [f, self](Arg... args) -> Return {
|
||||||
static inline Obj& derefImp(Obj& obj, std::false_type)
|
return (self->*f)(std::forward< Arg >(args)...);
|
||||||
{
|
};
|
||||||
return obj;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
// Wraps a member function and instance into a lambda that invokes the
|
||||||
static inline Obj& derefImp(Type& obj, std::true_type)
|
// method (const overload).
|
||||||
{
|
template <
|
||||||
return *obj;
|
typename Return, typename Class, typename Derived, typename... Arg,
|
||||||
}
|
typename =
|
||||||
|
std::enable_if_t< std::is_base_of< Class, Derived >::value > >
|
||||||
template < typename Type >
|
auto
|
||||||
static inline Obj& derefImp(const Type& obj, std::true_type)
|
memFn(Return (Class::*f)(Arg...) const, const Derived* self)
|
||||||
{
|
|
||||||
return *obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
static inline Obj& deref(Type& obj)
|
|
||||||
{
|
|
||||||
return derefImp(obj, traits::is_pointy< Type >());
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
static inline Obj& deref(const Type& obj)
|
|
||||||
{
|
|
||||||
return derefImp(obj, traits::is_pointy< Type >());
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename Instance >
|
|
||||||
class MemFn
|
|
||||||
{
|
{
|
||||||
using traits = MemFnTraits< Prototype >;
|
return [f, self](Arg... args) -> Return {
|
||||||
|
return (self->*f)(std::forward< Arg >(args)...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static_assert(traits::IsMemFn, "");
|
// Wraps a member function and shared pointer to an instance into a lambda
|
||||||
|
// that invokes the method.
|
||||||
public:
|
template <
|
||||||
using result_type = typename traits::result_type;
|
typename Return, typename Class, typename Derived, typename... Arg,
|
||||||
|
typename =
|
||||||
private:
|
std::enable_if_t< std::is_base_of< Class, Derived >::value > >
|
||||||
Prototype m_func;
|
auto
|
||||||
object::Proxy< Instance > m_instance;
|
memFn(Return (Class::*f)(Arg...), std::shared_ptr< Derived > self)
|
||||||
|
|
||||||
using Deref = MemFnDereference< typename traits::class_type >;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MemFn(Prototype prototype, const Instance& instance)
|
|
||||||
: m_func(prototype), m_instance(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename... Args >
|
|
||||||
result_type
|
|
||||||
operator()(Args&&... args) const
|
|
||||||
{
|
|
||||||
return (Deref::deref(m_instance.value())
|
|
||||||
.*m_func)(std::forward< Args >(args)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename Instance >
|
|
||||||
MemFn< Prototype, Instance >
|
|
||||||
memFn(Prototype prototype, const Instance& instance)
|
|
||||||
{
|
{
|
||||||
return MemFn< Prototype, Instance >(prototype, instance);
|
return [f, self = std::move(self)](Arg... args) -> Return {
|
||||||
|
return (self.get()->*f)(std::forward< Arg >(args)...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps a member function and shared pointer to an instance into a lambda
|
||||||
|
// that invokes the method (const method overload).
|
||||||
|
template <
|
||||||
|
typename Return, typename Class, typename Derived, typename... Arg,
|
||||||
|
typename =
|
||||||
|
std::enable_if_t< std::is_base_of< Class, Derived >::value > >
|
||||||
|
auto
|
||||||
|
memFn(Return (Class::*f)(Arg...) const, std::shared_ptr< Derived > self)
|
||||||
|
{
|
||||||
|
return [f, self = std::move(self)](Arg... args) -> Return {
|
||||||
|
return (self.get()->*f)(std::forward< Arg >(args)...);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/meta/memfn_traits.hpp>
|
|
|
@ -1,107 +0,0 @@
|
||||||
#ifndef LLARP_UTIL_MEMFN_TRAITS
|
|
||||||
#define LLARP_UTIL_MEMFN_TRAITS
|
|
||||||
|
|
||||||
#include <util/meta/object.hpp>
|
|
||||||
#include <util/meta/traits.hpp>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
template < typename Prototype, typename TestPrototype >
|
|
||||||
struct MemFnTraitsImpl;
|
|
||||||
|
|
||||||
template < typename Prototype >
|
|
||||||
struct MemFnTraits : public MemFnTraitsImpl< Prototype, Prototype >
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename Return, typename Type,
|
|
||||||
typename... Args >
|
|
||||||
class MemFnTraitsClass
|
|
||||||
{
|
|
||||||
using NonCVTag = traits::Tag< 0 >;
|
|
||||||
using ConstTag = traits::Tag< 1 >;
|
|
||||||
using VolTag = traits::Tag< 2 >;
|
|
||||||
using ConstVolTag = traits::Tag< 3 >;
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
static constexpr NonCVTag test(Return (Type::*)(Args...));
|
|
||||||
static constexpr ConstTag test(Return (Type::*)(Args...) const);
|
|
||||||
static constexpr VolTag test(Return (Type::*)(Args...) volatile);
|
|
||||||
static constexpr ConstVolTag test(Return (Type::*)(Args...) const volatile);
|
|
||||||
// clang-format on
|
|
||||||
public:
|
|
||||||
static constexpr bool IsConst =
|
|
||||||
((sizeof((test)((Prototype)0)) - 1) & 1) != 0;
|
|
||||||
static constexpr bool IsVolatile =
|
|
||||||
((sizeof((test)((Prototype)0)) - 1) & 2) != 0;
|
|
||||||
|
|
||||||
using ctype = std::conditional_t< IsConst, const Type, Type >;
|
|
||||||
using type = std::conditional_t< IsVolatile, volatile ctype, ctype >;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename Return, typename Type,
|
|
||||||
typename... Args >
|
|
||||||
struct MemFnTraitsImpl< Prototype, Return (Type::*)(Args...) >
|
|
||||||
{
|
|
||||||
static constexpr bool IsMemFn = true;
|
|
||||||
|
|
||||||
using class_type =
|
|
||||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
|
||||||
|
|
||||||
using result_type = Return;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename Return, typename Type,
|
|
||||||
typename... Args >
|
|
||||||
struct MemFnTraitsImpl< Prototype, Return (Type::*)(Args...) const >
|
|
||||||
{
|
|
||||||
static constexpr bool IsMemFn = true;
|
|
||||||
|
|
||||||
using class_type =
|
|
||||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
|
||||||
|
|
||||||
using result_type = Return;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename Return, typename Type,
|
|
||||||
typename... Args >
|
|
||||||
struct MemFnTraitsImpl< Prototype, Return (Type::*)(Args...) volatile >
|
|
||||||
{
|
|
||||||
static constexpr bool IsMemFn = true;
|
|
||||||
|
|
||||||
using class_type =
|
|
||||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
|
||||||
|
|
||||||
using result_type = Return;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename Return, typename Type,
|
|
||||||
typename... Args >
|
|
||||||
struct MemFnTraitsImpl< Prototype,
|
|
||||||
Return (Type::*)(Args...) const volatile >
|
|
||||||
{
|
|
||||||
static constexpr bool IsMemFn = true;
|
|
||||||
|
|
||||||
using class_type =
|
|
||||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
|
||||||
|
|
||||||
using result_type = Return;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Prototype, typename TestPrototype >
|
|
||||||
struct MemFnTraitsImpl
|
|
||||||
{
|
|
||||||
static constexpr bool IsMemFn = false;
|
|
||||||
|
|
||||||
using result_type = void;
|
|
||||||
using class_type = void;
|
|
||||||
};
|
|
||||||
} // namespace util
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/meta/object.hpp>
|
|
|
@ -1,469 +0,0 @@
|
||||||
#ifndef LLARP_OBJECT_HPP
|
|
||||||
#define LLARP_OBJECT_HPP
|
|
||||||
|
|
||||||
#include <util/thread/threading.hpp>
|
|
||||||
|
|
||||||
#include <nonstd/optional.hpp>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace object
|
|
||||||
{
|
|
||||||
/// Provide a buffer, capable of holding a single `Value` object.
|
|
||||||
/// This is useful for node-based data structures.
|
|
||||||
/// Note:
|
|
||||||
/// - This union explicitly does *not* manage the lifetime of the object,
|
|
||||||
/// explicit calls to the constructor/destructor must be made.
|
|
||||||
template < typename Value >
|
|
||||||
union Buffer {
|
|
||||||
private:
|
|
||||||
char m_buffer[sizeof(Value)];
|
|
||||||
char m_align[alignof(Value)];
|
|
||||||
|
|
||||||
public:
|
|
||||||
Value*
|
|
||||||
address()
|
|
||||||
{
|
|
||||||
return reinterpret_cast< Value* >(static_cast< void* >(m_buffer));
|
|
||||||
}
|
|
||||||
const Value*
|
|
||||||
address() const
|
|
||||||
{
|
|
||||||
return reinterpret_cast< Value* >(static_cast< void* >(m_buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
char*
|
|
||||||
buffer()
|
|
||||||
{
|
|
||||||
return m_buffer;
|
|
||||||
}
|
|
||||||
const char*
|
|
||||||
buffer() const
|
|
||||||
{
|
|
||||||
return m_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value&
|
|
||||||
value()
|
|
||||||
{
|
|
||||||
return *reinterpret_cast< Value* >(this);
|
|
||||||
}
|
|
||||||
const Value&
|
|
||||||
value() const
|
|
||||||
{
|
|
||||||
return *reinterpret_cast< const Value* >(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
class Proxy
|
|
||||||
{
|
|
||||||
Buffer< Value > m_value;
|
|
||||||
|
|
||||||
Proxy&
|
|
||||||
operator=(const Proxy&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Proxy()
|
|
||||||
{
|
|
||||||
::new(m_value.buffer()) Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
Proxy(const Proxy& other)
|
|
||||||
{
|
|
||||||
::new(m_value.buffer()) Value(other.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
Proxy(const Value& value)
|
|
||||||
{
|
|
||||||
::new(m_value.buffer()) Value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// template < typename... Args >
|
|
||||||
// Proxy(Args&&... args)
|
|
||||||
// {
|
|
||||||
// ::new(m_value.buffer()) Value(std::forward< Args >(args)...);
|
|
||||||
// }
|
|
||||||
|
|
||||||
~Proxy()
|
|
||||||
{
|
|
||||||
m_value.address()->~Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
Value&
|
|
||||||
value()
|
|
||||||
{
|
|
||||||
return m_value.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Value&
|
|
||||||
value() const
|
|
||||||
{
|
|
||||||
return m_value.value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
class Catalog;
|
|
||||||
template < typename Value >
|
|
||||||
class CatalogIterator;
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
class CatalogCleaner
|
|
||||||
{
|
|
||||||
Catalog< Value >* m_catalog;
|
|
||||||
typename Catalog< Value >::Node* m_node;
|
|
||||||
bool m_shouldDelete;
|
|
||||||
|
|
||||||
CatalogCleaner(const CatalogCleaner&) = delete;
|
|
||||||
CatalogCleaner&
|
|
||||||
operator=(const CatalogCleaner&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CatalogCleaner(Catalog< Value >* catalog)
|
|
||||||
: m_catalog(catalog), m_node(nullptr), m_shouldDelete(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CatalogCleaner();
|
|
||||||
|
|
||||||
void
|
|
||||||
manageNode(typename Catalog< Value >::Node* node, bool shouldDelete)
|
|
||||||
{
|
|
||||||
m_node = node;
|
|
||||||
m_shouldDelete = shouldDelete;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
releaseNode()
|
|
||||||
{
|
|
||||||
m_node = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
release()
|
|
||||||
{
|
|
||||||
releaseNode();
|
|
||||||
m_catalog = nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A pooling catalog of objects, referred to by a 32-bit handle
|
|
||||||
template < typename Value >
|
|
||||||
class Catalog
|
|
||||||
{
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
INDEX_MASK = 0X007FFFFF,
|
|
||||||
BUSY_INDICATOR = 0x00800000,
|
|
||||||
GENERATION_INC = 0x01000000,
|
|
||||||
GENERATION_MASK = 0XFF000000
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Node
|
|
||||||
{
|
|
||||||
union Payload {
|
|
||||||
Buffer< Value > m_buffer;
|
|
||||||
Node* m_next;
|
|
||||||
};
|
|
||||||
Payload m_payload;
|
|
||||||
int32_t m_handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector< Node* > m_nodes GUARDED_BY(m_mutex);
|
|
||||||
Node* m_next;
|
|
||||||
std::atomic_size_t m_size;
|
|
||||||
|
|
||||||
mutable util::Mutex m_mutex;
|
|
||||||
|
|
||||||
friend class CatalogCleaner< Value >;
|
|
||||||
friend class CatalogIterator< Value >;
|
|
||||||
|
|
||||||
static Value*
|
|
||||||
getValue(Node* node)
|
|
||||||
{
|
|
||||||
return node->m_payload.m_buffer.address();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
freeNode(Node* node)
|
|
||||||
{
|
|
||||||
node->m_handle += GENERATION_INC;
|
|
||||||
node->m_handle &= ~BUSY_INDICATOR;
|
|
||||||
|
|
||||||
node->m_payload.m_next = m_next;
|
|
||||||
m_next = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node*
|
|
||||||
findNode(int32_t handle) const SHARED_LOCKS_REQUIRED(m_mutex)
|
|
||||||
{
|
|
||||||
int32_t index = handle & INDEX_MASK;
|
|
||||||
|
|
||||||
if(0 > index || index >= static_cast< int32_t >(m_nodes.size())
|
|
||||||
|| !(handle & BUSY_INDICATOR))
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* node = m_nodes[index];
|
|
||||||
|
|
||||||
return (node->m_handle == handle) ? node : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Catalog() : m_next(nullptr), m_size(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~Catalog()
|
|
||||||
{
|
|
||||||
removeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t
|
|
||||||
add(const Value& value)
|
|
||||||
{
|
|
||||||
int32_t handle;
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
CatalogCleaner< Value > guard(this);
|
|
||||||
Node* node;
|
|
||||||
|
|
||||||
if(m_next)
|
|
||||||
{
|
|
||||||
node = m_next;
|
|
||||||
m_next = node->m_payload.m_next;
|
|
||||||
|
|
||||||
guard.manageNode(node, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(m_nodes.size() < BUSY_INDICATOR);
|
|
||||||
|
|
||||||
node = new Node;
|
|
||||||
guard.manageNode(node, true);
|
|
||||||
|
|
||||||
m_nodes.push_back(node);
|
|
||||||
node->m_handle = static_cast< int32_t >(m_nodes.size() - 1);
|
|
||||||
guard.manageNode(node, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
node->m_handle |= BUSY_INDICATOR;
|
|
||||||
handle = node->m_handle;
|
|
||||||
|
|
||||||
// construct into the node.
|
|
||||||
::new(getValue(node)) Value(value);
|
|
||||||
|
|
||||||
guard.release();
|
|
||||||
|
|
||||||
++m_size;
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
remove(int32_t handle, Value* value = nullptr)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
Node* node = findNode(handle);
|
|
||||||
|
|
||||||
if(!node)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* val = getValue(node);
|
|
||||||
|
|
||||||
if(value)
|
|
||||||
{
|
|
||||||
*value = *val;
|
|
||||||
}
|
|
||||||
|
|
||||||
val->~Value();
|
|
||||||
freeNode(node);
|
|
||||||
|
|
||||||
--m_size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
removeAll(std::vector< Value >* output = nullptr)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
|
|
||||||
for(Node* node : m_nodes)
|
|
||||||
{
|
|
||||||
if(node->m_handle & BUSY_INDICATOR)
|
|
||||||
{
|
|
||||||
Value* value = getValue(node);
|
|
||||||
|
|
||||||
if(output)
|
|
||||||
{
|
|
||||||
output->push_back(*value);
|
|
||||||
}
|
|
||||||
value->~Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete node;
|
|
||||||
}
|
|
||||||
m_nodes.clear();
|
|
||||||
m_next = nullptr;
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
replace(const Value& newValue, int32_t handle)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
Node* node = findNode(handle);
|
|
||||||
|
|
||||||
if(!node)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* value = getValue(node);
|
|
||||||
|
|
||||||
value->~Value();
|
|
||||||
// construct into the node.
|
|
||||||
::new(value) Value(newValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nonstd::optional< Value >
|
|
||||||
find(int32_t handle)
|
|
||||||
{
|
|
||||||
absl::ReaderMutexLock l(&m_mutex);
|
|
||||||
Node* node = findNode(handle);
|
|
||||||
|
|
||||||
if(!node)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return *getValue(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
size() const
|
|
||||||
{
|
|
||||||
return m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// introduced for testing only. verify the current state of the catalog.
|
|
||||||
bool
|
|
||||||
verify() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
class SCOPED_LOCKABLE CatalogIterator
|
|
||||||
{
|
|
||||||
const Catalog< Value >* m_catalog;
|
|
||||||
size_t m_index;
|
|
||||||
|
|
||||||
CatalogIterator(const CatalogIterator&) = delete;
|
|
||||||
CatalogIterator&
|
|
||||||
operator=(const CatalogIterator&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CatalogIterator(const Catalog< Value >* catalog)
|
|
||||||
SHARED_LOCK_FUNCTION(m_catalog->m_mutex)
|
|
||||||
: m_catalog(catalog), m_index(-1)
|
|
||||||
{
|
|
||||||
m_catalog->m_mutex.ReaderLock();
|
|
||||||
operator++();
|
|
||||||
}
|
|
||||||
|
|
||||||
~CatalogIterator() UNLOCK_FUNCTION()
|
|
||||||
{
|
|
||||||
m_catalog->m_mutex.ReaderUnlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
operator++() NO_THREAD_SAFETY_ANALYSIS
|
|
||||||
{
|
|
||||||
m_index++;
|
|
||||||
while(m_index < m_catalog->m_nodes.size()
|
|
||||||
&& !(m_catalog->m_nodes[m_index]->m_handle
|
|
||||||
& Catalog< Value >::BUSY_INDICATOR))
|
|
||||||
{
|
|
||||||
m_index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const NO_THREAD_SAFETY_ANALYSIS
|
|
||||||
{
|
|
||||||
return m_index < m_catalog->m_nodes.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair< int32_t, Value >
|
|
||||||
operator()() const NO_THREAD_SAFETY_ANALYSIS
|
|
||||||
{
|
|
||||||
auto* node = m_catalog->m_nodes[m_index];
|
|
||||||
return {node->m_handle, *Catalog< Value >::getValue(node)};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
CatalogCleaner< Value >::~CatalogCleaner()
|
|
||||||
{
|
|
||||||
if(m_catalog && m_node)
|
|
||||||
{
|
|
||||||
if(m_shouldDelete)
|
|
||||||
{
|
|
||||||
// We call the destructor elsewhere.
|
|
||||||
operator delete(m_node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_catalog->freeNode(m_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
bool
|
|
||||||
Catalog< Value >::verify() const
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
|
|
||||||
if(m_nodes.size() < m_size)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t busyCount = 0;
|
|
||||||
for(size_t i = 0; i < m_nodes.size(); i++)
|
|
||||||
{
|
|
||||||
if((m_nodes[i]->m_handle & INDEX_MASK) != i)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(m_nodes[i]->m_handle & BUSY_INDICATOR)
|
|
||||||
{
|
|
||||||
busyCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_size != busyCount)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t freeCount = 0;
|
|
||||||
for(Node* p = m_next; p != nullptr; p = p->m_payload.m_next)
|
|
||||||
{
|
|
||||||
freeCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(freeCount + busyCount != m_nodes.size())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} // namespace object
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/meta/traits.hpp>
|
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef LLARP_TRAITS_HPP
|
#ifndef LLARP_TRAITS_HPP
|
||||||
#define LLARP_TRAITS_HPP
|
#define LLARP_TRAITS_HPP
|
||||||
|
|
||||||
#include <absl/meta/type_traits.h>
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -12,9 +10,18 @@ namespace llarp
|
||||||
{
|
{
|
||||||
namespace traits
|
namespace traits
|
||||||
{
|
{
|
||||||
using absl::conjunction;
|
#ifdef __cpp_lib_void_t
|
||||||
using absl::disjunction;
|
using std::void_t;
|
||||||
using absl::void_t;
|
#else
|
||||||
|
/// C++17 void_t backport
|
||||||
|
template < typename... Ts >
|
||||||
|
struct void_t_impl
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
template < typename... Ts >
|
||||||
|
using void_t = typename void_t_impl< Ts... >::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Represents the empty type
|
/// Represents the empty type
|
||||||
struct Bottom
|
struct Bottom
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/meta/variant.hpp>
|
|
|
@ -1,45 +0,0 @@
|
||||||
#ifndef LLARP_VARIANT_HPP
|
|
||||||
#define LLARP_VARIANT_HPP
|
|
||||||
|
|
||||||
#include <absl/types/variant.h>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
template < typename... Ts >
|
|
||||||
struct _overloaded;
|
|
||||||
|
|
||||||
template < typename T, typename... Ts >
|
|
||||||
struct _overloaded< T, Ts... > : T, _overloaded< Ts... >
|
|
||||||
{
|
|
||||||
_overloaded(T&& t, Ts&&... ts)
|
|
||||||
: T(t), _overloaded< Ts... >(std::forward< Ts >(ts)...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
using T::operator();
|
|
||||||
|
|
||||||
using _overloaded< Ts... >::operator();
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
struct _overloaded< T > : T
|
|
||||||
{
|
|
||||||
_overloaded(T&& t) : T(t)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
using T::operator();
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename... Ts >
|
|
||||||
constexpr auto
|
|
||||||
overloaded(Ts&&... ts) -> _overloaded< Ts... >
|
|
||||||
{
|
|
||||||
return _overloaded< Ts... >(std::forward< Ts >(ts)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,753 +0,0 @@
|
||||||
#include <util/metrics/core.hpp>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
std::pair< Id, bool >
|
|
||||||
Registry::insert(string_view category, string_view name)
|
|
||||||
{
|
|
||||||
// avoid life time issues, putting strings in the stringmem set
|
|
||||||
string_view cStr = m_stringmem.emplace(category).first->c_str();
|
|
||||||
string_view nStr = m_stringmem.emplace(name).first->c_str();
|
|
||||||
|
|
||||||
NamedCategory namedCategory(cStr, nStr);
|
|
||||||
const auto it = m_metrics.find(namedCategory);
|
|
||||||
|
|
||||||
if(it != m_metrics.end())
|
|
||||||
{
|
|
||||||
return {Id(it->second.get()), false};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cIt = m_categories.find(cStr);
|
|
||||||
if(cIt == m_categories.end())
|
|
||||||
{
|
|
||||||
auto ptr = std::make_shared< Category >(cStr, m_defaultEnabled);
|
|
||||||
cIt = m_categories.emplace(cStr, ptr).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto mPtr =
|
|
||||||
std::make_shared< Description >(cIt->second.get(), nStr);
|
|
||||||
|
|
||||||
m_metrics.emplace(namedCategory, mPtr);
|
|
||||||
return {Id(mPtr.get()), true};
|
|
||||||
}
|
|
||||||
|
|
||||||
Id
|
|
||||||
Registry::add(string_view category, string_view name)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
auto result = insert(category, name);
|
|
||||||
return std::get< 1 >(result) ? std::get< 0 >(result) : Id();
|
|
||||||
}
|
|
||||||
|
|
||||||
Id
|
|
||||||
Registry::get(string_view category, string_view name)
|
|
||||||
{
|
|
||||||
Id result = findId(category, name);
|
|
||||||
if(result)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
return std::get< 0 >(insert(category, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
const Category *
|
|
||||||
Registry::add(string_view category)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
|
|
||||||
string_view cStr = m_stringmem.emplace(category).first->c_str();
|
|
||||||
auto it = m_categories.find(cStr);
|
|
||||||
if(it == m_categories.end())
|
|
||||||
{
|
|
||||||
auto ptr = std::make_shared< Category >(cStr, m_defaultEnabled);
|
|
||||||
it = m_categories.emplace(cStr, ptr).first;
|
|
||||||
return it->second.get();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Category *
|
|
||||||
Registry::get(string_view category)
|
|
||||||
{
|
|
||||||
const Category *cPtr = findCategory(category);
|
|
||||||
if(cPtr)
|
|
||||||
{
|
|
||||||
return cPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
string_view cStr = m_stringmem.emplace(category).first->c_str();
|
|
||||||
auto it = m_categories.find(cStr);
|
|
||||||
if(it == m_categories.end())
|
|
||||||
{
|
|
||||||
auto ptr = std::make_shared< Category >(cStr, m_defaultEnabled);
|
|
||||||
it = m_categories.emplace(cStr, ptr).first;
|
|
||||||
}
|
|
||||||
return it->second.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Registry::enable(const Category *category, bool value)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
const_cast< Category * >(category)->enabled(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Registry::enableAll(bool value)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
|
|
||||||
if(value == m_defaultEnabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_defaultEnabled = value;
|
|
||||||
|
|
||||||
std::for_each(m_categories.begin(), m_categories.end(),
|
|
||||||
[&](auto &x) { x.second->enabled(value); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Registry::registerContainer(const Category *category,
|
|
||||||
CategoryContainer &container)
|
|
||||||
{
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
if(container.m_category == nullptr)
|
|
||||||
{
|
|
||||||
const_cast< Category * >(category)->registerContainer(&container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Registry::publicationType(const Id &id, Publication::Type type)
|
|
||||||
{
|
|
||||||
const_cast< Description * >(id.description())->type(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Registry::setFormat(const Id &id, const Format &format)
|
|
||||||
{
|
|
||||||
auto *description = const_cast< Description * >(id.description());
|
|
||||||
|
|
||||||
absl::WriterMutexLock l(&m_mutex);
|
|
||||||
|
|
||||||
auto fmtPtr = std::make_shared< Format >(format);
|
|
||||||
|
|
||||||
for(byte_t i = 0; i < Publication::MaxSize; ++i)
|
|
||||||
{
|
|
||||||
auto type = static_cast< Publication::Type >(i);
|
|
||||||
const FormatSpec *spec = format.specFor(type);
|
|
||||||
if(spec != nullptr)
|
|
||||||
{
|
|
||||||
string_view fmt = m_stringmem.emplace(spec->m_format).first->c_str();
|
|
||||||
fmtPtr->setSpec(type, FormatSpec(spec->m_scale, fmt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
description->format(fmtPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Category *
|
|
||||||
Registry::findCategory(string_view category) const
|
|
||||||
{
|
|
||||||
absl::ReaderMutexLock l(&m_mutex);
|
|
||||||
auto it = m_categories.find(category);
|
|
||||||
return it == m_categories.end() ? nullptr : it->second.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Id
|
|
||||||
Registry::findId(string_view category, string_view name) const
|
|
||||||
{
|
|
||||||
absl::ReaderMutexLock l(&m_mutex);
|
|
||||||
auto it = m_metrics.find(std::make_tuple(category, name));
|
|
||||||
return it == m_metrics.end() ? Id() : Id(it->second.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector< const Category * >
|
|
||||||
Registry::getAll() const
|
|
||||||
{
|
|
||||||
absl::ReaderMutexLock l(&m_mutex);
|
|
||||||
|
|
||||||
std::vector< const Category * > result;
|
|
||||||
result.reserve(m_categories.size());
|
|
||||||
|
|
||||||
std::transform(m_categories.begin(), m_categories.end(),
|
|
||||||
std::back_inserter(result),
|
|
||||||
[](const auto &x) { return x.second.get(); });
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PublisherHelper
|
|
||||||
{
|
|
||||||
using SampleCache = std::map< std::shared_ptr< Publisher >, Sample >;
|
|
||||||
|
|
||||||
static void
|
|
||||||
updateSampleCache(SampleCache &cache,
|
|
||||||
const std::shared_ptr< Publisher > &publisher,
|
|
||||||
const SampleGroup< double > &doubleGroup,
|
|
||||||
const SampleGroup< int > &intGroup,
|
|
||||||
const absl::Time &timeStamp)
|
|
||||||
{
|
|
||||||
auto it = cache.find(publisher);
|
|
||||||
if(it == cache.end())
|
|
||||||
{
|
|
||||||
Sample sample;
|
|
||||||
sample.sampleTime(timeStamp);
|
|
||||||
it = cache.emplace(publisher, sample).first;
|
|
||||||
}
|
|
||||||
it->second.pushGroup(doubleGroup);
|
|
||||||
it->second.pushGroup(intGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CollectResult
|
|
||||||
{
|
|
||||||
Records records;
|
|
||||||
absl::Duration samplePeriod;
|
|
||||||
};
|
|
||||||
|
|
||||||
static CollectResult
|
|
||||||
collect(Manager &manager, const Category *category,
|
|
||||||
const absl::Duration &now, bool clear)
|
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(manager.m_mutex)
|
|
||||||
{
|
|
||||||
// Collect records from the repo.
|
|
||||||
const Records result = clear
|
|
||||||
? Records(manager.m_doubleRepo.collectAndClear(category),
|
|
||||||
manager.m_intRepo.collectAndClear(category))
|
|
||||||
: Records(manager.m_doubleRepo.collect(category),
|
|
||||||
manager.m_intRepo.collect(category));
|
|
||||||
|
|
||||||
// Get the time since last reset, and clear if needed.
|
|
||||||
auto it = manager.m_resetTimes.find(category);
|
|
||||||
if(it == manager.m_resetTimes.end())
|
|
||||||
{
|
|
||||||
if(clear)
|
|
||||||
{
|
|
||||||
manager.m_resetTimes.emplace(category, now);
|
|
||||||
}
|
|
||||||
return {result, now - manager.m_createTime};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto tmp = now - it->second;
|
|
||||||
if(clear)
|
|
||||||
{
|
|
||||||
it->second = now;
|
|
||||||
}
|
|
||||||
return {result, tmp};
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
using RecordBuffer = std::vector<
|
|
||||||
std::shared_ptr< std::vector< TaggedRecords< Type > > > >;
|
|
||||||
|
|
||||||
template < typename CategoryIterator >
|
|
||||||
static void
|
|
||||||
publish(Manager &manager, const CategoryIterator &categoriesBegin,
|
|
||||||
const CategoryIterator &categoriesEnd, bool clear)
|
|
||||||
{
|
|
||||||
if(categoriesBegin == categoriesEnd)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordBuffer< double > doubleRecordBuffer;
|
|
||||||
RecordBuffer< int > intRecordBuffer;
|
|
||||||
|
|
||||||
SampleCache sampleCache;
|
|
||||||
|
|
||||||
absl::Time timeStamp = absl::Now();
|
|
||||||
absl::Duration now = absl::Now() - absl::UnixEpoch();
|
|
||||||
{
|
|
||||||
// 1.
|
|
||||||
absl::WriterMutexLock publishGuard(&manager.m_publishLock);
|
|
||||||
// 2.
|
|
||||||
absl::WriterMutexLock propertiesGuard(&manager.m_mutex);
|
|
||||||
|
|
||||||
// Build the 'sampleCache' by iterating over the categories and
|
|
||||||
// collecting records for those categories.
|
|
||||||
for(CategoryIterator catIt = categoriesBegin; catIt != categoriesEnd;
|
|
||||||
++catIt)
|
|
||||||
{
|
|
||||||
if(!(*catIt)->enabled())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Collect the metrics.
|
|
||||||
auto result = collect(manager, *catIt, now, clear);
|
|
||||||
const auto &records = result.records;
|
|
||||||
|
|
||||||
// If there are no collected records then this category can be
|
|
||||||
// ignored.
|
|
||||||
if(records.doubleRecords.empty() && records.intRecords.empty())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result.samplePeriod == absl::Duration())
|
|
||||||
{
|
|
||||||
std::cerr << "Invalid elapsed time interval of 0 for "
|
|
||||||
"published metrics.";
|
|
||||||
result.samplePeriod += absl::Nanoseconds(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the collected records to the buffer of records.
|
|
||||||
auto dRecords =
|
|
||||||
std::make_shared< DoubleRecords >(records.doubleRecords);
|
|
||||||
doubleRecordBuffer.push_back(dRecords);
|
|
||||||
SampleGroup< double > doubleGroup(
|
|
||||||
absl::Span< const TaggedRecords< double > >(*dRecords),
|
|
||||||
result.samplePeriod);
|
|
||||||
|
|
||||||
auto iRecords = std::make_shared< IntRecords >(records.intRecords);
|
|
||||||
intRecordBuffer.push_back(iRecords);
|
|
||||||
SampleGroup< int > intGroup(
|
|
||||||
absl::Span< const TaggedRecords< int > >(*iRecords),
|
|
||||||
result.samplePeriod);
|
|
||||||
|
|
||||||
std::for_each(manager.m_publishers.globalBegin(),
|
|
||||||
manager.m_publishers.globalEnd(),
|
|
||||||
[&](const auto &ptr) {
|
|
||||||
updateSampleCache(sampleCache, ptr, doubleGroup,
|
|
||||||
intGroup, timeStamp);
|
|
||||||
});
|
|
||||||
|
|
||||||
std::for_each(manager.m_publishers.lowerBound(*catIt),
|
|
||||||
manager.m_publishers.upperBound(*catIt),
|
|
||||||
[&](const auto &val) {
|
|
||||||
updateSampleCache(sampleCache, val.second,
|
|
||||||
doubleGroup, intGroup, timeStamp);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto &entry : sampleCache)
|
|
||||||
{
|
|
||||||
Publisher *publisher = entry.first.get();
|
|
||||||
|
|
||||||
publisher->publish(entry.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Sample
|
|
||||||
Manager::collectSample(Records &records,
|
|
||||||
absl::Span< const Category * > categories,
|
|
||||||
bool clear)
|
|
||||||
{
|
|
||||||
absl::Time timeStamp = absl::Now();
|
|
||||||
absl::Duration now = timeStamp - absl::UnixEpoch();
|
|
||||||
|
|
||||||
Sample sample;
|
|
||||||
sample.sampleTime(timeStamp);
|
|
||||||
|
|
||||||
// Use a tuple to hold 'references' to the collected records
|
|
||||||
using SampleDescription = std::tuple< size_t, size_t, absl::Duration >;
|
|
||||||
std::vector< SampleDescription > dSamples;
|
|
||||||
std::vector< SampleDescription > iSamples;
|
|
||||||
dSamples.reserve(categories.size());
|
|
||||||
iSamples.reserve(categories.size());
|
|
||||||
|
|
||||||
// 1
|
|
||||||
absl::WriterMutexLock publishGuard(&m_publishLock);
|
|
||||||
// 2
|
|
||||||
absl::WriterMutexLock propertiesGuard(&m_mutex);
|
|
||||||
|
|
||||||
for(const Category *const category : categories)
|
|
||||||
{
|
|
||||||
if(!category->enabled())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t dBeginIndex = records.doubleRecords.size();
|
|
||||||
size_t iBeginIndex = records.intRecords.size();
|
|
||||||
|
|
||||||
// Collect the metrics.
|
|
||||||
auto collectRes = PublisherHelper::collect(*this, category, now, clear);
|
|
||||||
DoubleRecords catDRecords = collectRes.records.doubleRecords;
|
|
||||||
IntRecords catIRecords = collectRes.records.intRecords;
|
|
||||||
|
|
||||||
absl::Duration elapsedTime = collectRes.samplePeriod;
|
|
||||||
|
|
||||||
records.doubleRecords.insert(records.doubleRecords.end(),
|
|
||||||
catDRecords.begin(), catDRecords.end());
|
|
||||||
records.intRecords.insert(records.intRecords.end(), catIRecords.begin(),
|
|
||||||
catIRecords.end());
|
|
||||||
|
|
||||||
size_t dSize = records.doubleRecords.size() - dBeginIndex;
|
|
||||||
size_t iSize = records.intRecords.size() - iBeginIndex;
|
|
||||||
|
|
||||||
// If there are no collected records then this category can be ignored.
|
|
||||||
if(dSize != 0)
|
|
||||||
{
|
|
||||||
dSamples.emplace_back(dBeginIndex, dSize, elapsedTime);
|
|
||||||
}
|
|
||||||
if(iSize != 0)
|
|
||||||
{
|
|
||||||
iSamples.emplace_back(iBeginIndex, iSize, elapsedTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we have all the records, we can build our sample
|
|
||||||
for(const SampleDescription &s : dSamples)
|
|
||||||
{
|
|
||||||
sample.pushGroup(&records.doubleRecords[std::get< 0 >(s)],
|
|
||||||
std::get< 1 >(s), std::get< 2 >(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const SampleDescription &s : iSamples)
|
|
||||||
{
|
|
||||||
sample.pushGroup(&records.intRecords[std::get< 0 >(s)],
|
|
||||||
std::get< 1 >(s), std::get< 2 >(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Manager::publish(absl::Span< const Category * > categories, bool clear)
|
|
||||||
{
|
|
||||||
PublisherHelper::publish(*this, categories.begin(), categories.end(),
|
|
||||||
clear);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Manager::publish(const std::set< const Category * > &categories, bool clear)
|
|
||||||
{
|
|
||||||
PublisherHelper::publish(*this, categories.begin(), categories.end(),
|
|
||||||
clear);
|
|
||||||
}
|
|
||||||
|
|
||||||
Manager *DefaultManager::m_manager = nullptr;
|
|
||||||
|
|
||||||
struct PublisherSchedulerData
|
|
||||||
{
|
|
||||||
util::Mutex m_mutex;
|
|
||||||
thread::Scheduler::Handle m_handle GUARDED_BY(m_mutex);
|
|
||||||
std::set< const Category * > m_categories GUARDED_BY(m_mutex);
|
|
||||||
|
|
||||||
bool m_default GUARDED_BY(m_mutex){false};
|
|
||||||
std::set< const Category * > m_nonDefaultCategories GUARDED_BY(m_mutex);
|
|
||||||
|
|
||||||
PublisherSchedulerData() : m_handle(thread::Scheduler::INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reverts a publisher scheduler back to its default state
|
|
||||||
class PublisherSchedulerGuard
|
|
||||||
{
|
|
||||||
PublisherScheduler *m_scheduler;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PublisherSchedulerGuard(PublisherScheduler *scheduler)
|
|
||||||
: m_scheduler(scheduler)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~PublisherSchedulerGuard()
|
|
||||||
{
|
|
||||||
if(m_scheduler != nullptr)
|
|
||||||
{
|
|
||||||
for(auto &repeat : m_scheduler->m_repeaters)
|
|
||||||
{
|
|
||||||
if(repeat.second->m_handle != thread::Scheduler::INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
m_scheduler->m_scheduler.cancelRepeat(repeat.second->m_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_scheduler->m_defaultInterval = absl::Duration();
|
|
||||||
m_scheduler->m_repeaters.clear();
|
|
||||||
m_scheduler->m_categories.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
release()
|
|
||||||
{
|
|
||||||
m_scheduler = nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
PublisherScheduler::publish(
|
|
||||||
const std::shared_ptr< PublisherSchedulerData > &data) const
|
|
||||||
{
|
|
||||||
util::Lock l(&data->m_mutex);
|
|
||||||
if(data->m_default)
|
|
||||||
{
|
|
||||||
m_manager->publishAllExcluding(data->m_nonDefaultCategories);
|
|
||||||
}
|
|
||||||
else if(!data->m_categories.empty())
|
|
||||||
{
|
|
||||||
m_manager->publish(data->m_categories);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PublisherScheduler::cancel(Categories::iterator it)
|
|
||||||
{
|
|
||||||
assert(it != m_categories.end());
|
|
||||||
auto repeatIt = m_repeaters.find(it->second);
|
|
||||||
assert(repeatIt != m_repeaters.end());
|
|
||||||
|
|
||||||
const Category *category = it->first;
|
|
||||||
m_categories.erase(it);
|
|
||||||
auto data = repeatIt->second;
|
|
||||||
|
|
||||||
util::Lock l(&data->m_mutex);
|
|
||||||
assert(data->m_categories.find(category) != data->m_categories.end());
|
|
||||||
data->m_categories.erase(category);
|
|
||||||
|
|
||||||
if(!data->m_default)
|
|
||||||
{
|
|
||||||
if(data->m_categories.empty())
|
|
||||||
{
|
|
||||||
m_scheduler.cancelRepeat(data->m_handle);
|
|
||||||
m_repeaters.erase(repeatIt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_defaultInterval != absl::Duration())
|
|
||||||
{
|
|
||||||
auto defaultIntervalIt = m_repeaters.find(m_defaultInterval);
|
|
||||||
assert(defaultIntervalIt != m_repeaters.end());
|
|
||||||
|
|
||||||
auto &defaultRepeater = defaultIntervalIt->second;
|
|
||||||
util::Lock lock(&defaultRepeater->m_mutex);
|
|
||||||
defaultRepeater->m_nonDefaultCategories.erase(category);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PublisherScheduler::cancelDefault()
|
|
||||||
{
|
|
||||||
if(m_defaultInterval == absl::Duration())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Duration interval = m_defaultInterval;
|
|
||||||
m_defaultInterval = absl::Duration();
|
|
||||||
|
|
||||||
auto repeatIt = m_repeaters.find(interval);
|
|
||||||
assert(repeatIt != m_repeaters.end());
|
|
||||||
auto data = repeatIt->second;
|
|
||||||
|
|
||||||
util::Lock l(&data->m_mutex);
|
|
||||||
|
|
||||||
if(data->m_categories.empty())
|
|
||||||
{
|
|
||||||
assert(data->m_handle != thread::Scheduler::INVALID_HANDLE);
|
|
||||||
m_scheduler.cancelRepeat(data->m_handle);
|
|
||||||
m_repeaters.erase(repeatIt);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data->m_default = false;
|
|
||||||
data->m_nonDefaultCategories.clear();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PublisherScheduler::schedule(const Category *category,
|
|
||||||
absl::Duration interval)
|
|
||||||
{
|
|
||||||
assert(absl::Seconds(0) < interval);
|
|
||||||
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
|
|
||||||
auto catIt = m_categories.find(category);
|
|
||||||
if(catIt != m_categories.end())
|
|
||||||
{
|
|
||||||
if(catIt->second == interval)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cancel(catIt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a guard, so if something throws, the scheduler is reset to a
|
|
||||||
// somewhat "sane" state (no metrics).
|
|
||||||
PublisherSchedulerGuard guard(this);
|
|
||||||
|
|
||||||
m_categories.emplace(category, interval);
|
|
||||||
auto repeatIt = m_repeaters.find(interval);
|
|
||||||
std::shared_ptr< PublisherSchedulerData > data;
|
|
||||||
|
|
||||||
// Create a new 'ClockData' object if one does not exist for the
|
|
||||||
// 'interval', otherwise update the existing 'data'.
|
|
||||||
if(repeatIt == m_repeaters.end())
|
|
||||||
{
|
|
||||||
data = std::make_shared< PublisherSchedulerData >();
|
|
||||||
util::Lock lock(&data->m_mutex);
|
|
||||||
data->m_categories.insert(category);
|
|
||||||
m_repeaters.emplace(interval, data);
|
|
||||||
data->m_handle = m_scheduler.scheduleRepeat(
|
|
||||||
interval, std::bind(&PublisherScheduler::publish, this, data));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data = repeatIt->second;
|
|
||||||
util::Lock lock(&data->m_mutex);
|
|
||||||
data->m_categories.insert(category);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this isn't being added to the default schedule, then add to the set
|
|
||||||
// of non-default categories in the default schedule.
|
|
||||||
|
|
||||||
util::Lock dataLock(&data->m_mutex);
|
|
||||||
if(!data->m_default && m_defaultInterval != absl::Duration())
|
|
||||||
{
|
|
||||||
auto defaultIntervalIt = m_repeaters.find(m_defaultInterval);
|
|
||||||
assert(defaultIntervalIt != m_repeaters.end());
|
|
||||||
|
|
||||||
auto &defaultInterval = defaultIntervalIt->second;
|
|
||||||
util::Lock lock(&defaultInterval->m_mutex);
|
|
||||||
defaultInterval->m_nonDefaultCategories.insert(category);
|
|
||||||
}
|
|
||||||
|
|
||||||
guard.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PublisherScheduler::setDefault(absl::Duration interval)
|
|
||||||
{
|
|
||||||
assert(absl::Seconds(0) < interval);
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
|
|
||||||
// If its already this interval, return early.
|
|
||||||
if(interval == m_defaultInterval)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelDefault();
|
|
||||||
m_defaultInterval = interval;
|
|
||||||
|
|
||||||
// Make a guard, so if something throws, the scheduler is reset to a
|
|
||||||
// somewhat "sane" state (no metrics).
|
|
||||||
PublisherSchedulerGuard guard(this);
|
|
||||||
|
|
||||||
std::shared_ptr< PublisherSchedulerData > data;
|
|
||||||
auto repeatIt = m_repeaters.find(interval);
|
|
||||||
if(repeatIt == m_repeaters.end())
|
|
||||||
{
|
|
||||||
data = std::make_shared< PublisherSchedulerData >();
|
|
||||||
m_repeaters.emplace(interval, data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data = repeatIt->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
util::Lock lock(&data->m_mutex);
|
|
||||||
data->m_default = true;
|
|
||||||
|
|
||||||
auto cIt = m_categories.begin();
|
|
||||||
for(; cIt != m_categories.end(); ++cIt)
|
|
||||||
{
|
|
||||||
if(cIt->second != interval)
|
|
||||||
{
|
|
||||||
data->m_nonDefaultCategories.insert(cIt->first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data->m_handle == thread::Scheduler::INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
data->m_handle = m_scheduler.scheduleRepeat(
|
|
||||||
interval, std::bind(&PublisherScheduler::publish, this, data));
|
|
||||||
}
|
|
||||||
|
|
||||||
guard.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PublisherScheduler::cancel(const Category *category)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
|
|
||||||
auto it = m_categories.find(category);
|
|
||||||
if(it == m_categories.end())
|
|
||||||
{
|
|
||||||
// This category has no specific schedule.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cancel(it);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PublisherScheduler::clearDefault()
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
return cancelDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PublisherScheduler::cancelAll()
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
for(auto &repeat : m_repeaters)
|
|
||||||
{
|
|
||||||
util::Lock dataLock(&repeat.second->m_mutex);
|
|
||||||
m_scheduler.cancelRepeat(repeat.second->m_handle, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_defaultInterval = absl::Duration();
|
|
||||||
m_repeaters.clear();
|
|
||||||
m_categories.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
nonstd::optional< absl::Duration >
|
|
||||||
PublisherScheduler::find(const Category *category) const
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
auto it = m_categories.find(category);
|
|
||||||
|
|
||||||
if(it == m_categories.end())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
nonstd::optional< absl::Duration >
|
|
||||||
PublisherScheduler::getDefault() const
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
|
|
||||||
if(m_defaultInterval == absl::Duration())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_defaultInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector< std::pair< const Category *, absl::Duration > >
|
|
||||||
PublisherScheduler::getAll() const
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
std::vector< std::pair< const Category *, absl::Duration > > result;
|
|
||||||
result.reserve(m_categories.size());
|
|
||||||
std::copy(m_categories.begin(), m_categories.end(),
|
|
||||||
std::back_inserter(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,178 +0,0 @@
|
||||||
#include <util/metrics/json_publisher.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
nlohmann::json
|
|
||||||
tagsToJson(const Tags &tags)
|
|
||||||
{
|
|
||||||
nlohmann::json result;
|
|
||||||
|
|
||||||
std::for_each(tags.begin(), tags.end(), [&](const auto &tag) {
|
|
||||||
absl::visit([&](const auto &t) { result[tag.first] = t; },
|
|
||||||
tag.second);
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
nlohmann::json
|
|
||||||
formatValue(const Record< Value > &record, const Tags &tags,
|
|
||||||
double elapsedTime, Publication::Type publicationType)
|
|
||||||
{
|
|
||||||
switch(publicationType)
|
|
||||||
{
|
|
||||||
case Publication::Type::Unspecified:
|
|
||||||
{
|
|
||||||
assert(false && "Invalid publication type");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Total:
|
|
||||||
{
|
|
||||||
return {{"tags", tagsToJson(tags)}, {"total", record.total()}};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Count:
|
|
||||||
{
|
|
||||||
return {{"tags", tagsToJson(tags)}, {"count", record.count()}};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Min:
|
|
||||||
{
|
|
||||||
return {{"tags", tagsToJson(tags)}, {"min", record.min()}};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Max:
|
|
||||||
{
|
|
||||||
return {{"tags", tagsToJson(tags)}, {"max", record.max()}};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Avg:
|
|
||||||
{
|
|
||||||
return {{"tags", tagsToJson(tags)},
|
|
||||||
{"avg", record.total() / record.count()}};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Rate:
|
|
||||||
{
|
|
||||||
return {{"tags", tagsToJson(tags)},
|
|
||||||
{"rate", record.total() / elapsedTime}};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::RateCount:
|
|
||||||
{
|
|
||||||
return {{"tags", tagsToJson(tags)},
|
|
||||||
{"rateCount", record.count() / elapsedTime}};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
nlohmann::json
|
|
||||||
recordToJson(const TaggedRecords< Value > &taggedRecord,
|
|
||||||
double elapsedTime)
|
|
||||||
{
|
|
||||||
nlohmann::json result;
|
|
||||||
result["id"] = taggedRecord.id.toString();
|
|
||||||
|
|
||||||
auto publicationType = taggedRecord.id.description()->type();
|
|
||||||
|
|
||||||
for(const auto &rec : taggedRecord.data)
|
|
||||||
{
|
|
||||||
const auto &record = rec.second;
|
|
||||||
if(publicationType != Publication::Type::Unspecified)
|
|
||||||
{
|
|
||||||
result["publicationType"] = Publication::repr(publicationType);
|
|
||||||
|
|
||||||
result["metrics"].push_back(
|
|
||||||
formatValue(record, rec.first, elapsedTime, publicationType));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlohmann::json tmp;
|
|
||||||
tmp["tags"] = tagsToJson(rec.first);
|
|
||||||
tmp["count"] = record.count();
|
|
||||||
tmp["total"] = record.total();
|
|
||||||
|
|
||||||
if(Record< Value >::DEFAULT_MIN() != record.min())
|
|
||||||
{
|
|
||||||
tmp["min"] = record.min();
|
|
||||||
}
|
|
||||||
if(Record< Value >::DEFAULT_MAX() == record.max())
|
|
||||||
{
|
|
||||||
tmp["max"] = record.max();
|
|
||||||
}
|
|
||||||
|
|
||||||
result["metrics"].push_back(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void
|
|
||||||
JsonPublisher::publish(const Sample &values)
|
|
||||||
{
|
|
||||||
if(values.recordCount() == 0)
|
|
||||||
{
|
|
||||||
// nothing to publish
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlohmann::json result;
|
|
||||||
result["sampleTime"] = absl::UnparseFlag(values.sampleTime());
|
|
||||||
result["recordCount"] = values.recordCount();
|
|
||||||
auto gIt = values.begin();
|
|
||||||
auto prev = values.begin();
|
|
||||||
for(; gIt != values.end(); ++gIt)
|
|
||||||
{
|
|
||||||
const double elapsedTime = absl::ToDoubleSeconds(samplePeriod(*gIt));
|
|
||||||
|
|
||||||
if(gIt == prev || samplePeriod(*gIt) != samplePeriod(*prev))
|
|
||||||
{
|
|
||||||
result["elapsedTime"] = elapsedTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::visit(
|
|
||||||
[&](const auto &x) -> void {
|
|
||||||
for(const auto &record : x)
|
|
||||||
{
|
|
||||||
result["record"].emplace_back(
|
|
||||||
recordToJson(record, elapsedTime));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*gIt);
|
|
||||||
|
|
||||||
prev = gIt;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_publish(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
JsonPublisher::directoryPublisher(const nlohmann::json &result,
|
|
||||||
const fs::path &path)
|
|
||||||
{
|
|
||||||
std::ofstream fstream(path.string(), std::ios_base::app);
|
|
||||||
if(!fstream)
|
|
||||||
{
|
|
||||||
std::cerr << "Skipping metrics publish, " << path << " is not a file\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fstream << std::setw(0) << result << '\n';
|
|
||||||
fstream.close();
|
|
||||||
}
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
|
@ -1,40 +0,0 @@
|
||||||
#ifndef LLARP_METRICS_JSON_PUBLISHER_HPP
|
|
||||||
#define LLARP_METRICS_JSON_PUBLISHER_HPP
|
|
||||||
|
|
||||||
#include <util/fs.hpp>
|
|
||||||
#include <util/metrics/core.hpp>
|
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
class JsonPublisher final : public Publisher
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using PublishFunction = std::function< void(const nlohmann::json&) >;
|
|
||||||
|
|
||||||
private:
|
|
||||||
PublishFunction m_publish;
|
|
||||||
|
|
||||||
public:
|
|
||||||
JsonPublisher(PublishFunction publish) : m_publish(std::move(publish))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~JsonPublisher() override = default;
|
|
||||||
|
|
||||||
void
|
|
||||||
publish(const Sample& values) override;
|
|
||||||
|
|
||||||
static void
|
|
||||||
directoryPublisher(const nlohmann::json& result, const fs::path& path);
|
|
||||||
};
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
||||||
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/metrics/metrics.hpp>
|
|
|
@ -1,80 +0,0 @@
|
||||||
#ifndef LLARP_METRICS_HPP
|
|
||||||
#define LLARP_METRICS_HPP
|
|
||||||
|
|
||||||
#include <util/metrics/types.hpp>
|
|
||||||
#include <util/metrics/core.hpp>
|
|
||||||
#include <util/string_view.hpp>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
struct MetricsHelper
|
|
||||||
{
|
|
||||||
static void
|
|
||||||
initContainer(CategoryContainer& container, const char* category)
|
|
||||||
{
|
|
||||||
Manager* manager = DefaultManager::instance();
|
|
||||||
Registry& registry = manager->registry();
|
|
||||||
registry.registerContainer(registry.get(category), container);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setType(const Id& id, Publication::Type type)
|
|
||||||
{
|
|
||||||
Manager* manager = DefaultManager::instance();
|
|
||||||
return manager->registry().publicationType(id, type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename... TagVals >
|
|
||||||
void
|
|
||||||
integerTick(string_view category, string_view metric, int val,
|
|
||||||
TagVals&&... tags)
|
|
||||||
{
|
|
||||||
if(DefaultManager::instance())
|
|
||||||
{
|
|
||||||
CollectorRepo< int >& repository =
|
|
||||||
DefaultManager::instance()->intCollectorRepo();
|
|
||||||
IntCollector* collector = repository.defaultCollector(category, metric);
|
|
||||||
if(collector->id().category()->enabled())
|
|
||||||
{
|
|
||||||
collector->tick(val, tags...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
// Some MSVC flags mess with __LINE__, but __COUNTER__ is better anyway
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define METRICS_UNIQ_NUMBER __COUNTER__
|
|
||||||
#else
|
|
||||||
#define METRICS_UNIQ_NUMBER __LINE__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Use a level of indirection to force the preprocessor to expand args first.
|
|
||||||
#define METRICS_NAME_CAT_IMP(X, Y) X##Y
|
|
||||||
#define METRICS_NAME_CAT(X, Y) METRICS_NAME_CAT_IMP(X, Y)
|
|
||||||
|
|
||||||
#define METRICS_UNIQUE_NAME(X) METRICS_NAME_CAT(X, METRICS_UNIQ_NUMBER)
|
|
||||||
|
|
||||||
// For when the category/metric may change during the program run
|
|
||||||
#define METRICS_DYNAMIC_UPDATE(CAT, METRIC, ...) \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
using namespace llarp::metrics; \
|
|
||||||
if(DefaultManager::instance()) \
|
|
||||||
{ \
|
|
||||||
CollectorRepo< double >& repository = \
|
|
||||||
DefaultManager::instance()->doubleCollectorRepo(); \
|
|
||||||
DoubleCollector* collector = \
|
|
||||||
repository.defaultCollector((CAT), (METRIC)); \
|
|
||||||
if(collector->id().category()->enabled()) \
|
|
||||||
{ \
|
|
||||||
collector->tick(__VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while(false)
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,430 +0,0 @@
|
||||||
#include <util/metrics/metrictank_publisher.hpp>
|
|
||||||
|
|
||||||
#include <util/logging/logger.hpp>
|
|
||||||
#include <util/meta/variant.hpp>
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <absl/strings/str_cat.h>
|
|
||||||
#include <absl/strings/str_join.h>
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
// bzero and friends graduated from /usr/ucb*
|
|
||||||
// not too long ago
|
|
||||||
#include <strings.h>
|
|
||||||
#else
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winsock2.h>
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#include <wspiapi.h>
|
|
||||||
#include <lmcons.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
nonstd::optional< std::string >
|
|
||||||
makeStr(double d)
|
|
||||||
{
|
|
||||||
if(std::isnan(d) || std::isinf(d))
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::to_string(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
nonstd::optional< std::string >
|
|
||||||
makeStr(int i)
|
|
||||||
{
|
|
||||||
if(i == std::numeric_limits< int >::min()
|
|
||||||
|| i == std::numeric_limits< int >::max())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::to_string(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
nonstd::optional< std::string >
|
|
||||||
formatValue(const Record< Value > &record, double elapsedTime,
|
|
||||||
Publication::Type publicationType)
|
|
||||||
{
|
|
||||||
switch(publicationType)
|
|
||||||
{
|
|
||||||
case Publication::Type::Unspecified:
|
|
||||||
{
|
|
||||||
assert(false && "Invalid publication type");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Total:
|
|
||||||
{
|
|
||||||
return makeStr(record.total());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Count:
|
|
||||||
{
|
|
||||||
return std::to_string(record.count());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Min:
|
|
||||||
{
|
|
||||||
return makeStr(record.min());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Max:
|
|
||||||
{
|
|
||||||
return makeStr(record.max());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Avg:
|
|
||||||
{
|
|
||||||
return makeStr(static_cast< double >(record.total())
|
|
||||||
/ static_cast< double >(record.count()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Rate:
|
|
||||||
{
|
|
||||||
return makeStr(record.total() / elapsedTime);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::RateCount:
|
|
||||||
{
|
|
||||||
return makeStr(record.count() / elapsedTime);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(false && "Invalid publication type");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
makeTagStr(const Tags &tags)
|
|
||||||
{
|
|
||||||
std::string tagStr;
|
|
||||||
|
|
||||||
auto overloaded = util::overloaded(
|
|
||||||
[](const std::string &str) { return str; },
|
|
||||||
[](double d) { return std::to_string(d); },
|
|
||||||
[](const std::int64_t i) { return std::to_string(i); });
|
|
||||||
|
|
||||||
for(const auto &tag : tags)
|
|
||||||
{
|
|
||||||
absl::StrAppend(&tagStr, ";", tag.first, "=",
|
|
||||||
absl::visit(overloaded, tag.second));
|
|
||||||
}
|
|
||||||
if(!tags.empty())
|
|
||||||
{
|
|
||||||
absl::StrAppend(&tagStr, ";");
|
|
||||||
}
|
|
||||||
return tagStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
addName(string_view id, string_view name, const Tags &tags,
|
|
||||||
string_view suffix)
|
|
||||||
{
|
|
||||||
return absl::StrCat(id, ".", name, makeTagStr(tags), suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool
|
|
||||||
isValid(int val)
|
|
||||||
{
|
|
||||||
return val != std::numeric_limits< int >::min()
|
|
||||||
&& val != std::numeric_limits< int >::max();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool
|
|
||||||
isValid(double val)
|
|
||||||
{
|
|
||||||
return Record< double >::DEFAULT_MIN() != val
|
|
||||||
&& Record< double >::DEFAULT_MAX() != val && !std::isnan(val)
|
|
||||||
&& !std::isinf(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
std::vector< MetricTankPublisherInterface::PublishData >
|
|
||||||
recordToData(const TaggedRecords< Value > &taggedRecords, absl::Time time,
|
|
||||||
double elapsedTime, string_view suffix)
|
|
||||||
{
|
|
||||||
std::vector< MetricTankPublisherInterface::PublishData > result;
|
|
||||||
|
|
||||||
std::string id = taggedRecords.id.toString();
|
|
||||||
|
|
||||||
auto publicationType = taggedRecords.id.description()->type();
|
|
||||||
|
|
||||||
for(const auto &record : taggedRecords.data)
|
|
||||||
{
|
|
||||||
const auto &tags = record.first;
|
|
||||||
const auto &rec = record.second;
|
|
||||||
if(publicationType != Publication::Type::Unspecified)
|
|
||||||
{
|
|
||||||
auto val = formatValue(rec, elapsedTime, publicationType);
|
|
||||||
|
|
||||||
if(val)
|
|
||||||
{
|
|
||||||
result.emplace_back(
|
|
||||||
addName(id, Publication::repr(publicationType), tags, suffix),
|
|
||||||
val.value(), time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.emplace_back(addName(id, "count", tags, suffix),
|
|
||||||
std::to_string(rec.count()), time);
|
|
||||||
result.emplace_back(addName(id, "total", tags, suffix),
|
|
||||||
std::to_string(rec.total()), time);
|
|
||||||
|
|
||||||
if(isValid(rec.min()))
|
|
||||||
{
|
|
||||||
result.emplace_back(addName(id, "min", tags, suffix),
|
|
||||||
std::to_string(rec.min()), time);
|
|
||||||
}
|
|
||||||
if(isValid(rec.max()))
|
|
||||||
{
|
|
||||||
result.emplace_back(addName(id, "max", tags, suffix),
|
|
||||||
std::to_string(rec.max()), time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
void
|
|
||||||
publishData(const std::vector< std::string > &toSend,
|
|
||||||
const std::string &host, short port)
|
|
||||||
{
|
|
||||||
struct addrinfo hints;
|
|
||||||
struct addrinfo *addrs;
|
|
||||||
bzero(&hints, sizeof(hints));
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
|
|
||||||
const std::string portAsStr = std::to_string(port);
|
|
||||||
|
|
||||||
if(getaddrinfo(host.c_str(), portAsStr.c_str(), &hints, &addrs) != 0)
|
|
||||||
{
|
|
||||||
LogError("Failed to get address info");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sock =
|
|
||||||
::socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
|
|
||||||
|
|
||||||
if(sock < 0)
|
|
||||||
{
|
|
||||||
LogError("Failed to open socket");
|
|
||||||
freeaddrinfo(addrs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(connect(sock, addrs->ai_addr, addrs->ai_addrlen) < 0)
|
|
||||||
{
|
|
||||||
LogError("Failed to connect to metrictank");
|
|
||||||
close(sock);
|
|
||||||
freeaddrinfo(addrs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(addrs);
|
|
||||||
|
|
||||||
for(const std::string &val : toSend)
|
|
||||||
{
|
|
||||||
ssize_t sentLen = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
sentLen =
|
|
||||||
::send(sock, val.c_str() + sentLen, val.size() - sentLen, 0);
|
|
||||||
if(sentLen == -1)
|
|
||||||
{
|
|
||||||
LogError("Error ", strerror(errno));
|
|
||||||
}
|
|
||||||
} while((0 <= sentLen)
|
|
||||||
&& (static_cast< size_t >(sentLen) < val.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfo("Sent ", toSend.size(), " metrics to metrictank");
|
|
||||||
|
|
||||||
shutdown(sock, SHUT_RDWR);
|
|
||||||
close(sock);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void
|
|
||||||
publishData(const std::vector< std::string > &toSend,
|
|
||||||
const std::string &host, short port)
|
|
||||||
{
|
|
||||||
struct addrinfo *addrs = NULL, hints;
|
|
||||||
ZeroMemory(&hints, sizeof(hints));
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
|
||||||
|
|
||||||
const std::string portAsStr = std::to_string(port);
|
|
||||||
|
|
||||||
if(getaddrinfo(host.c_str(), portAsStr.c_str(), &hints, &addrs) != 0)
|
|
||||||
{
|
|
||||||
LogError("Failed to get address info");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SOCKET sock =
|
|
||||||
::socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
|
|
||||||
|
|
||||||
if(sock == INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
LogError("Failed to open socket");
|
|
||||||
freeaddrinfo(addrs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(connect(sock, addrs->ai_addr, addrs->ai_addrlen) == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
LogError("Failed to connect to metrictank");
|
|
||||||
closesocket(sock);
|
|
||||||
freeaddrinfo(addrs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(addrs);
|
|
||||||
|
|
||||||
for(const std::string &val : toSend)
|
|
||||||
{
|
|
||||||
int sentLen = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
sentLen =
|
|
||||||
::send(sock, val.c_str() + sentLen, val.size() - sentLen, 0);
|
|
||||||
if(sentLen == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
LogError("Error ", strerror(errno));
|
|
||||||
}
|
|
||||||
} while((0 <= sentLen)
|
|
||||||
&& (static_cast< size_t >(sentLen) < val.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdown(sock, SD_SEND);
|
|
||||||
closesocket(sock);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MetricTankPublisherInterface::Tags
|
|
||||||
updateTags(MetricTankPublisherInterface::Tags tags)
|
|
||||||
{
|
|
||||||
if(tags.count("system") == 0)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
|
|
||||||
tags["system"] = "windows";
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
tags["system"] = "macos";
|
|
||||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
|
||||||
tags["system"] = "bsd";
|
|
||||||
#elif defined(__sun)
|
|
||||||
tags["system"] = "solaris";
|
|
||||||
#elif defined(__linux__)
|
|
||||||
tags["system"] = "linux";
|
|
||||||
#else
|
|
||||||
tags["system"] = "unknown";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return tags;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
std::string
|
|
||||||
MetricTankPublisherInterface::makeSuffix(const Tags &tags)
|
|
||||||
{
|
|
||||||
return absl::StrJoin(updateTags(tags), ";", absl::PairFormatter("="));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MetricTankPublisherInterface::publish(const Sample &values)
|
|
||||||
{
|
|
||||||
if(values.recordCount() == 0)
|
|
||||||
{
|
|
||||||
// nothing to publish
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Time sampleTime = values.sampleTime();
|
|
||||||
|
|
||||||
std::vector< PublishData > result;
|
|
||||||
result.reserve(values.recordCount());
|
|
||||||
|
|
||||||
auto gIt = values.begin();
|
|
||||||
auto prev = values.begin();
|
|
||||||
for(; gIt != values.end(); ++gIt)
|
|
||||||
{
|
|
||||||
const double elapsedTime = absl::ToDoubleSeconds(samplePeriod(*gIt));
|
|
||||||
|
|
||||||
absl::visit(
|
|
||||||
[&](const auto &d) {
|
|
||||||
for(const auto &record : d)
|
|
||||||
{
|
|
||||||
auto partial =
|
|
||||||
recordToData(record, sampleTime, elapsedTime, m_suffix);
|
|
||||||
result.insert(result.end(), partial.begin(), partial.end());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*gIt);
|
|
||||||
|
|
||||||
prev = gIt;
|
|
||||||
}
|
|
||||||
|
|
||||||
publish(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MetricTankPublisher::publish(const std::vector< PublishData > &data)
|
|
||||||
{
|
|
||||||
if(m_queue.tryPushBack(data) == thread::QueueReturn::QueueFull)
|
|
||||||
{
|
|
||||||
LogWarn("Dropping metrictank logs!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MetricTankPublisher::work()
|
|
||||||
{
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
auto data = m_queue.popFront(); // block until we get something
|
|
||||||
|
|
||||||
// Finish
|
|
||||||
if(absl::holds_alternative< StopStruct >(data))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(absl::holds_alternative< std::vector< PublishData > >(data));
|
|
||||||
|
|
||||||
auto vec = absl::get< std::vector< PublishData > >(data);
|
|
||||||
|
|
||||||
std::vector< std::string > toSend;
|
|
||||||
toSend.reserve(vec.size());
|
|
||||||
|
|
||||||
std::transform(vec.begin(), vec.end(), std::back_inserter(toSend),
|
|
||||||
[](const PublishData &d) -> std::string {
|
|
||||||
return absl::StrCat(
|
|
||||||
std::get< 0 >(d), " ", std::get< 1 >(d), " ",
|
|
||||||
absl::ToUnixSeconds(std::get< 2 >(d)), "\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
publishData(toSend, m_host, m_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
|
@ -1,90 +0,0 @@
|
||||||
#ifndef LLARP_METRICS_METRICTANK_PUBLISHER_HPP
|
|
||||||
#define LLARP_METRICS_METRICTANK_PUBLISHER_HPP
|
|
||||||
|
|
||||||
#include <util/metrics/core.hpp>
|
|
||||||
|
|
||||||
#include <util/thread/queue.hpp>
|
|
||||||
|
|
||||||
#include <absl/types/variant.h>
|
|
||||||
#include <string>
|
|
||||||
#include <thread>
|
|
||||||
#include <tuple>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
class MetricTankPublisherInterface : public Publisher
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Format for metrictank is <metric path, value, seconds since epoch>
|
|
||||||
// Metric path = metrics.namespaces.metric;key=value;key1=value2
|
|
||||||
using PublishData = std::tuple< std::string, std::string, absl::Time >;
|
|
||||||
using Tags = std::map< std::string, std::string >;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string m_suffix; // tags to send to metric tank
|
|
||||||
|
|
||||||
public:
|
|
||||||
MetricTankPublisherInterface(const Tags& tags)
|
|
||||||
: m_suffix(makeSuffix(tags))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~MetricTankPublisherInterface() override = default;
|
|
||||||
|
|
||||||
static std::string
|
|
||||||
makeSuffix(const Tags& tags);
|
|
||||||
|
|
||||||
void
|
|
||||||
publish(const Sample& values) override;
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
publish(const std::vector< PublishData >& data) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MetricTankPublisher final : public MetricTankPublisherInterface
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const std::string m_host;
|
|
||||||
const short m_port;
|
|
||||||
|
|
||||||
struct StopStruct
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
using Queue = thread::Queue<
|
|
||||||
absl::variant< std::vector< PublishData >, StopStruct > >;
|
|
||||||
|
|
||||||
Queue m_queue; // queue of things to publish
|
|
||||||
std::thread m_worker; // worker thread
|
|
||||||
|
|
||||||
void
|
|
||||||
work();
|
|
||||||
|
|
||||||
public:
|
|
||||||
MetricTankPublisher(const Tags& tags, std::string host, short port)
|
|
||||||
: MetricTankPublisherInterface(tags)
|
|
||||||
, m_host(std::move(host))
|
|
||||||
, m_port(port)
|
|
||||||
, m_queue(100)
|
|
||||||
, m_worker(&MetricTankPublisher::work, this)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~MetricTankPublisher() override
|
|
||||||
{
|
|
||||||
// Push back a signal value onto the queue
|
|
||||||
m_queue.pushBack(StopStruct());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
publish(const std::vector< PublishData >& data) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,196 +0,0 @@
|
||||||
#include <util/metrics/stream_publisher.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
template < typename Value >
|
|
||||||
void
|
|
||||||
formatValue(std::ostream &stream, Value value,
|
|
||||||
const FormatSpec *formatSpec)
|
|
||||||
{
|
|
||||||
if(formatSpec)
|
|
||||||
{
|
|
||||||
FormatSpec::format(stream, static_cast< double >(value), *formatSpec);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream << value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
void
|
|
||||||
formatValue(std::ostream &stream, const Record< Value > &record,
|
|
||||||
double elapsedTime, Publication::Type publicationType,
|
|
||||||
const FormatSpec *formatSpec)
|
|
||||||
{
|
|
||||||
switch(publicationType)
|
|
||||||
{
|
|
||||||
case Publication::Type::Unspecified:
|
|
||||||
{
|
|
||||||
assert(false && "Invalid publication type");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Total:
|
|
||||||
{
|
|
||||||
formatValue(stream, record.total(), formatSpec);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Count:
|
|
||||||
{
|
|
||||||
formatValue(stream, record.count(), formatSpec);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Min:
|
|
||||||
{
|
|
||||||
formatValue(stream, record.min(), formatSpec);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Max:
|
|
||||||
{
|
|
||||||
formatValue(stream, record.max(), formatSpec);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Avg:
|
|
||||||
{
|
|
||||||
formatValue(stream, record.total() / record.count(), formatSpec);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::Rate:
|
|
||||||
{
|
|
||||||
formatValue(stream, record.total() / elapsedTime, formatSpec);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Publication::Type::RateCount:
|
|
||||||
{
|
|
||||||
formatValue(stream, record.count() / elapsedTime, formatSpec);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
void
|
|
||||||
publishRecord(std::ostream &stream,
|
|
||||||
const TaggedRecords< Value > &taggedRecords,
|
|
||||||
double elapsedTime)
|
|
||||||
{
|
|
||||||
auto publicationType = taggedRecords.id.description()->type();
|
|
||||||
std::shared_ptr< const Format > format =
|
|
||||||
taggedRecords.id.description()->format();
|
|
||||||
|
|
||||||
if(taggedRecords.data.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream << "\t\t" << taggedRecords.id << " [";
|
|
||||||
|
|
||||||
for(const auto &rec : taggedRecords.data)
|
|
||||||
{
|
|
||||||
stream << "\n\t\t\t";
|
|
||||||
const auto &tags = rec.first;
|
|
||||||
const auto &record = rec.second;
|
|
||||||
|
|
||||||
{
|
|
||||||
Printer printer(stream, -1, -1);
|
|
||||||
printer.printValue(tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream << " ";
|
|
||||||
|
|
||||||
if(publicationType != Publication::Type::Unspecified)
|
|
||||||
{
|
|
||||||
stream << Publication::repr(publicationType) << " = ";
|
|
||||||
const FormatSpec *formatSpec =
|
|
||||||
format ? format->specFor(publicationType) : nullptr;
|
|
||||||
|
|
||||||
formatValue(stream, record, elapsedTime, publicationType,
|
|
||||||
formatSpec);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const FormatSpec *countSpec = nullptr;
|
|
||||||
const FormatSpec *totalSpec = nullptr;
|
|
||||||
const FormatSpec *minSpec = nullptr;
|
|
||||||
const FormatSpec *maxSpec = nullptr;
|
|
||||||
|
|
||||||
if(format)
|
|
||||||
{
|
|
||||||
countSpec = format->specFor(Publication::Type::Count);
|
|
||||||
totalSpec = format->specFor(Publication::Type::Total);
|
|
||||||
minSpec = format->specFor(Publication::Type::Min);
|
|
||||||
maxSpec = format->specFor(Publication::Type::Max);
|
|
||||||
}
|
|
||||||
stream << "count = ";
|
|
||||||
formatValue(stream, record.count(), countSpec);
|
|
||||||
stream << ", total = ";
|
|
||||||
formatValue(stream, record.total(), totalSpec);
|
|
||||||
if(Record< Value >::DEFAULT_MIN() == record.min())
|
|
||||||
{
|
|
||||||
stream << ", min = undefined";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream << ", min = ";
|
|
||||||
formatValue(stream, record.min(), minSpec);
|
|
||||||
}
|
|
||||||
if(Record< Value >::DEFAULT_MAX() == record.max())
|
|
||||||
{
|
|
||||||
stream << ", max = undefined";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream << ", max = ";
|
|
||||||
formatValue(stream, record.max(), maxSpec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stream << "\n\t\t]\n";
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void
|
|
||||||
StreamPublisher::publish(const Sample &values)
|
|
||||||
{
|
|
||||||
if(values.recordCount() == 0)
|
|
||||||
{
|
|
||||||
// nothing to publish
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_stream << values.sampleTime() << " " << values.recordCount()
|
|
||||||
<< " Records\n";
|
|
||||||
|
|
||||||
auto gIt = values.begin();
|
|
||||||
auto prev = values.begin();
|
|
||||||
for(; gIt != values.end(); ++gIt)
|
|
||||||
{
|
|
||||||
const double elapsedTime = absl::ToDoubleSeconds(samplePeriod(*gIt));
|
|
||||||
|
|
||||||
if(gIt == prev || samplePeriod(*gIt) != samplePeriod(*prev))
|
|
||||||
{
|
|
||||||
m_stream << "\tElapsed Time: " << elapsedTime << "s\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::visit(
|
|
||||||
[&](const auto &x) {
|
|
||||||
for(const auto &record : x)
|
|
||||||
{
|
|
||||||
publishRecord(m_stream, record, elapsedTime);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*gIt);
|
|
||||||
|
|
||||||
prev = gIt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
|
@ -1,30 +0,0 @@
|
||||||
#ifndef LLARP_METRICS_STREAM_PUBLISHER_HPP
|
|
||||||
#define LLARP_METRICS_STREAM_PUBLISHER_HPP
|
|
||||||
|
|
||||||
#include <util/metrics/core.hpp>
|
|
||||||
|
|
||||||
#include <iosfwd>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
class StreamPublisher final : public Publisher
|
|
||||||
{
|
|
||||||
std::ostream& m_stream;
|
|
||||||
|
|
||||||
public:
|
|
||||||
StreamPublisher(std::ostream& stream) : m_stream(stream)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~StreamPublisher() override = default;
|
|
||||||
|
|
||||||
void
|
|
||||||
publish(const Sample& values) override;
|
|
||||||
};
|
|
||||||
} // namespace metrics
|
|
||||||
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,145 +0,0 @@
|
||||||
#include <util/metrics/types.hpp>
|
|
||||||
|
|
||||||
#include <util/printer.hpp>
|
|
||||||
|
|
||||||
#include <absl/strings/str_join.h>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
std::ostream &
|
|
||||||
FormatSpec::format(std::ostream &stream, double data,
|
|
||||||
const FormatSpec &format)
|
|
||||||
{
|
|
||||||
static constexpr size_t INIT_SIZE = 32;
|
|
||||||
|
|
||||||
char buf[INIT_SIZE] = {0};
|
|
||||||
int rc = snprintf(buf, INIT_SIZE, format.m_format.data(),
|
|
||||||
data * format.m_scale);
|
|
||||||
|
|
||||||
if(rc < 0)
|
|
||||||
{
|
|
||||||
stream << "Bad format " << format.m_format << " applied to " << data;
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(static_cast< size_t >(rc) < INIT_SIZE)
|
|
||||||
{
|
|
||||||
stream << buf;
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector< char > vec(rc + 1);
|
|
||||||
rc = snprintf(vec.data(), vec.size(), format.m_format.data(),
|
|
||||||
data * format.m_scale);
|
|
||||||
|
|
||||||
if(static_cast< size_t >(rc) > vec.size())
|
|
||||||
{
|
|
||||||
stream << "Bad format " << format.m_format << " applied to " << data;
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream << vec.data();
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_view
|
|
||||||
Publication::repr(Type val)
|
|
||||||
{
|
|
||||||
switch(val)
|
|
||||||
{
|
|
||||||
case Type::Unspecified:
|
|
||||||
return "Unspecified";
|
|
||||||
case Type::Total:
|
|
||||||
return "Total";
|
|
||||||
case Type::Count:
|
|
||||||
return "Count";
|
|
||||||
case Type::Min:
|
|
||||||
return "Min";
|
|
||||||
case Type::Max:
|
|
||||||
return "Max";
|
|
||||||
case Type::Avg:
|
|
||||||
return "Avg";
|
|
||||||
case Type::Rate:
|
|
||||||
return "Rate";
|
|
||||||
case Type::RateCount:
|
|
||||||
return "RateCount";
|
|
||||||
default:
|
|
||||||
return "???";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
Publication::print(std::ostream &stream, Type val)
|
|
||||||
{
|
|
||||||
stream << repr(val);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
Category::~Category()
|
|
||||||
{
|
|
||||||
while(m_container)
|
|
||||||
{
|
|
||||||
auto next = m_container->m_nextCategory;
|
|
||||||
m_container->clear();
|
|
||||||
m_container = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Category::enabled(bool val)
|
|
||||||
{
|
|
||||||
// sync point
|
|
||||||
if(m_enabled != val)
|
|
||||||
{
|
|
||||||
auto cont = m_container;
|
|
||||||
while(cont)
|
|
||||||
{
|
|
||||||
cont->m_enabled = val;
|
|
||||||
cont = cont->m_nextCategory;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_enabled = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Category::registerContainer(CategoryContainer *container)
|
|
||||||
{
|
|
||||||
container->m_enabled = m_enabled;
|
|
||||||
container->m_category = this;
|
|
||||||
container->m_nextCategory = m_container;
|
|
||||||
m_container = container;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
Category::print(std::ostream &stream, int level, int spaces) const
|
|
||||||
{
|
|
||||||
Printer printer(stream, level, spaces);
|
|
||||||
printer.printAttribute("name", m_name);
|
|
||||||
printer.printAttribute("enabled",
|
|
||||||
m_enabled.load(std::memory_order_relaxed));
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
Description::toString() const
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
return absl::StrCat(m_category->name(), ".", m_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
Description::print(std::ostream &stream) const
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
|
|
||||||
stream << m_category->name() << '.' << m_name;
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
} // namespace metrics
|
|
||||||
|
|
||||||
} // namespace llarp
|
|
|
@ -1,675 +0,0 @@
|
||||||
#ifndef LLARP_METRICS_TYPES_HPP
|
|
||||||
#define LLARP_METRICS_TYPES_HPP
|
|
||||||
|
|
||||||
#include <util/printer.hpp>
|
|
||||||
#include <util/string_view.hpp>
|
|
||||||
#include <util/thread/threading.hpp>
|
|
||||||
#include <util/types.hpp>
|
|
||||||
#include <util/meta/variant.hpp>
|
|
||||||
|
|
||||||
#include <absl/container/flat_hash_map.h>
|
|
||||||
#include <absl/container/flat_hash_set.h>
|
|
||||||
#include <absl/hash/hash.h>
|
|
||||||
#include <nonstd/optional.hpp>
|
|
||||||
#include <absl/types/span.h>
|
|
||||||
#include <absl/types/variant.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <memory>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace metrics
|
|
||||||
{
|
|
||||||
struct Publication
|
|
||||||
{
|
|
||||||
enum class Type : byte_t
|
|
||||||
{
|
|
||||||
Unspecified = 0, // no associated metric type
|
|
||||||
Total, // sum of seen values in the measurement period
|
|
||||||
Count, // count of seen events
|
|
||||||
Min, // Minimum value
|
|
||||||
Max, // Max value
|
|
||||||
Avg, // total / count
|
|
||||||
Rate, // total per second
|
|
||||||
RateCount // count per second
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MaxSize = static_cast< byte_t >(Type::RateCount) + 1
|
|
||||||
};
|
|
||||||
|
|
||||||
static string_view
|
|
||||||
repr(Type val);
|
|
||||||
|
|
||||||
static std::ostream &
|
|
||||||
print(std::ostream &stream, Type val);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FormatSpec
|
|
||||||
{
|
|
||||||
float m_scale{1.0};
|
|
||||||
string_view m_format;
|
|
||||||
|
|
||||||
static constexpr char DEFAULT_FORMAT[] = "%f";
|
|
||||||
|
|
||||||
constexpr FormatSpec() : m_format(DEFAULT_FORMAT)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr FormatSpec(float scale, string_view format)
|
|
||||||
: m_scale(scale), m_format(format)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::ostream &
|
|
||||||
format(std::ostream &stream, double data, const FormatSpec &spec);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
operator==(const FormatSpec &lhs, const FormatSpec &rhs)
|
|
||||||
{
|
|
||||||
return std::make_tuple(lhs.m_scale, lhs.m_format)
|
|
||||||
== std::make_tuple(rhs.m_scale, rhs.m_format);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Format
|
|
||||||
{
|
|
||||||
using Spec = nonstd::optional< FormatSpec >;
|
|
||||||
|
|
||||||
std::array< Spec, Publication::MaxSize > m_specs;
|
|
||||||
|
|
||||||
constexpr Format() : m_specs()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
setSpec(Publication::Type pub, const FormatSpec &spec)
|
|
||||||
{
|
|
||||||
m_specs[static_cast< size_t >(pub)].emplace(spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clear()
|
|
||||||
{
|
|
||||||
for(auto &s : m_specs)
|
|
||||||
s.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const FormatSpec *
|
|
||||||
specFor(Publication::Type val) const
|
|
||||||
{
|
|
||||||
const auto &spec = m_specs[static_cast< size_t >(val)];
|
|
||||||
return spec ? &spec.value() : nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
operator==(const Format &lhs, const Format &rhs)
|
|
||||||
{
|
|
||||||
return lhs.m_specs == rhs.m_specs;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CategoryContainer;
|
|
||||||
|
|
||||||
/// Represents a category of grouped metrics
|
|
||||||
class Category
|
|
||||||
{
|
|
||||||
string_view m_name;
|
|
||||||
std::atomic_bool m_enabled;
|
|
||||||
CategoryContainer *m_container;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Category(string_view name, bool enabled = true)
|
|
||||||
: m_name(name), m_enabled(enabled), m_container(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~Category();
|
|
||||||
|
|
||||||
void
|
|
||||||
enabled(bool flag);
|
|
||||||
|
|
||||||
void
|
|
||||||
registerContainer(CategoryContainer *container);
|
|
||||||
|
|
||||||
const std::atomic_bool &
|
|
||||||
enabledRaw() const
|
|
||||||
{
|
|
||||||
return m_enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_view
|
|
||||||
name() const
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
enabled() const
|
|
||||||
{
|
|
||||||
return m_enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
print(std::ostream &stream, int level, int spaces) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::ostream &
|
|
||||||
operator<<(std::ostream &stream, const Category &c)
|
|
||||||
{
|
|
||||||
return c.print(stream, -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CategoryContainer
|
|
||||||
{
|
|
||||||
bool m_enabled;
|
|
||||||
const Category *m_category;
|
|
||||||
CategoryContainer *m_nextCategory;
|
|
||||||
|
|
||||||
constexpr void
|
|
||||||
clear()
|
|
||||||
{
|
|
||||||
m_enabled = false;
|
|
||||||
m_category = nullptr;
|
|
||||||
m_nextCategory = nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Description
|
|
||||||
{
|
|
||||||
mutable util::Mutex m_mutex;
|
|
||||||
|
|
||||||
const Category *m_category GUARDED_BY(m_mutex);
|
|
||||||
string_view m_name GUARDED_BY(m_mutex);
|
|
||||||
Publication::Type m_type GUARDED_BY(m_mutex);
|
|
||||||
std::shared_ptr< Format > m_format GUARDED_BY(m_mutex);
|
|
||||||
|
|
||||||
Description(const Description &) = delete;
|
|
||||||
Description &
|
|
||||||
operator=(const Description &) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Description(const Category *category, string_view name)
|
|
||||||
: m_category(category)
|
|
||||||
, m_name(name)
|
|
||||||
, m_type(Publication::Type::Unspecified)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
category(const Category *c) LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
m_category = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Category *
|
|
||||||
category() const LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
return m_category;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
name(string_view n) LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
m_name = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_view
|
|
||||||
name() const LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
type(Publication::Type t) LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
m_type = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
Publication::Type
|
|
||||||
type() const LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
return m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
format(const std::shared_ptr< Format > &f) LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
m_format = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr< Format >
|
|
||||||
format() const LOCKS_EXCLUDED(m_mutex)
|
|
||||||
{
|
|
||||||
util::Lock l(&m_mutex);
|
|
||||||
return m_format;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
toString() const;
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
print(std::ostream &stream) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::ostream &
|
|
||||||
operator<<(std::ostream &stream, const Description &d)
|
|
||||||
{
|
|
||||||
return d.print(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A metric id is what we will actually deal with in terms of metrics, in
|
|
||||||
/// order to make things like static initialisation cleaner.
|
|
||||||
class Id
|
|
||||||
{
|
|
||||||
const Description *m_description{nullptr};
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr Id() = default;
|
|
||||||
|
|
||||||
constexpr Id(const Description *description) : m_description(description)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const Description *&
|
|
||||||
description()
|
|
||||||
{
|
|
||||||
return m_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const Description *const &
|
|
||||||
description() const
|
|
||||||
{
|
|
||||||
return m_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
valid() const noexcept
|
|
||||||
{
|
|
||||||
return m_description != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const noexcept
|
|
||||||
{
|
|
||||||
return valid();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Category *
|
|
||||||
category() const
|
|
||||||
{
|
|
||||||
assert(valid());
|
|
||||||
return m_description->category();
|
|
||||||
}
|
|
||||||
|
|
||||||
string_view
|
|
||||||
categoryName() const
|
|
||||||
{
|
|
||||||
assert(valid());
|
|
||||||
return m_description->category()->name();
|
|
||||||
}
|
|
||||||
|
|
||||||
string_view
|
|
||||||
metricName() const
|
|
||||||
{
|
|
||||||
assert(valid());
|
|
||||||
return m_description->name();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
toString() const
|
|
||||||
{
|
|
||||||
if(m_description)
|
|
||||||
{
|
|
||||||
return m_description->toString();
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "INVALID_METRIC";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
print(std::ostream &stream, int, int) const
|
|
||||||
{
|
|
||||||
if(m_description)
|
|
||||||
{
|
|
||||||
stream << *m_description;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream << "INVALID_METRIC";
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
operator==(const Id &lhs, const Id &rhs)
|
|
||||||
{
|
|
||||||
return lhs.description() == rhs.description();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
operator<(const Id &lhs, const Id &rhs)
|
|
||||||
{
|
|
||||||
return lhs.description() < rhs.description();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream &
|
|
||||||
operator<<(std::ostream &stream, const Id &id)
|
|
||||||
{
|
|
||||||
return id.print(stream, -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
// Forwarding class to specialise for metric types
|
|
||||||
template<typename Type>
|
|
||||||
struct RecordMax {
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct RecordMax<double> {
|
|
||||||
static constexpr double min() { return std::numeric_limits< double >::infinity(); }
|
|
||||||
static constexpr double max() { return -std::numeric_limits< double >::infinity(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct RecordMax<int> {
|
|
||||||
static constexpr int min() { return std::numeric_limits< int >::max(); }
|
|
||||||
static constexpr int max() { return std::numeric_limits< int >::min(); }
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
class Record
|
|
||||||
{
|
|
||||||
size_t m_count{0};
|
|
||||||
Type m_total;
|
|
||||||
Type m_min;
|
|
||||||
Type m_max;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// clang-format off
|
|
||||||
static constexpr Type DEFAULT_MIN() { return RecordMax<Type>::min(); };
|
|
||||||
static constexpr Type DEFAULT_MAX() { return RecordMax<Type>::max(); };
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
Record() : m_total(0.0), m_min(DEFAULT_MIN()), m_max(DEFAULT_MAX())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Record(size_t count, double total, double min, double max)
|
|
||||||
: m_count(count), m_total(total), m_min(min), m_max(max)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
size_t count() const { return m_count; }
|
|
||||||
size_t& count() { return m_count; }
|
|
||||||
|
|
||||||
Type total() const { return m_total; }
|
|
||||||
Type& total() { return m_total; }
|
|
||||||
|
|
||||||
Type min() const { return m_min; }
|
|
||||||
Type& min() { return m_min; }
|
|
||||||
|
|
||||||
Type max() const { return m_max; }
|
|
||||||
Type& max() { return m_max; }
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
void
|
|
||||||
clear()
|
|
||||||
{
|
|
||||||
m_count = 0;
|
|
||||||
m_total = 0;
|
|
||||||
m_min = DEFAULT_MIN();
|
|
||||||
m_max = DEFAULT_MAX();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
print(std::ostream &stream, int level, int spaces) const
|
|
||||||
{
|
|
||||||
Printer printer(stream, level, spaces);
|
|
||||||
printer.printAttribute("count", m_count);
|
|
||||||
printer.printAttribute("total", m_total);
|
|
||||||
printer.printAttribute("min", m_min);
|
|
||||||
printer.printAttribute("max", m_max);
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
inline std::ostream &
|
|
||||||
operator<<(std::ostream &stream, const Record< Type > &rec)
|
|
||||||
{
|
|
||||||
return rec.print(stream, -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
inline bool
|
|
||||||
operator==(const Record< Type > &lhs, const Record< Type > &rhs)
|
|
||||||
{
|
|
||||||
return std::make_tuple(lhs.count(), lhs.total(), lhs.min(), lhs.max())
|
|
||||||
== std::make_tuple(rhs.count(), rhs.total(), rhs.min(), rhs.max());
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
inline bool
|
|
||||||
operator!=(const Record< Type > &lhs, const Record< Type > &rhs)
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
using Tag = std::string;
|
|
||||||
using TagValue = absl::variant< std::string, double, std::int64_t >;
|
|
||||||
using Tags = std::set< std::pair< Tag, TagValue > >;
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
using TaggedRecordsData = absl::flat_hash_map< Tags, Record< Type > >;
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
struct TaggedRecords
|
|
||||||
{
|
|
||||||
Id id;
|
|
||||||
TaggedRecordsData< Type > data;
|
|
||||||
|
|
||||||
explicit TaggedRecords(const Id &_id) : id(_id)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TaggedRecords(const Id &_id, const TaggedRecordsData< Type > &_data)
|
|
||||||
: id(_id), data(_data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
print(std::ostream &stream, int level, int spaces) const
|
|
||||||
{
|
|
||||||
Printer printer(stream, level, spaces);
|
|
||||||
printer.printAttribute("id", id);
|
|
||||||
printer.printAttribute("data", data);
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
bool
|
|
||||||
operator==(const TaggedRecords< Value > &lhs,
|
|
||||||
const TaggedRecords< Value > &rhs)
|
|
||||||
{
|
|
||||||
return std::tie(lhs.id, lhs.data) == std::tie(rhs.id, rhs.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Value >
|
|
||||||
std::ostream &
|
|
||||||
operator<<(std::ostream &stream, const TaggedRecords< Value > &rec)
|
|
||||||
{
|
|
||||||
return rec.print(stream, -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
class SampleGroup
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using RecordType = TaggedRecords< Type >;
|
|
||||||
using const_iterator =
|
|
||||||
typename absl::Span< const RecordType >::const_iterator;
|
|
||||||
|
|
||||||
private:
|
|
||||||
absl::Span< const RecordType > m_records;
|
|
||||||
absl::Duration m_samplePeriod;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SampleGroup() : m_records(), m_samplePeriod()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SampleGroup(const RecordType *records, size_t size,
|
|
||||||
absl::Duration samplePeriod)
|
|
||||||
: m_records(records, size), m_samplePeriod(samplePeriod)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SampleGroup(const absl::Span< const RecordType > &records,
|
|
||||||
absl::Duration samplePeriod)
|
|
||||||
: m_records(records), m_samplePeriod(samplePeriod)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
void samplePeriod(absl::Duration duration) { m_samplePeriod = duration; }
|
|
||||||
absl::Duration samplePeriod() const { return m_samplePeriod; }
|
|
||||||
|
|
||||||
void records(absl::Span<const RecordType> recs) { m_records = recs; }
|
|
||||||
absl::Span<const RecordType> records() const { return m_records; }
|
|
||||||
|
|
||||||
bool empty() const { return m_records.empty(); }
|
|
||||||
size_t size() const { return m_records.size(); }
|
|
||||||
|
|
||||||
const_iterator begin() const { return m_records.begin(); }
|
|
||||||
const_iterator end() const { return m_records.end(); }
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
print(std::ostream &stream, int level, int spaces) const
|
|
||||||
{
|
|
||||||
Printer::PrintFunction< absl::Duration > durationPrinter =
|
|
||||||
[](std::ostream &os, const absl::Duration &duration, int,
|
|
||||||
int) -> std::ostream & {
|
|
||||||
os << duration;
|
|
||||||
return os;
|
|
||||||
};
|
|
||||||
Printer printer(stream, level, spaces);
|
|
||||||
printer.printAttribute("records", m_records);
|
|
||||||
printer.printForeignAttribute("samplePeriod", m_samplePeriod,
|
|
||||||
durationPrinter);
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
inline std::ostream &
|
|
||||||
operator<<(std::ostream &stream, const SampleGroup< Type > &group)
|
|
||||||
{
|
|
||||||
return group.print(stream, -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
|
||||||
inline bool
|
|
||||||
operator==(const SampleGroup< Type > &lhs, const SampleGroup< Type > &rhs)
|
|
||||||
{
|
|
||||||
return lhs.records() == rhs.records()
|
|
||||||
&& lhs.samplePeriod() == rhs.samplePeriod();
|
|
||||||
}
|
|
||||||
|
|
||||||
class Sample
|
|
||||||
{
|
|
||||||
absl::Time m_sampleTime;
|
|
||||||
std::vector< absl::variant< SampleGroup< double >, SampleGroup< int > > >
|
|
||||||
m_samples;
|
|
||||||
size_t m_recordCount{0};
|
|
||||||
|
|
||||||
public:
|
|
||||||
using const_iterator = typename decltype(m_samples)::const_iterator;
|
|
||||||
|
|
||||||
Sample() : m_sampleTime()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
void sampleTime(const absl::Time& time) { m_sampleTime = time; }
|
|
||||||
absl::Time sampleTime() const { return m_sampleTime; }
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
void pushGroup(const SampleGroup<Type>& group) {
|
|
||||||
if (!group.empty()) {
|
|
||||||
m_samples.emplace_back(group);
|
|
||||||
m_recordCount += group.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
void pushGroup(const TaggedRecords< Type > *records, size_t size, absl::Duration duration) {
|
|
||||||
if (size != 0) {
|
|
||||||
m_samples.emplace_back(SampleGroup<Type>(records, size, duration));
|
|
||||||
m_recordCount += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
void pushGroup(const absl::Span< const TaggedRecords< Type > > &records,absl::Duration duration) {
|
|
||||||
if (!records.empty()) {
|
|
||||||
m_samples.emplace_back(SampleGroup<Type>(records, duration));
|
|
||||||
m_recordCount += records.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
m_samples.clear();
|
|
||||||
m_recordCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const absl::variant<SampleGroup<double>, SampleGroup<int> >& group(size_t index) {
|
|
||||||
assert(index < m_samples.size());
|
|
||||||
return m_samples[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator begin() const { return m_samples.begin(); }
|
|
||||||
const_iterator end() const { return m_samples.end(); }
|
|
||||||
|
|
||||||
size_t groupCount() const { return m_samples.size(); }
|
|
||||||
size_t recordCount() const { return m_recordCount; }
|
|
||||||
// clang-format on
|
|
||||||
};
|
|
||||||
|
|
||||||
inline absl::Duration
|
|
||||||
samplePeriod(
|
|
||||||
const absl::variant< SampleGroup< double >, SampleGroup< int > > &group)
|
|
||||||
{
|
|
||||||
return absl::visit([](const auto &x) { return x.samplePeriod(); }, group);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t
|
|
||||||
sampleSize(
|
|
||||||
const absl::variant< SampleGroup< double >, SampleGroup< int > > &group)
|
|
||||||
{
|
|
||||||
return absl::visit([](const auto &x) { return x.size(); }, group);
|
|
||||||
}
|
|
||||||
} // namespace metrics
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -3,9 +3,7 @@
|
||||||
|
|
||||||
#include <util/string_view.hpp>
|
#include <util/string_view.hpp>
|
||||||
#include <util/meta/traits.hpp>
|
#include <util/meta/traits.hpp>
|
||||||
#include <util/meta/variant.hpp>
|
|
||||||
|
|
||||||
#include <absl/types/variant.h>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -197,11 +195,6 @@ namespace llarp
|
||||||
printType(std::ostream& stream, const std::tuple< Types... >& value,
|
printType(std::ostream& stream, const std::tuple< Types... >& value,
|
||||||
int level, int spaces, traits::select::Case<>);
|
int level, int spaces, traits::select::Case<>);
|
||||||
|
|
||||||
template < typename... Types >
|
|
||||||
static void
|
|
||||||
printType(std::ostream& stream, const absl::variant< Types... >& value,
|
|
||||||
int level, int spaces, traits::select::Case<>);
|
|
||||||
|
|
||||||
// Default type
|
// Default type
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
static void
|
static void
|
||||||
|
@ -493,17 +486,6 @@ namespace llarp
|
||||||
[&](const auto& x) { print.printValue(x); });
|
[&](const auto& x) { print.printValue(x); });
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename... Types >
|
|
||||||
inline void
|
|
||||||
PrintHelper::printType(std::ostream& stream,
|
|
||||||
const absl::variant< Types... >& value, int level,
|
|
||||||
int spaces, traits::select::Case<>)
|
|
||||||
{
|
|
||||||
Printer print(stream, level, spaces);
|
|
||||||
|
|
||||||
absl::visit([&](const auto& x) { print.printValue(x); }, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
inline void
|
inline void
|
||||||
PrintHelper::printType(std::ostream& stream, const Type& value, int level,
|
PrintHelper::printType(std::ostream& stream, const Type& value, int level,
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/status.hpp>
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <absl/types/variant.h>
|
|
||||||
|
|
||||||
namespace llarp
|
namespace llarp
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/stopwatch.hpp>
|
|
|
@ -1,53 +0,0 @@
|
||||||
#ifndef LLARP_STOPWATCH_HPP
|
|
||||||
#define LLARP_STOPWATCH_HPP
|
|
||||||
|
|
||||||
#include <nonstd/optional.hpp>
|
|
||||||
#include <absl/time/clock.h>
|
|
||||||
|
|
||||||
namespace llarp
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
class Stopwatch
|
|
||||||
{
|
|
||||||
nonstd::optional< absl::Time > m_start;
|
|
||||||
nonstd::optional< absl::Time > m_stop;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Stopwatch() = default;
|
|
||||||
|
|
||||||
void
|
|
||||||
start()
|
|
||||||
{
|
|
||||||
assert(!m_start);
|
|
||||||
assert(!m_stop);
|
|
||||||
m_start.emplace(absl::Now());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
stop()
|
|
||||||
{
|
|
||||||
assert(m_start);
|
|
||||||
assert(!m_stop);
|
|
||||||
m_stop.emplace(absl::Now());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
done() const
|
|
||||||
{
|
|
||||||
return m_start && m_stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Duration
|
|
||||||
time() const
|
|
||||||
{
|
|
||||||
assert(m_start);
|
|
||||||
assert(m_stop);
|
|
||||||
return m_stop.value() - m_start.value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
} // namespace llarp
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
#include <util/string_view.hpp>
|
|
61
llarp/util/thread/annotations.hpp
Normal file
61
llarp/util/thread/annotations.hpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Clang thread safety analysis macros. Does nothing under non-clang compilers.
|
||||||
|
|
||||||
|
// Enable thread safety attributes only with clang.
|
||||||
|
// The attributes can be safely erased when compiling with other compilers.
|
||||||
|
#if defined(__clang__) && (!defined(SWIG))
|
||||||
|
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||||
|
#else
|
||||||
|
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
||||||
|
|
||||||
|
#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||||
|
|
||||||
|
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
||||||
|
|
||||||
|
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
||||||
|
|
||||||
|
#define ACQUIRED_BEFORE(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define ACQUIRED_AFTER(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define REQUIRES(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define REQUIRES_SHARED(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define ACQUIRE(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define ACQUIRE_SHARED(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define RELEASE(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define RELEASE_SHARED(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define TRY_ACQUIRE(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define TRY_ACQUIRE_SHARED(...) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
|
||||||
|
|
||||||
|
#define ASSERT_SHARED_CAPABILITY(x) \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
|
||||||
|
|
||||||
|
#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||||
|
|
||||||
|
#define NO_THREAD_SAFETY_ANALYSIS \
|
||||||
|
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
46
llarp/util/thread/barrier.hpp
Normal file
46
llarp/util/thread/barrier.hpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
namespace llarp
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
/// Barrier class that blocks all threads until the high water mark of
|
||||||
|
/// threads (set during construction) is reached, then releases them all.
|
||||||
|
class Barrier
|
||||||
|
{
|
||||||
|
std::mutex mutex;
|
||||||
|
std::condition_variable cv;
|
||||||
|
unsigned pending;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Barrier(unsigned threads) : pending{threads}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if *this* Block call is the one that releases all of
|
||||||
|
/// them; returns false (i.e. after unblocking) if some other thread
|
||||||
|
/// triggered the released.
|
||||||
|
bool
|
||||||
|
Block()
|
||||||
|
{
|
||||||
|
std::unique_lock< std::mutex > lock{mutex};
|
||||||
|
if(pending == 1)
|
||||||
|
{
|
||||||
|
pending = 0;
|
||||||
|
lock.unlock();
|
||||||
|
cv.notify_all();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(pending > 1)
|
||||||
|
{
|
||||||
|
pending--;
|
||||||
|
}
|
||||||
|
cv.wait(lock, [this] { return !pending; });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
|
} // namespace llarp
|
|
@ -1,7 +1,6 @@
|
||||||
#include <util/thread/logic.hpp>
|
#include <util/thread/logic.hpp>
|
||||||
#include <util/logging/logger.hpp>
|
#include <util/logging/logger.hpp>
|
||||||
#include <util/mem.h>
|
#include <util/mem.h>
|
||||||
#include <util/metrics/metrics.hpp>
|
|
||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
|
@ -53,28 +52,10 @@ namespace llarp
|
||||||
Logic::_traceLogicCall(std::function< void(void) > func, const char* tag,
|
Logic::_traceLogicCall(std::function< void(void) > func, const char* tag,
|
||||||
int line)
|
int line)
|
||||||
{
|
{
|
||||||
#define TAG (tag ? tag : LOG_TAG)
|
|
||||||
#define LINE (line ? line : __LINE__)
|
|
||||||
// wrap the function so that we ensure that it's always calling stuff one at
|
// wrap the function so that we ensure that it's always calling stuff one at
|
||||||
// a time
|
// a time
|
||||||
|
|
||||||
#if defined(LOKINET_DEBUG)
|
auto f = [self = this, func]() {
|
||||||
#define METRIC(action) \
|
|
||||||
metrics::integerTick("logic", action, 1, "tag", TAG, "line", \
|
|
||||||
std::to_string(LINE))
|
|
||||||
#else
|
|
||||||
#define METRIC(action) \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
} while(false)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
METRIC("queue");
|
|
||||||
auto f = [self = this, func, tag, line]() {
|
|
||||||
#if defined(LOKINET_DEBUG)
|
|
||||||
metrics::TimerGuard g("logic",
|
|
||||||
std::string(TAG) + ":" + std::to_string(LINE));
|
|
||||||
#endif
|
|
||||||
if(self->m_Queue)
|
if(self->m_Queue)
|
||||||
{
|
{
|
||||||
func();
|
func();
|
||||||
|
@ -86,7 +67,6 @@ namespace llarp
|
||||||
};
|
};
|
||||||
if(can_flush())
|
if(can_flush())
|
||||||
{
|
{
|
||||||
METRIC("fired");
|
|
||||||
f();
|
f();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -97,21 +77,16 @@ namespace llarp
|
||||||
}
|
}
|
||||||
if(m_Thread->LooksFull(5))
|
if(m_Thread->LooksFull(5))
|
||||||
{
|
{
|
||||||
LogErrorExplicit(TAG, LINE,
|
LogErrorExplicit(tag ? tag : LOG_TAG, line ? line : __LINE__,
|
||||||
"holy crap, we are trying to queue a job "
|
"holy crap, we are trying to queue a job "
|
||||||
"onto the logic thread but it looks full");
|
"onto the logic thread but it looks full");
|
||||||
METRIC("full");
|
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
auto ret = llarp_threadpool_queue_job(m_Thread, f);
|
auto ret = llarp_threadpool_queue_job(m_Thread, f);
|
||||||
if(not ret)
|
if(not ret)
|
||||||
{
|
{
|
||||||
METRIC("dropped");
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
#undef TAG
|
|
||||||
#undef LINE
|
|
||||||
#undef METRIC
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue