From 73e4286fbfce8ce017304f693a1190521ad4a8f9 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 3 Jul 2018 12:51:41 -0700 Subject: Fix two controller bugs: filesystem bug and another possible infinite recursion bug. --- controller/FileDB.cpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'controller/FileDB.cpp') diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index a7b59cbf..e78a64c9 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -91,13 +91,15 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record) nlohmann::json old; get(nwid,old); - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json.new",_networksPath.c_str(),nwid); - OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); - if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) - fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); - OSUtils::rename(p1,p2); + if ((!old.is_object())||(old != record)) { + OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json.new",_networksPath.c_str(),nwid); + OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid); + if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) + fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); + OSUtils::rename(p1,p2); - _networkChanged(old,record,true); + _networkChanged(old,record,true); + } } } else if (objtype == "member") { const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL); @@ -106,17 +108,21 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record) nlohmann::json network,old; get(nwid,network,id,old); - OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid); - OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json.new",pb,(unsigned long long)id); - OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); - if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) { - OSUtils::mkdir(pb); - if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) - fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); - } - OSUtils::rename(p1,p2); + if ((!old.is_object())||(old != record)) { + OSUtils::ztsnprintf(pb,sizeof(pb),"%s" ZT_PATH_SEPARATOR_S "%.16llx" ZT_PATH_SEPARATOR_S "member",_networksPath.c_str(),(unsigned long long)nwid); + OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json.new",pb,(unsigned long long)id); + if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) { + OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.16llx",_networksPath.c_str(),(unsigned long long)nwid); + OSUtils::mkdir(p2); + OSUtils::mkdir(pb); + if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) + fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1); + } + OSUtils::ztsnprintf(p2,sizeof(p2),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id); + OSUtils::rename(p1,p2); - _memberChanged(old,record,true); + _memberChanged(old,record,true); + } } } else if (objtype == "trace") { const std::string id = record["id"]; -- cgit v1.2.3 From f94aea8119bdf5b894c4d9a29e678c3c3594b490 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 11 Jul 2018 10:42:31 -0700 Subject: Return error 503 if RethinkDB is down when built as RethinkDB-based controller. --- controller/DB.hpp | 1 + controller/EmbeddedNetworkController.cpp | 5 +++-- controller/FileDB.cpp | 10 +++------- controller/FileDB.hpp | 1 + controller/RethinkDB.cpp | 11 ++++++++++- controller/RethinkDB.hpp | 4 ++-- 6 files changed, 20 insertions(+), 12 deletions(-) (limited to 'controller/FileDB.cpp') diff --git a/controller/DB.hpp b/controller/DB.hpp index 4757bb40..4b2940cd 100644 --- a/controller/DB.hpp +++ b/controller/DB.hpp @@ -82,6 +82,7 @@ public: virtual ~DB(); virtual bool waitForReady() = 0; + virtual bool isReady() = 0; inline bool hasNetwork(const uint64_t networkId) const { diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp index ef52f6e0..6a4134c6 100644 --- a/controller/EmbeddedNetworkController.cpp +++ b/controller/EmbeddedNetworkController.cpp @@ -596,10 +596,11 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET( // Controller status char tmp[4096]; - OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now()); + const bool dbOk = _db->isReady(); + OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu,\n\t\"databaseReady\": %s\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now(),dbOk ? "true" : "false"); responseBody = tmp; responseContentType = "application/json"; - return 200; + return dbOk ? 200 : 503; } diff --git a/controller/FileDB.cpp b/controller/FileDB.cpp index e78a64c9..8cbd60ce 100644 --- a/controller/FileDB.cpp +++ b/controller/FileDB.cpp @@ -63,14 +63,10 @@ FileDB::FileDB(EmbeddedNetworkController *const nc,const Identity &myId,const ch } } -FileDB::~FileDB() -{ -} +FileDB::~FileDB() {} -bool FileDB::waitForReady() -{ - return true; -} +bool FileDB::waitForReady() { return true; } +bool FileDB::isReady() { return true; } void FileDB::save(nlohmann::json *orig,nlohmann::json &record) { diff --git a/controller/FileDB.hpp b/controller/FileDB.hpp index 1e275a36..1a3c12e9 100644 --- a/controller/FileDB.hpp +++ b/controller/FileDB.hpp @@ -31,6 +31,7 @@ public: virtual ~FileDB(); virtual bool waitForReady(); + virtual bool isReady(); virtual void save(nlohmann::json *orig,nlohmann::json &record); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); diff --git a/controller/RethinkDB.cpp b/controller/RethinkDB.cpp index f6c8a59c..a46d033f 100644 --- a/controller/RethinkDB.cpp +++ b/controller/RethinkDB.cpp @@ -263,9 +263,13 @@ RethinkDB::RethinkDB(EmbeddedNetworkController *const nc,const Identity &myId,co std::unique_ptr rdb; while (_run == 1) { try { - if (!rdb) + if (!rdb) { + _connected = 0; rdb = R::connect(this->_host,this->_port,this->_auth); + } + if (rdb) { + _connected = 1; R::Array batch; R::Object tmpobj; @@ -434,6 +438,11 @@ bool RethinkDB::waitForReady() return true; } +bool RethinkDB::isReady() +{ + return ((_ready)&&(_connected)); +} + void RethinkDB::save(nlohmann::json *orig,nlohmann::json &record) { if (!record.is_object()) // sanity check diff --git a/controller/RethinkDB.hpp b/controller/RethinkDB.hpp index b1049ac3..60f04c5b 100644 --- a/controller/RethinkDB.hpp +++ b/controller/RethinkDB.hpp @@ -41,6 +41,7 @@ public: virtual ~RethinkDB(); virtual bool waitForReady(); + virtual bool isReady(); virtual void save(nlohmann::json *orig,nlohmann::json &record); virtual void eraseNetwork(const uint64_t networkId); virtual void eraseMember(const uint64_t networkId,const uint64_t memberId); @@ -72,8 +73,7 @@ protected: std::thread _heartbeatThread; mutable std::mutex _readyLock; // locked until ready - std::atomic _ready; - std::atomic _run; + std::atomic _ready,_connected,_run; mutable volatile bool _waitNoticePrinted; }; -- cgit v1.2.3