Browse Source

Cruftectomy, work in progress on mirrorring

Adam Ierymenko 6 years ago
parent
commit
3c776675b3

+ 3 - 1
controller/DB.hpp

@@ -27,6 +27,8 @@
 #ifndef ZT_CONTROLLER_DB_HPP
 #ifndef ZT_CONTROLLER_DB_HPP
 #define ZT_CONTROLLER_DB_HPP
 #define ZT_CONTROLLER_DB_HPP
 
 
+#define ZT_CONTROLLER_USE_LIBPQ
+
 #include "../node/Constants.hpp"
 #include "../node/Constants.hpp"
 #include "../node/Identity.hpp"
 #include "../node/Identity.hpp"
 #include "../node/InetAddress.hpp"
 #include "../node/InetAddress.hpp"
@@ -99,7 +101,7 @@ public:
 	bool summary(const uint64_t networkId,NetworkSummaryInfo &info);
 	bool summary(const uint64_t networkId,NetworkSummaryInfo &info);
 	void networks(std::vector<uint64_t> &networks);
 	void networks(std::vector<uint64_t> &networks);
 
 
-	virtual void save(nlohmann::json *orig,nlohmann::json &record) = 0;
+	virtual void save(nlohmann::json &record) = 0;
 
 
 	virtual void eraseNetwork(const uint64_t networkId) = 0;
 	virtual void eraseNetwork(const uint64_t networkId) = 0;
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0;
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId) = 0;

+ 112 - 0
controller/DBMirrorSet.cpp

@@ -0,0 +1,112 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2019  ZeroTier, Inc.  https://www.zerotier.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial closed-source software that incorporates or links
+ * directly against ZeroTier software without disclosing the source code
+ * of your own application.
+ */
+
+#include "DBMirrorSet.hpp"
+
+namespace ZeroTier {
+
+DBMirrorSet::DBMirrorSet()
+{
+}
+
+DBMirrorSet::~DBMirrorSet()
+{
+}
+
+bool DBMirrorSet::waitForReady()
+{
+	bool r = false;
+	std::lock_guard<std::mutex> l(_dbs_l);
+	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+		r |= (*d)->waitForReady();
+	}
+	return r;
+}
+
+bool DBMirrorSet::isReady()
+{
+	std::lock_guard<std::mutex> l(_dbs_l);
+	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+		if (!(*d)->isReady())
+			return false;
+	}
+	return true;
+}
+
+void DBMirrorSet::save(nlohmann::json &record)
+{
+	std::lock_guard<std::mutex> l(_dbs_l);
+	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+		(*d)->save(record);
+	}
+}
+
+void DBMirrorSet::eraseNetwork(const uint64_t networkId)
+{
+	std::lock_guard<std::mutex> l(_dbs_l);
+	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+		(*d)->eraseNetwork(networkId);
+	}
+}
+
+void DBMirrorSet::eraseMember(const uint64_t networkId,const uint64_t memberId)
+{
+	std::lock_guard<std::mutex> l(_dbs_l);
+	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+		(*d)->eraseMember(networkId,memberId);
+	}
+}
+
+void DBMirrorSet::nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress)
+{
+	std::lock_guard<std::mutex> l(_dbs_l);
+	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+		(*d)->nodeIsOnline(networkId,memberId,physicalAddress);
+	}
+}
+
+void DBMirrorSet::onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network)
+{
+	std::lock_guard<std::mutex> l(_dbs_l);
+	for(auto d=_dbs.begin();d!=_dbs.end();++d) {
+		if (d->get() != db) {
+		}
+	}
+}
+
+void DBMirrorSet::onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member)
+{
+}
+
+void DBMirrorSet::onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId)
+{
+}
+
+void DBMirrorSet::onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress)
+{
+}
+
+} // namespace ZeroTier

+ 70 - 0
controller/DBMirrorSet.hpp

@@ -0,0 +1,70 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2019  ZeroTier, Inc.  https://www.zerotier.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial closed-source software that incorporates or links
+ * directly against ZeroTier software without disclosing the source code
+ * of your own application.
+ */
+
+#ifndef ZT_DBMIRRORSET_HPP
+#define ZT_DBMIRRORSET_HPP
+
+#include "DB.hpp"
+
+#include <vector>
+#include <memory>
+#include <mutex>
+
+namespace ZeroTier {
+
+class DBMirrorSet : public DB::ChangeListener
+{
+public:
+	DBMirrorSet();
+	virtual ~DBMirrorSet();
+
+	bool waitForReady();
+	bool isReady();
+	void save(nlohmann::json &record);
+	void eraseNetwork(const uint64_t networkId);
+	void eraseMember(const uint64_t networkId,const uint64_t memberId);
+	void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
+
+	// These are called by various DB instances when changes occur.
+	virtual void onNetworkUpdate(const DB *db,uint64_t networkId,const nlohmann::json &network);
+	virtual void onNetworkMemberUpdate(const DB *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member);
+	virtual void onNetworkMemberDeauthorize(const DB *db,uint64_t networkId,uint64_t memberId);
+	virtual void onNetworkMemberOnline(const DB *db,uint64_t networkId,uint64_t memberId,const InetAddress &physicalAddress);
+
+	inline void addDB(const std::shared_ptr<DB> &db)
+	{
+		std::lock_guard<std::mutex> l(_dbs_l);
+		_dbs.push_back(db);
+	}
+
+private:
+	std::vector< std::shared_ptr< DB > > _dbs;
+	std::mutex _dbs_l;
+};
+
+} // namespace ZeroTier
+
+#endif

+ 6 - 9
controller/EmbeddedNetworkController.cpp

@@ -705,7 +705,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
 
 
 					json member,network;
 					json member,network;
 					_db->get(nwid,network,address,member);
 					_db->get(nwid,network,address,member);
-					json origMember(member); // for detecting changes
 					DB::initMember(member);
 					DB::initMember(member);
 
 
 					try {
 					try {
@@ -799,7 +798,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
 					member["nwid"] = nwids;
 					member["nwid"] = nwids;
 
 
 					DB::cleanMember(member);
 					DB::cleanMember(member);
-					_db->save(&origMember,member);
+					_db->save(member);
 					responseBody = OSUtils::jsonDump(member);
 					responseBody = OSUtils::jsonDump(member);
 					responseContentType = "application/json";
 					responseContentType = "application/json";
 
 
@@ -830,7 +829,6 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
 
 
 				json network;
 				json network;
 				_db->get(nwid,network);
 				_db->get(nwid,network);
-				json origNetwork(network); // for detecting changes
 				DB::initNetwork(network);
 				DB::initNetwork(network);
 
 
 				try {
 				try {
@@ -1061,7 +1059,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
 				network["nwid"] = nwids; // legacy
 				network["nwid"] = nwids; // legacy
 
 
 				DB::cleanNetwork(network);
 				DB::cleanNetwork(network);
-				_db->save(&origNetwork,network);
+				_db->save(network);
 
 
 				responseBody = OSUtils::jsonDump(network);
 				responseBody = OSUtils::jsonDump(network);
 				responseContentType = "application/json";
 				responseContentType = "application/json";
@@ -1184,7 +1182,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt)
 		d["objtype"] = "trace";
 		d["objtype"] = "trace";
 		d["ts"] = now;
 		d["ts"] = now;
 		d["nodeId"] = Utils::hex10(rt.origin,tmp);
 		d["nodeId"] = Utils::hex10(rt.origin,tmp);
-		_db->save((nlohmann::json *)0,d);
+		_db->save(d);
 	} catch ( ... ) {
 	} catch ( ... ) {
 		// drop invalid trace messages if an error occurs
 		// drop invalid trace messages if an error occurs
 	}
 	}
@@ -1235,7 +1233,7 @@ void EmbeddedNetworkController::_request(
 {
 {
 	char nwids[24];
 	char nwids[24];
 	DB::NetworkSummaryInfo ns;
 	DB::NetworkSummaryInfo ns;
-	json network,member,origMember;
+	json network,member;
 
 
 	if (!_db)
 	if (!_db)
 		return;
 		return;
@@ -1261,7 +1259,6 @@ void EmbeddedNetworkController::_request(
 		_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND);
 		_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND);
 		return;
 		return;
 	}
 	}
-	origMember = member;
 	const bool newMember = ((!member.is_object())||(member.size() == 0));
 	const bool newMember = ((!member.is_object())||(member.size() == 0));
 	DB::initMember(member);
 	DB::initMember(member);
 
 
@@ -1362,7 +1359,7 @@ void EmbeddedNetworkController::_request(
 	} else {
 	} else {
 		// If they are not authorized, STOP!
 		// If they are not authorized, STOP!
 		DB::cleanMember(member);
 		DB::cleanMember(member);
-		_db->save(&origMember,member);
+		_db->save(member);
 		_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED);
 		_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED);
 		return;
 		return;
 	}
 	}
@@ -1734,7 +1731,7 @@ void EmbeddedNetworkController::_request(
 	}
 	}
 
 
 	DB::cleanMember(member);
 	DB::cleanMember(member);
-	_db->save(&origMember,member);
+	_db->save(member);
 	_sender->ncSendConfig(nwid,requestPacketId,identity.address(),*(nc.get()),metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6);
 	_sender->ncSendConfig(nwid,requestPacketId,identity.address(),*(nc.get()),metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6);
 }
 }
 
 

+ 7 - 15
controller/FileDB.cpp

@@ -85,38 +85,35 @@ FileDB::~FileDB()
 bool FileDB::waitForReady() { return true; }
 bool FileDB::waitForReady() { return true; }
 bool FileDB::isReady() { return true; }
 bool FileDB::isReady() { return true; }
 
 
-void FileDB::save(nlohmann::json *orig,nlohmann::json &record)
+void FileDB::save(nlohmann::json &record)
 {
 {
 	char p1[4096],p2[4096],pb[4096];
 	char p1[4096],p2[4096],pb[4096];
 	try {
 	try {
-		if (orig) {
-			if (*orig != record) {
-				record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1;
-			}
-		} else {
-			record["revision"] = 1;
-		}
-
 		const std::string objtype = record["objtype"];
 		const std::string objtype = record["objtype"];
 		if (objtype == "network") {
 		if (objtype == "network") {
+
 			const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
 			const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
 			if (nwid) {
 			if (nwid) {
 				nlohmann::json old;
 				nlohmann::json old;
 				get(nwid,old);
 				get(nwid,old);
 				if ((!old.is_object())||(old != record)) {
 				if ((!old.is_object())||(old != record)) {
+					record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
 					OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid);
 					OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.16llx.json",_networksPath.c_str(),nwid);
 					if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)))
 					if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1)))
 						fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
 						fprintf(stderr,"WARNING: controller unable to write to path: %s" ZT_EOL_S,p1);
 					_networkChanged(old,record,true);
 					_networkChanged(old,record,true);
 				}
 				}
 			}
 			}
+
 		} else if (objtype == "member") {
 		} else if (objtype == "member") {
+
 			const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL);
 			const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL);
 			const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL);
 			const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL);
 			if ((id)&&(nwid)) {
 			if ((id)&&(nwid)) {
 				nlohmann::json network,old;
 				nlohmann::json network,old;
 				get(nwid,network,id,old);
 				get(nwid,network,id,old);
 				if ((!old.is_object())||(old != record)) {
 				if ((!old.is_object())||(old != record)) {
+					record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
 					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(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",pb,(unsigned long long)id);
 					OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%.10llx.json",pb,(unsigned long long)id);
 					if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
 					if (!OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1))) {
@@ -129,12 +126,7 @@ void FileDB::save(nlohmann::json *orig,nlohmann::json &record)
 					_memberChanged(old,record,true);
 					_memberChanged(old,record,true);
 				}
 				}
 			}
 			}
-		} else if (objtype == "trace") {
-			const std::string id = record["id"];
-			if (id.length() > 0) {
-				OSUtils::ztsnprintf(p1,sizeof(p1),"%s" ZT_PATH_SEPARATOR_S "%s.json",_tracePath.c_str(),id.c_str());
-				OSUtils::writeFile(p1,OSUtils::jsonDump(record,-1));
-			}
+
 		}
 		}
 	} catch ( ... ) {} // drop invalid records missing fields
 	} catch ( ... ) {} // drop invalid records missing fields
 }
 }

+ 1 - 1
controller/FileDB.hpp

@@ -40,7 +40,7 @@ public:
 
 
 	virtual bool waitForReady();
 	virtual bool waitForReady();
 	virtual bool isReady();
 	virtual bool isReady();
-	virtual void save(nlohmann::json *orig,nlohmann::json &record);
+	virtual void save(nlohmann::json &record);
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
 	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
 	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);

+ 3 - 9
controller/LFDB.cpp

@@ -335,16 +335,8 @@ bool LFDB::isReady()
 	return (_ready.load());
 	return (_ready.load());
 }
 }
 
 
-void LFDB::save(nlohmann::json *orig,nlohmann::json &record)
+void LFDB::save(nlohmann::json &record)
 {
 {
-	if (orig) {
-		if (*orig != record) {
-			record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1;
-		}
-	} else {
-		record["revision"] = 1;
-	}
-
 	const std::string objtype = record["objtype"];
 	const std::string objtype = record["objtype"];
 	if (objtype == "network") {
 	if (objtype == "network") {
 		const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
 		const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
@@ -352,6 +344,7 @@ void LFDB::save(nlohmann::json *orig,nlohmann::json &record)
 			nlohmann::json old;
 			nlohmann::json old;
 			get(nwid,old);
 			get(nwid,old);
 			if ((!old.is_object())||(old != record)) {
 			if ((!old.is_object())||(old != record)) {
+				record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
 				_networkChanged(old,record,true);
 				_networkChanged(old,record,true);
 				{
 				{
 					std::lock_guard<std::mutex> l(_state_l);
 					std::lock_guard<std::mutex> l(_state_l);
@@ -366,6 +359,7 @@ void LFDB::save(nlohmann::json *orig,nlohmann::json &record)
 			nlohmann::json network,old;
 			nlohmann::json network,old;
 			get(nwid,network,id,old);
 			get(nwid,network,id,old);
 			if ((!old.is_object())||(old != record)) {
 			if ((!old.is_object())||(old != record)) {
+				record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
 				_memberChanged(old,record,true);
 				_memberChanged(old,record,true);
 				{
 				{
 					std::lock_guard<std::mutex> l(_state_l);
 					std::lock_guard<std::mutex> l(_state_l);

+ 1 - 1
controller/LFDB.hpp

@@ -56,7 +56,7 @@ public:
 
 
 	virtual bool waitForReady();
 	virtual bool waitForReady();
 	virtual bool isReady();
 	virtual bool isReady();
-	virtual void save(nlohmann::json *orig,nlohmann::json &record);
+	virtual void save(nlohmann::json &record);
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
 	virtual void eraseMember(const uint64_t networkId,const uint64_t memberId);
 	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);
 	virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress);

+ 26 - 2
controller/PostgreSQL.cpp

@@ -165,12 +165,35 @@ bool PostgreSQL::isReady()
 	return ((_ready == 2)&&(_connected));
 	return ((_ready == 2)&&(_connected));
 }
 }
 
 
-void PostgreSQL::save(nlohmann::json *orig, nlohmann::json &record)
+void PostgreSQL::save(nlohmann::json &record)
 {
 {
 	try {
 	try {
-		if (!record.is_object()) {
+		if (!record.is_object())
 			return;
 			return;
+		const std::string objtype = record["objtype"];
+		if (objtype == "network") {
+			const uint64_t nwid = OSUtils::jsonIntHex(record["id"],0ULL);
+			if (nwid) {
+				nlohmann::json old;
+				get(nwid,old);
+				if ((!old.is_object())||(old != record)) {
+					record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
+					_commitQueue.post(new nlohmann::json(record));
+				}
+			}
+		} else if (objtype == "member") {
+			const uint64_t nwid = OSUtils::jsonIntHex(record["nwid"],0ULL);
+			const uint64_t id = OSUtils::jsonIntHex(record["id"],0ULL);
+			if ((id)&&(nwid)) {
+				nlohmann::json network,old;
+				get(nwid,network,id,old);
+				if ((!old.is_object())||(old != record)) {
+					record["revision"] = OSUtils::jsonInt(record["revision"],0ULL) + 1ULL;
+					_commitQueue.post(new nlohmann::json(record));
+				}
+			}
 		}
 		}
+		/*
 		waitForReady();
 		waitForReady();
 		if (orig) {
 		if (orig) {
 			if (*orig != record) {
 			if (*orig != record) {
@@ -181,6 +204,7 @@ void PostgreSQL::save(nlohmann::json *orig, nlohmann::json &record)
 			record["revision"] = 1;
 			record["revision"] = 1;
 			_commitQueue.post(new nlohmann::json(record));
 			_commitQueue.post(new nlohmann::json(record));
 		}
 		}
+		*/
 	} catch (std::exception &e) {
 	} catch (std::exception &e) {
 		fprintf(stderr, "Error on PostgreSQL::save: %s\n", e.what());
 		fprintf(stderr, "Error on PostgreSQL::save: %s\n", e.what());
 	} catch (...) {
 	} catch (...) {

+ 3 - 5
controller/PostgreSQL.hpp

@@ -23,16 +23,14 @@
  * directly against ZeroTier software without disclosing the source code
  * directly against ZeroTier software without disclosing the source code
  * of your own application.
  * of your own application.
  */
  */
- 
-#define ZT_CONTROLLER_USE_LIBPQ
+
+#include "DB.hpp"
 
 
 #ifdef ZT_CONTROLLER_USE_LIBPQ
 #ifdef ZT_CONTROLLER_USE_LIBPQ
 
 
 #ifndef ZT_CONTROLLER_LIBPQ_HPP
 #ifndef ZT_CONTROLLER_LIBPQ_HPP
 #define ZT_CONTROLLER_LIBPQ_HPP
 #define ZT_CONTROLLER_LIBPQ_HPP
 
 
-#include "DB.hpp"
-
 #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
 #define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
 
 
 extern "C" {
 extern "C" {
@@ -57,7 +55,7 @@ public:
 
 
 	virtual bool waitForReady();
 	virtual bool waitForReady();
 	virtual bool isReady();
 	virtual bool isReady();
-	virtual void save(nlohmann::json *orig, nlohmann::json &record);
+	virtual void save(nlohmann::json &record);
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseNetwork(const uint64_t networkId);
 	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
 	virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
 	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress);
 	virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress &physicalAddress);

+ 27 - 0
controller/RabbitMQ.cpp

@@ -1,3 +1,30 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2019  ZeroTier, Inc.  https://www.zerotier.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial closed-source software that incorporates or links
+ * directly against ZeroTier software without disclosing the source code
+ * of your own application.
+ */
+
+
 #include "RabbitMQ.hpp"
 #include "RabbitMQ.hpp"
 
 
 #ifdef ZT_CONTROLLER_USE_LIBPQ
 #ifdef ZT_CONTROLLER_USE_LIBPQ

+ 2 - 0
controller/RabbitMQ.hpp

@@ -27,6 +27,8 @@
 #ifndef ZT_CONTROLLER_RABBITMQ_HPP
 #ifndef ZT_CONTROLLER_RABBITMQ_HPP
 #define ZT_CONTROLLER_RABBITMQ_HPP
 #define ZT_CONTROLLER_RABBITMQ_HPP
 
 
+#include "DB.hpp"
+
 namespace ZeroTier
 namespace ZeroTier
 {
 {
 struct MQConfig {
 struct MQConfig {