mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 12:28:42 +00:00
Compare commits
5
Commits
ssl
...
persist_state
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6046e0a561 | ||
|
|
244b16b978 | ||
|
|
778b389abd | ||
|
|
92a341d8a0 | ||
|
|
ecb441f31e |
No files matched your search
@@ -103,6 +103,9 @@ struct OPENDHT_PUBLIC Config {
|
||||
|
||||
/** Makes the DHT responsible to maintain its stored values. Consumes more ressources. */
|
||||
bool maintain_storage;
|
||||
|
||||
/** If set, the dht will load its state from this file on start and save its state in this file on shutdown */
|
||||
std::string persist_path;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -186,7 +186,7 @@ class OPENDHT_PUBLIC RevocationList
|
||||
public:
|
||||
RevocationList();
|
||||
RevocationList(const Blob& b);
|
||||
RevocationList(RevocationList&& o) : crl(o.crl) { o.crl = nullptr; }
|
||||
RevocationList(RevocationList&& o) noexcept : crl(o.crl) { o.crl = nullptr; }
|
||||
~RevocationList();
|
||||
|
||||
RevocationList& operator=(RevocationList&& o) { crl = o.crl; o.crl = nullptr; return *this; }
|
||||
@@ -500,7 +500,7 @@ struct OPENDHT_PUBLIC TrustList
|
||||
};
|
||||
|
||||
TrustList();
|
||||
TrustList(TrustList&& o) : trust(std::move(o.trust)) {
|
||||
TrustList(TrustList&& o) noexcept : trust(std::move(o.trust)) {
|
||||
o.trust = nullptr;
|
||||
}
|
||||
TrustList& operator=(TrustList&& o);
|
||||
|
||||
+13
-8
@@ -261,11 +261,14 @@ public:
|
||||
* Get the list of good nodes for local storage saving purposes
|
||||
* The list is ordered to minimize the back-to-work delay.
|
||||
*/
|
||||
std::vector<NodeExport> exportNodes();
|
||||
std::vector<NodeExport> exportNodes() const;
|
||||
|
||||
std::vector<ValuesExport> exportValues() const;
|
||||
void importValues(const std::vector<ValuesExport>&);
|
||||
|
||||
void saveState(const std::string& path) const;
|
||||
void loadState(const std::string& path);
|
||||
|
||||
NodeStats getNodesStats(sa_family_t af) const;
|
||||
|
||||
std::string getStorageLog() const;
|
||||
@@ -359,13 +362,6 @@ private:
|
||||
// registred types
|
||||
TypeStore types;
|
||||
|
||||
// are we a bootstrap node ?
|
||||
// note: Any running node can be used as a bootstrap node.
|
||||
// Only nodes running only as bootstrap nodes should
|
||||
// be put in bootstrap mode.
|
||||
const bool is_bootstrap {false};
|
||||
const bool maintain_storage {false};
|
||||
|
||||
// the stuff
|
||||
RoutingTable buckets4 {};
|
||||
RoutingTable buckets6 {};
|
||||
@@ -400,6 +396,15 @@ private:
|
||||
|
||||
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
|
||||
|
||||
std::string persistPath;
|
||||
|
||||
// are we a bootstrap node ?
|
||||
// note: Any running node can be used as a bootstrap node.
|
||||
// Only nodes running only as bootstrap nodes should
|
||||
// be put in bootstrap mode.
|
||||
const bool is_bootstrap {false};
|
||||
const bool maintain_storage {false};
|
||||
|
||||
void rotateSecrets();
|
||||
|
||||
Blob makeToken(const SockAddr&, bool old) const;
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
* Get the list of good nodes for local storage saving purposes
|
||||
* The list is ordered to minimize the back-to-work delay.
|
||||
*/
|
||||
virtual std::vector<NodeExport> exportNodes() = 0;
|
||||
virtual std::vector<NodeExport> exportNodes() const = 0;
|
||||
|
||||
virtual std::vector<ValuesExport> exportValues() const = 0;
|
||||
virtual void importValues(const std::vector<ValuesExport>&) = 0;
|
||||
|
||||
@@ -235,7 +235,7 @@ public:
|
||||
void insertNode(const InfoHash&, const sockaddr*, socklen_t) { }
|
||||
void insertNode(const NodeExport&) { }
|
||||
std::pair<size_t, size_t> getStoreSize() const { return {}; }
|
||||
std::vector<NodeExport> exportNodes() { return {}; }
|
||||
std::vector<NodeExport> exportNodes() const { return {}; }
|
||||
std::vector<ValuesExport> exportValues() const { return {}; }
|
||||
void importValues(const std::vector<ValuesExport>&) {}
|
||||
std::string getStorageLog() const { return {}; }
|
||||
|
||||
@@ -354,7 +354,8 @@ public:
|
||||
/*.node_id = */{},
|
||||
/*.network = */network,
|
||||
/*.is_bootstrap = */false,
|
||||
/*.maintain_storage*/false
|
||||
/*.maintain_storage = */false,
|
||||
/*.persist_path = */{}
|
||||
},
|
||||
/*.id = */identity
|
||||
},
|
||||
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
|
||||
dht_->setStorageLimit(limit);
|
||||
}
|
||||
std::vector<NodeExport> exportNodes() override {
|
||||
std::vector<NodeExport> exportNodes() const override {
|
||||
return dht_->exportNodes();
|
||||
}
|
||||
std::vector<ValuesExport> exportValues() const override {
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
SockAddr(const SockAddr& o) {
|
||||
set(o.get(), o.getLength());
|
||||
}
|
||||
SockAddr(SockAddr&& o) : len(o.len), addr(std::move(o.addr)) {
|
||||
SockAddr(SockAddr&& o) noexcept : len(o.len), addr(std::move(o.addr)) {
|
||||
o.len = 0;
|
||||
}
|
||||
|
||||
|
||||
+62
-7
@@ -29,6 +29,7 @@
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
namespace dht {
|
||||
|
||||
@@ -54,6 +55,9 @@ Dht::getStatus(sa_family_t af) const
|
||||
void
|
||||
Dht::shutdown(ShutdownCallback cb)
|
||||
{
|
||||
if (not persistPath.empty())
|
||||
saveState(persistPath);
|
||||
|
||||
if (not maintain_storage) {
|
||||
if (cb) cb();
|
||||
return;
|
||||
@@ -1722,9 +1726,7 @@ Dht::~Dht()
|
||||
Dht::Dht() : store(), network_engine(DHT_LOG, scheduler) {}
|
||||
|
||||
Dht::Dht(const int& s, const int& s6, Config config)
|
||||
: myid(config.node_id ? config.node_id : InfoHash::getRandom()),
|
||||
is_bootstrap(config.is_bootstrap),
|
||||
maintain_storage(config.maintain_storage), store(), store_quota(),
|
||||
: myid(config.node_id ? config.node_id : InfoHash::getRandom()), store(), store_quota(),
|
||||
network_engine(myid, config.network, s, s6, DHT_LOG, scheduler,
|
||||
std::bind(&Dht::onError, this, _1, _2),
|
||||
std::bind(&Dht::onNewNode, this, _1, _2),
|
||||
@@ -1734,7 +1736,10 @@ Dht::Dht(const int& s, const int& s6, Config config)
|
||||
std::bind(&Dht::onGetValues, this, _1, _2, _3, _4),
|
||||
std::bind(&Dht::onListen, this, _1, _2, _3, _4, _5),
|
||||
std::bind(&Dht::onAnnounce, this, _1, _2, _3, _4, _5),
|
||||
std::bind(&Dht::onRefresh, this, _1, _2, _3, _4))
|
||||
std::bind(&Dht::onRefresh, this, _1, _2, _3, _4)),
|
||||
persistPath(config.persist_path),
|
||||
is_bootstrap(config.is_bootstrap),
|
||||
maintain_storage(config.maintain_storage)
|
||||
{
|
||||
scheduler.syncTime();
|
||||
if (s < 0 && s6 < 0)
|
||||
@@ -1765,8 +1770,10 @@ Dht::Dht(const int& s, const int& s6, Config config)
|
||||
expire();
|
||||
|
||||
DHT_LOG.d("DHT initialised with node ID %s", myid.toString().c_str());
|
||||
}
|
||||
|
||||
if (not persistPath.empty())
|
||||
loadState(persistPath);
|
||||
}
|
||||
|
||||
bool
|
||||
Dht::neighbourhoodMaintenance(RoutingTable& list)
|
||||
@@ -2056,7 +2063,7 @@ Dht::importValues(const std::vector<ValuesExport>& import)
|
||||
|
||||
|
||||
std::vector<NodeExport>
|
||||
Dht::exportNodes()
|
||||
Dht::exportNodes() const
|
||||
{
|
||||
const auto& now = scheduler.time();
|
||||
std::vector<NodeExport> nodes;
|
||||
@@ -2283,7 +2290,7 @@ Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t soc
|
||||
}
|
||||
|
||||
void
|
||||
Dht::onListenDone(const Sp<Node>& node, net::RequestAnswer& answer, Sp<Search>& sr)
|
||||
Dht::onListenDone(const Sp<Node>& /* node */, net::RequestAnswer& /* answer */, Sp<Search>& sr)
|
||||
{
|
||||
// DHT_LOG.d(sr->id, node->id, "[search %s] [node %s] got listen confirmation",
|
||||
// sr->id.toString().c_str(), node->toString().c_str(), answer.values.size());
|
||||
@@ -2424,4 +2431,52 @@ Dht::onAnnounceDone(const Sp<Node>& node, net::RequestAnswer& answer, Sp<Search>
|
||||
sr->checkAnnounced(answer.vid);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Dht::saveState(const std::string& path) const
|
||||
{
|
||||
std::ofstream file(path);
|
||||
msgpack::pack(file, exportNodes());
|
||||
msgpack::pack(file, exportValues());
|
||||
}
|
||||
|
||||
void
|
||||
Dht::loadState(const std::string& path)
|
||||
{
|
||||
DHT_LOG.d("Importing state from %s", path.c_str());
|
||||
try {
|
||||
// Import nodes from binary file
|
||||
msgpack::unpacker pac;
|
||||
{
|
||||
// Read whole file
|
||||
std::ifstream file(path, std::ios::binary|std::ios::ate);
|
||||
if (!file.is_open()) {
|
||||
return;
|
||||
}
|
||||
auto size = file.tellg();
|
||||
file.seekg (0, std::ios::beg);
|
||||
pac.reserve_buffer(size);
|
||||
file.read (pac.buffer(), size);
|
||||
pac.buffer_consumed(size);
|
||||
}
|
||||
// Import nodes
|
||||
msgpack::object_handle oh;
|
||||
if (pac.next(oh)) {
|
||||
{
|
||||
auto imported_nodes = oh.get().as<std::vector<NodeExport>>();
|
||||
DHT_LOG.d("Importing %zu nodes", imported_nodes.size());
|
||||
for (const auto& node : imported_nodes)
|
||||
insertNode(node);
|
||||
}
|
||||
if (pac.next(oh)) {
|
||||
auto imported_values = oh.get().as<std::vector<ValuesExport>>();
|
||||
DHT_LOG.d("Importing %zu values", imported_values.size());
|
||||
importValues(imported_values);
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
DHT_LOG.w("Error importing state from %s: %s", path.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -32,8 +32,8 @@ struct OpCacheValueStorage
|
||||
|
||||
class OpValueCache {
|
||||
public:
|
||||
OpValueCache(ValueCallback&& cb) : callback(std::forward<ValueCallback>(cb)) {}
|
||||
OpValueCache(OpValueCache&& o) : values(std::move(o.values)), callback(std::move(o.callback)) {
|
||||
OpValueCache(ValueCallback&& cb) noexcept : callback(std::forward<ValueCallback>(cb)) {}
|
||||
OpValueCache(OpValueCache&& o) noexcept : values(std::move(o.values)), callback(std::move(o.callback)) {
|
||||
o.callback = {};
|
||||
}
|
||||
|
||||
|
||||
@@ -90,20 +90,7 @@ struct Storage {
|
||||
|
||||
Storage() {}
|
||||
Storage(time_point t) : maintenance_time(t) {}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 || defined(_WIN32)
|
||||
// GCC-bug: remove me when support of GCC < 4.9.2 is abandoned
|
||||
Storage(Storage&& o) noexcept
|
||||
: maintenance_time(std::move(o.maintenance_time))
|
||||
, listeners(std::move(o.listeners))
|
||||
, local_listeners(std::move(o.local_listeners))
|
||||
, listener_token(std::move(o.listener_token))
|
||||
, values(std::move(o.values))
|
||||
, total_size(std::move(o.total_size)) {}
|
||||
#else
|
||||
Storage(Storage&& o) noexcept = default;
|
||||
#endif
|
||||
|
||||
Storage& operator=(Storage&& o) = default;
|
||||
|
||||
bool empty() const {
|
||||
|
||||
@@ -26,12 +26,29 @@
|
||||
|
||||
namespace dht {
|
||||
|
||||
constexpr const size_t IO_THREADS_MAX {64};
|
||||
|
||||
struct ThreadPool::ThreadState
|
||||
{
|
||||
std::thread thread {};
|
||||
std::atomic_bool run {true};
|
||||
};
|
||||
|
||||
ThreadPool&
|
||||
ThreadPool::computation()
|
||||
{
|
||||
static ThreadPool pool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
ThreadPool&
|
||||
ThreadPool::io()
|
||||
{
|
||||
static ThreadPool pool(IO_THREADS_MAX);
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
ThreadPool::ThreadPool(size_t maxThreads) : maxThreads_(maxThreads)
|
||||
{
|
||||
threads_.reserve(maxThreads_);
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@ namespace dht {
|
||||
|
||||
class ThreadPool {
|
||||
public:
|
||||
static ThreadPool& instance() {
|
||||
static ThreadPool pool;
|
||||
return pool;
|
||||
}
|
||||
static ThreadPool& computation();
|
||||
static ThreadPool& io();
|
||||
|
||||
ThreadPool();
|
||||
ThreadPool(size_t maxThreads);
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ public:
|
||||
if (syncCallback)
|
||||
syncCallback(ListenSyncStatus::ADDED);
|
||||
}
|
||||
ValueCache(ValueCache&& o) : values(std::move(o.values)), callback(std::move(o.callback)), syncCallback(std::move(o.syncCallback)) {
|
||||
ValueCache(ValueCache&& o) noexcept : values(std::move(o.values)), callback(std::move(o.callback)), syncCallback(std::move(o.syncCallback)) {
|
||||
o.callback = {};
|
||||
o.syncCallback = {};
|
||||
}
|
||||
|
||||
@@ -500,6 +500,7 @@ main(int argc, char **argv)
|
||||
dht::DhtRunner::Config config {};
|
||||
config.dht_config.node_config.network = params.network;
|
||||
config.dht_config.node_config.maintain_storage = false;
|
||||
config.dht_config.node_config.persist_path = params.persist_path;
|
||||
config.dht_config.id = crt;
|
||||
config.threaded = true;
|
||||
config.proxy_server = params.proxyclient;
|
||||
|
||||
@@ -103,6 +103,7 @@ struct dht_params {
|
||||
std::string proxyclient {};
|
||||
std::string pushserver {};
|
||||
std::string devicekey {};
|
||||
std::string persist_path {};
|
||||
};
|
||||
|
||||
static const constexpr struct option long_options[] = {
|
||||
@@ -114,6 +115,7 @@ static const constexpr struct option long_options[] = {
|
||||
{"verbose", no_argument , nullptr, 'v'},
|
||||
{"daemonize", no_argument , nullptr, 'd'},
|
||||
{"service", no_argument , nullptr, 's'},
|
||||
{"persist", required_argument, nullptr, 'f'},
|
||||
{"logfile", required_argument, nullptr, 'l'},
|
||||
{"syslog", no_argument , nullptr, 'L'},
|
||||
{"proxyserver",required_argument, nullptr, 'S'},
|
||||
@@ -127,7 +129,7 @@ dht_params
|
||||
parseArgs(int argc, char **argv) {
|
||||
dht_params params;
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, "hidsvp:n:b:l:", long_options, nullptr)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "hidsvp:n:b:f:l:", long_options, nullptr)) != -1) {
|
||||
switch (opt) {
|
||||
case 'p': {
|
||||
int port_arg = atoi(optarg);
|
||||
@@ -154,6 +156,9 @@ parseArgs(int argc, char **argv) {
|
||||
case 'D':
|
||||
params.devicekey = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
params.persist_path = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
params.network = strtoul(optarg, nullptr, 0);
|
||||
break;
|
||||
|
||||
Reference in new issue
Block a user