From 5b15fdeeefa58204c1e72bc5c9d147fce6352500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= Date: Wed, 15 Jan 2020 13:54:24 -0500 Subject: [PATCH] proxy server: use shared_ptr for stats, remove statsMutex_ --- include/opendht/dht_proxy_server.h | 29 ++++++++++--------- src/dht_proxy_server.cpp | 45 ++++++++++++++++-------------- tools/dhtnode.cpp | 7 +++-- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/include/opendht/dht_proxy_server.h b/include/opendht/dht_proxy_server.h index 25cc8f20..a864eaa3 100644 --- a/include/opendht/dht_proxy_server.h +++ b/include/opendht/dht_proxy_server.h @@ -90,20 +90,19 @@ public: /** Average requests per second */ double requestRate {0}; /** Node Info **/ - NodeInfo nodeInfo {}; + std::shared_ptr nodeInfo {}; std::string toString() const { std::ostringstream ss; ss << "Listens: " << listenCount << " Puts: " << putCount << " PushListeners: " << pushListenersCount << std::endl; ss << "Requests: " << requestRate << " per second." << std::endl; - auto& ni = nodeInfo; - auto& ipv4 = ni.ipv4; - if (ipv4.table_depth > 1) { - ss << "IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;; - } - auto& ipv6 = ni.ipv6; - if (ipv6.table_depth > 1) { - ss << "IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;; + if (nodeInfo) { + auto& ipv4 = nodeInfo->ipv4; + if (ipv4.table_depth > 1) + ss << "IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;; + auto& ipv6 = nodeInfo->ipv6; + if (ipv6.table_depth > 1) + ss << "IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;; } return ss.str(); } @@ -117,14 +116,15 @@ public: result["putCount"] = static_cast(putCount); result["pushListenersCount"] = static_cast(pushListenersCount); result["requestRate"] = requestRate; - result["nodeInfo"] = nodeInfo.toJson(); + if (nodeInfo) + result["nodeInfo"] = nodeInfo->toJson(); return result; } }; - ServerStats stats() const { return stats_; } + std::shared_ptr stats() const { return stats_; } - void updateStats() const; + std::shared_ptr updateStats(std::shared_ptr info) const; std::shared_ptr getNode() const { return dht_; } @@ -327,9 +327,8 @@ private: std::shared_ptr logger_; - mutable std::mutex statsMutex_; - mutable ServerStats stats_; - mutable NodeInfo nodeInfo_ {}; + mutable std::shared_ptr stats_; + mutable std::shared_ptr nodeInfo_ {}; std::unique_ptr printStatsTimer_; // Thread-safe access to listeners map. diff --git a/src/dht_proxy_server.cpp b/src/dht_proxy_server.cpp index 7a41d45b..25b59591 100644 --- a/src/dht_proxy_server.cpp +++ b/src/dht_proxy_server.cpp @@ -36,6 +36,7 @@ #include using namespace std::placeholders; +using namespace std::chrono_literals; #ifdef OPENDHT_PROXY_HTTP_PARSER_FORK namespace restinio { @@ -263,7 +264,7 @@ DhtProxyServer::DhtProxyServer( } dht->forwardAllMessages(true); - printStatsTimer_ = std::make_unique(io_context(), PRINT_STATS_PERIOD); + printStatsTimer_ = std::make_unique(io_context(), 0s); printStatsTimer_->async_wait(std::bind(&DhtProxyServer::handlePrintStats, this, std::placeholders::_1)); } @@ -344,20 +345,23 @@ DhtProxyServer::addServerSettings(ServerSettings& settings, const unsigned int m settings.connection_state_listener(connListener_); } -void -DhtProxyServer::updateStats() const +std::shared_ptr +DhtProxyServer::updateStats(std::shared_ptr info) const { auto now = clock::now(); auto last = lastStatsReset_.exchange(now); auto count = requestNum_.exchange(0); auto dt = std::chrono::duration(now - last); - stats_.requestRate = count / dt.count(); + auto sstats = std::make_shared(); + auto& stats = *sstats; + stats.requestRate = count / dt.count(); #ifdef OPENDHT_PUSH_NOTIFICATIONS - stats_.pushListenersCount = pushListeners_.size(); + stats.pushListenersCount = pushListeners_.size(); #endif - stats_.putCount = puts_.size(); - stats_.listenCount = listeners_.size(); - stats_.nodeInfo = nodeInfo_; + stats.putCount = puts_.size(); + stats.listenCount = listeners_.size(); + stats.nodeInfo = info; + return sstats; } void @@ -372,13 +376,12 @@ DhtProxyServer::handlePrintStats(const asio::error_code &ec) if (io_context().stopped()) return; - if (dht_){ - updateStats(); + if (auto dht = dht_) { // Refresh stats cache - auto newInfo = dht_->getNodeInfo(); - std::lock_guard lck(statsMutex_); - nodeInfo_ = std::move(newInfo); - auto json = nodeInfo_.toJson(); + auto newInfo = std::make_shared(dht->getNodeInfo()); + stats_ = updateStats(newInfo); + nodeInfo_ = newInfo; + auto json = newInfo->toJson(); auto str = Json::writeString(jsonBuilder_, json); if (logger_) logger_->d("[proxy:server] [stats] %s", str.c_str()); @@ -477,12 +480,12 @@ DhtProxyServer::getNodeInfo(restinio::request_handle_t request, restinio::router::route_params_t /*params*/) const { Json::Value result; - std::lock_guard lck(statsMutex_); - if (nodeInfo_.ipv4.good_nodes == 0 && - nodeInfo_.ipv6.good_nodes == 0){ - nodeInfo_ = dht_->getNodeInfo(); + auto nodeInfo = nodeInfo_; + if (not nodeInfo) { + nodeInfo = std::make_shared(dht_->getNodeInfo()); + nodeInfo_ = nodeInfo; } - result = nodeInfo_.toJson(); + result = nodeInfo->toJson(); // [ipv6:ipv4]:port or ipv4:port result["public_ip"] = request->remote_endpoint().address().to_string(); auto output = Json::writeString(jsonBuilder_, result) + "\n"; @@ -498,8 +501,8 @@ DhtProxyServer::getStats(restinio::request_handle_t request, { requestNum_++; try { - if (dht_){ - auto output = Json::writeString(jsonBuilder_, stats_.toJson()) + "\n"; + if (auto stats = stats_) { + auto output = Json::writeString(jsonBuilder_, stats->toJson()) + "\n"; auto response = initHttpResponse(request->create_response()); response.append_body(output); response.done(); diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp index bb4cee6a..76632b9c 100644 --- a/tools/dhtnode.cpp +++ b/tools/dhtnode.cpp @@ -152,8 +152,11 @@ void cmd_loop(std::shared_ptr& node, dht_params& params std::cout << nodeInfo.ipv6.toString() << std::endl; #ifdef OPENDHT_PROXY_SERVER for (const auto& proxy : proxies) { - std::cout << "Stats for proxy on port " << proxy.first << std::endl; - std::cout << " " << proxy.second->stats().toString() << std::endl; + std::cout << "Stats for proxy server on port " << proxy.first << std::endl; + if (auto stats = proxy.second->stats()) + std::cout << " " << stats->toString() << std::endl; + else + std::cout << " (stats not available yet)" << std::endl; } #endif continue;