Skip to content
Snippets Groups Projects
Commit 73655917 authored by Adrien Béraud's avatar Adrien Béraud Committed by Andreas Traczyk
Browse files

namedirectory: make thread-safe


Change-Id: Icce9d2e5a126421e853463a05538d4e75184ab75
Reviewed-by: default avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent d489efd5
No related branches found
No related tags found
No related merge requests found
...@@ -37,6 +37,7 @@ namespace ring { ...@@ -37,6 +37,7 @@ namespace ring {
constexpr const char* const QUERY_NAME {"/name/"}; constexpr const char* const QUERY_NAME {"/name/"};
constexpr const char* const QUERY_ADDR {"/addr/"}; constexpr const char* const QUERY_ADDR {"/addr/"};
constexpr const char* const HTTPS_PROTO {"https://"}; constexpr const char* const HTTPS_PROTO {"https://"};
constexpr const char* const CACHE_DIRECTORY {"namecache"};
/** Parser for Ring URIs. ( protocol ) ( username ) ( hostname ) */ /** Parser for Ring URIs. ( protocol ) ( username ) ( hostname ) */
const std::regex URI_VALIDATOR {"^([a-zA-Z]+:(?://)?)?(?:([a-z0-9-_]{1,64})@)?([a-zA-Z0-9\\-._~%!$&'()*+,;=:\\[\\]]+)"}; const std::regex URI_VALIDATOR {"^([a-zA-Z]+:(?://)?)?(?:([a-z0-9-_]{1,64})@)?([a-zA-Z0-9\\-._~%!$&'()*+,;=:\\[\\]]+)"};
...@@ -68,7 +69,7 @@ NameDirectory::lookupUri(const std::string& uri, const std::string& default_serv ...@@ -68,7 +69,7 @@ NameDirectory::lookupUri(const std::string& uri, const std::string& default_serv
NameDirectory::NameDirectory(const std::string& s) NameDirectory::NameDirectory(const std::string& s)
: serverHost_(s), : serverHost_(s),
cachePath_(fileutils::get_cache_dir()+DIR_SEPARATOR_STR+"namecache"+DIR_SEPARATOR_STR+serverHost_) cachePath_(fileutils::get_cache_dir()+DIR_SEPARATOR_STR+CACHE_DIRECTORY+DIR_SEPARATOR_STR+serverHost_)
{} {}
void void
...@@ -81,7 +82,9 @@ NameDirectory& NameDirectory::instance(const std::string& server) ...@@ -81,7 +82,9 @@ NameDirectory& NameDirectory::instance(const std::string& server)
{ {
const std::string& s = server.empty() ? DEFAULT_SERVER_HOST : server; const std::string& s = server.empty() ? DEFAULT_SERVER_HOST : server;
static std::map<std::string, NameDirectory> instances {}; static std::map<std::string, NameDirectory> instances {};
auto r = instances.emplace(s, NameDirectory{s}); auto r = instances.emplace(std::piecewise_construct,
std::forward_as_tuple(s),
std::forward_as_tuple(s));
if (r.second) if (r.second)
r.first->second.load(); r.first->second.load();
return r.first->second; return r.first->second;
...@@ -137,8 +140,11 @@ void NameDirectory::lookupAddress(const std::string& addr, LookupCallback cb) ...@@ -137,8 +140,11 @@ void NameDirectory::lookupAddress(const std::string& addr, LookupCallback cb)
auto name = json["name"].asString(); auto name = json["name"].asString();
if (not name.empty()) { if (not name.empty()) {
RING_DBG("Found name for %s: %s", addr.c_str(), name.c_str()); RING_DBG("Found name for %s: %s", addr.c_str(), name.c_str());
{
std::lock_guard<std::mutex> l(lock_);
addrCache_.emplace(name, addr); addrCache_.emplace(name, addr);
nameCache_.emplace(addr, name); nameCache_.emplace(addr, name);
}
cb(name, Response::found); cb(name, Response::found);
saveCache(); saveCache();
} else { } else {
...@@ -212,8 +218,11 @@ void NameDirectory::lookupName(const std::string& n, LookupCallback cb) ...@@ -212,8 +218,11 @@ void NameDirectory::lookupName(const std::string& n, LookupCallback cb)
addr = addr.substr(HEX_PREFIX.size()); addr = addr.substr(HEX_PREFIX.size());
if (not addr.empty()) { if (not addr.empty()) {
RING_DBG("Found address for %s: %s", name.c_str(), addr.c_str()); RING_DBG("Found address for %s: %s", name.c_str(), addr.c_str());
{
std::lock_guard<std::mutex> l(lock_);
addrCache_.emplace(name, addr); addrCache_.emplace(name, addr);
nameCache_.emplace(addr, name); nameCache_.emplace(addr, name);
}
cb(addr, Response::found); cb(addr, Response::found);
saveCache(); saveCache();
} else { } else {
...@@ -302,6 +311,7 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n, ...@@ -302,6 +311,7 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n,
auto success = json["success"].asBool(); auto success = json["success"].asBool();
RING_DBG("Got reply for registration of %s -> %s: %s", name.c_str(), addr.c_str(), success ? "success" : "failure"); RING_DBG("Got reply for registration of %s -> %s: %s", name.c_str(), addr.c_str(), success ? "success" : "failure");
if (success) { if (success) {
std::lock_guard<std::mutex> l(lock_);
addrCache_.emplace(name, addr); addrCache_.emplace(name, addr);
nameCache_.emplace(addr, name); nameCache_.emplace(addr, name);
} }
...@@ -324,9 +334,13 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n, ...@@ -324,9 +334,13 @@ void NameDirectory::registerName(const std::string& addr, const std::string& n,
void void
NameDirectory::saveCache() NameDirectory::saveCache()
{ {
fileutils::recursive_mkdir(fileutils::get_cache_dir()+DIR_SEPARATOR_STR+"namecache"); fileutils::recursive_mkdir(fileutils::get_cache_dir()+DIR_SEPARATOR_STR+CACHE_DIRECTORY);
std::lock_guard<std::mutex> lock(fileutils::getFileLock(cachePath_));
std::ofstream file(cachePath_, std::ios::trunc | std::ios::binary); std::ofstream file(cachePath_, std::ios::trunc | std::ios::binary);
{
std::lock_guard<std::mutex> l(lock_);
msgpack::pack(file, nameCache_); msgpack::pack(file, nameCache_);
}
RING_DBG("Saved %lu name-address mappings", (long unsigned)nameCache_.size()); RING_DBG("Saved %lu name-address mappings", (long unsigned)nameCache_.size());
} }
...@@ -337,6 +351,7 @@ NameDirectory::loadCache() ...@@ -337,6 +351,7 @@ NameDirectory::loadCache()
// read file // read file
{ {
std::lock_guard<std::mutex> lock(fileutils::getFileLock(cachePath_));
std::ifstream file(cachePath_); std::ifstream file(cachePath_);
if (!file.is_open()) { if (!file.is_open()) {
RING_DBG("Could not load %s", cachePath_.c_str()); RING_DBG("Could not load %s", cachePath_.c_str());
...@@ -351,6 +366,7 @@ NameDirectory::loadCache() ...@@ -351,6 +366,7 @@ NameDirectory::loadCache()
} }
// load values // load values
std::lock_guard<std::mutex> l(lock_);
msgpack::object_handle oh; msgpack::object_handle oh;
if (pac.next(oh)) if (pac.next(oh))
oh.get().convert(nameCache_); oh.get().convert(nameCache_);
......
...@@ -17,9 +17,12 @@ ...@@ -17,9 +17,12 @@
*/ */
#pragma once #pragma once
#include "noncopyable.h"
#include <functional> #include <functional>
#include <map> #include <map>
#include <string> #include <string>
#include <mutex>
namespace ring { namespace ring {
...@@ -51,14 +54,16 @@ public: ...@@ -51,14 +54,16 @@ public:
} }
private: private:
NON_COPYABLE(NameDirectory);
NameDirectory(NameDirectory&&) = delete;
constexpr static const char* const DEFAULT_SERVER_HOST = "ns.ring.cx"; constexpr static const char* const DEFAULT_SERVER_HOST = "ns.ring.cx";
const std::string serverHost_ {DEFAULT_SERVER_HOST}; const std::string serverHost_ {DEFAULT_SERVER_HOST};
const std::string cachePath_; const std::string cachePath_;
std::map<std::string, std::string> nameCache_; std::map<std::string, std::string> nameCache_ {};
std::map<std::string, std::string> addrCache_; std::map<std::string, std::string> addrCache_ {};
std::mutex lock_ {};
bool validateName(const std::string& name) const; bool validateName(const std::string& name) const;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment