Bladeren bron

Add a concept of a member revision counter to networks. This can be used to select all members that have been added or changed since a given point.

Adam Ierymenko 10 jaren geleden
bovenliggende
commit
99969b186b

+ 30 - 6
controller/SqliteNetworkController.cpp

@@ -108,6 +108,7 @@ struct NetworkRecord {
 	int multicastLimit;
 	uint64_t creationTime;
 	uint64_t revision;
+	uint64_t memberRevisionCounter;
 };
 
 } // anonymous namespace
@@ -149,12 +150,13 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
 	if (
 
 			/* Network */
-			  (sqlite3_prepare_v2(_db,"SELECT name,private,enableBroadcast,allowPassiveBridging,v4AssignMode,v6AssignMode,multicastLimit,creationTime,revision FROM Network WHERE id = ?",-1,&_sGetNetworkById,(const char **)0) != SQLITE_OK)
+			  (sqlite3_prepare_v2(_db,"SELECT name,private,enableBroadcast,allowPassiveBridging,v4AssignMode,v6AssignMode,multicastLimit,creationTime,revision,memberRevisionCounter FROM Network WHERE id = ?",-1,&_sGetNetworkById,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"SELECT id FROM Network ORDER BY id ASC",-1,&_sListNetworks,(const char **)0) != SQLITE_OK)
+			||(sqlite3_prepare_v2(_db,"UPDATE Network SET memberRevisionCounter = (memberRevisionCounter + 1) WHERE id = ?",-1,&_sIncrementMemberRevisionCounter,(const char **)0) != SQLITE_OK)
 
 			/* Node */
 			||(sqlite3_prepare_v2(_db,"SELECT identity FROM Node WHERE id = ?",-1,&_sGetNodeIdentity,(const char **)0) != SQLITE_OK)
@@ -189,11 +191,11 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
 			/* Member */
 			||(sqlite3_prepare_v2(_db,"SELECT rowid,authorized,activeBridge FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sGetMember,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity FROM Member AS m JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK)
-			||(sqlite3_prepare_v2(_db,"INSERT INTO Member (networkId,nodeId,authorized,activeBridge) VALUES (?,?,?,0)",-1,&_sCreateMember,(const char **)0) != SQLITE_OK)
+			||(sqlite3_prepare_v2(_db,"INSERT INTO Member (networkId,nodeId,authorized,activeBridge,memberRevision) VALUES (?,?,?,0,(SELECT memberRevisionCounter FROM Network WHERE id = ?))",-1,&_sCreateMember,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"SELECT m.nodeId FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK)
-			||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK)
-			||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK)
+			||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK)
+			||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK)
 			||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
 
 			/* Gateway */
@@ -251,6 +253,7 @@ SqliteNetworkController::~SqliteNetworkController()
 		sqlite3_finalize(_sGetGateways);
 		sqlite3_finalize(_sDeleteGateways);
 		sqlite3_finalize(_sCreateGateway);
+		sqlite3_finalize(_sIncrementMemberRevisionCounter);
 		sqlite3_close(_db);
 	}
 }
@@ -316,6 +319,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
 		network.multicastLimit = sqlite3_column_int(_sGetNetworkById,6);
 		network.creationTime = (uint64_t)sqlite3_column_int64(_sGetNetworkById,7);
 		network.revision = (uint64_t)sqlite3_column_int64(_sGetNetworkById,8);
+		network.memberRevisionCounter = (uint64_t)sqlite3_column_int64(_sGetNetworkById,9);
 	} else return NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND;
 
 	// Fetch Member record
@@ -340,11 +344,16 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
 		sqlite3_bind_text(_sCreateMember,1,network.id,16,SQLITE_STATIC);
 		sqlite3_bind_text(_sCreateMember,2,member.nodeId,10,SQLITE_STATIC);
 		sqlite3_bind_int(_sCreateMember,3,(member.authorized ? 1 : 0));
+		sqlite3_bind_text(_sCreateMember,4,network.id,16,SQLITE_STATIC);
 		if (sqlite3_step(_sCreateMember) != SQLITE_DONE) {
 			netconf["error"] = "unable to create new member record";
 			return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR;
 		}
 		member.rowid = (int64_t)sqlite3_last_insert_rowid(_db);
+
+		sqlite3_reset(_sIncrementMemberRevisionCounter);
+		sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,network.id,16,SQLITE_STATIC);
+		sqlite3_step(_sIncrementMemberRevisionCounter);
 	}
 
 	// Check member authorization
@@ -683,9 +692,14 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
 						sqlite3_bind_text(_sCreateMember,1,nwids,16,SQLITE_STATIC);
 						sqlite3_bind_text(_sCreateMember,2,addrs,10,SQLITE_STATIC);
 						sqlite3_bind_int(_sCreateMember,3,0);
+						sqlite3_bind_text(_sCreateMember,4,nwids,16,SQLITE_STATIC);
 						if (sqlite3_step(_sCreateMember) != SQLITE_DONE)
 							return 500;
 						memberRowId = (int64_t)sqlite3_last_insert_rowid(_db);
+
+						sqlite3_reset(_sIncrementMemberRevisionCounter);
+						sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);
+						sqlite3_step(_sIncrementMemberRevisionCounter);
 					}
 
 					json_value *j = json_parse(body.c_str(),body.length());
@@ -697,17 +711,27 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
 									if (j->u.object.values[k].value->type == json_boolean) {
 										sqlite3_reset(_sUpdateMemberAuthorized);
 										sqlite3_bind_int(_sUpdateMemberAuthorized,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
-										sqlite3_bind_int64(_sUpdateMemberAuthorized,2,memberRowId);
+										sqlite3_bind_text(_sUpdateMemberAuthorized,2,nwids,16,SQLITE_STATIC);
+										sqlite3_bind_int64(_sUpdateMemberAuthorized,3,memberRowId);
 										if (sqlite3_step(_sUpdateMemberAuthorized) != SQLITE_DONE)
 											return 500;
+
+										sqlite3_reset(_sIncrementMemberRevisionCounter);
+										sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);
+										sqlite3_step(_sIncrementMemberRevisionCounter);
 									}
 								} else if (!strcmp(j->u.object.values[k].name,"activeBridge")) {
 									if (j->u.object.values[k].value->type == json_boolean) {
 										sqlite3_reset(_sUpdateMemberActiveBridge);
 										sqlite3_bind_int(_sUpdateMemberActiveBridge,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
-										sqlite3_bind_int64(_sUpdateMemberActiveBridge,2,memberRowId);
+										sqlite3_bind_text(_sUpdateMemberActiveBridge,2,nwids,16,SQLITE_STATIC);
+										sqlite3_bind_int64(_sUpdateMemberActiveBridge,3,memberRowId);
 										if (sqlite3_step(_sUpdateMemberActiveBridge) != SQLITE_DONE)
 											return 500;
+
+										sqlite3_reset(_sIncrementMemberRevisionCounter);
+										sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);
+										sqlite3_step(_sIncrementMemberRevisionCounter);
 									}
 								} else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) {
 									if (j->u.object.values[k].value->type == json_array) {

+ 1 - 0
controller/SqliteNetworkController.hpp

@@ -137,6 +137,7 @@ private:
 	sqlite3_stmt *_sGetGateways;
 	sqlite3_stmt *_sDeleteGateways;
 	sqlite3_stmt *_sCreateGateway;
+	sqlite3_stmt *_sIncrementMemberRevisionCounter;
 
 	Mutex _lock;
 };

+ 4 - 1
controller/schema.sql

@@ -13,7 +13,8 @@ CREATE TABLE Network (
   v6AssignMode varchar(8) NOT NULL DEFAULT('none'),
   multicastLimit integer NOT NULL DEFAULT(32),
   creationTime integer NOT NULL DEFAULT(0),
-  revision integer NOT NULL DEFAULT(1)
+  revision integer NOT NULL DEFAULT(1),
+  memberRevisionCounter integer NOT NULL DEFAULT(1)
 );
 
 CREATE TABLE Node (
@@ -57,10 +58,12 @@ CREATE TABLE Member (
   nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
   authorized integer NOT NULL DEFAULT(0),
   activeBridge integer NOT NULL DEFAULT(0),
+  memberRevision integer NOT NULL DEFAULT(0)
   PRIMARY KEY (networkId, nodeId)
 );
 
 CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
+CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);
 
 CREATE TABLE Relay (
   networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,

+ 4 - 1
controller/schema.sql.c

@@ -14,7 +14,8 @@
 "  v6AssignMode varchar(8) NOT NULL DEFAULT('none'),\n"\
 "  multicastLimit integer NOT NULL DEFAULT(32),\n"\
 "  creationTime integer NOT NULL DEFAULT(0),\n"\
-"  revision integer NOT NULL DEFAULT(1)\n"\
+"  revision integer NOT NULL DEFAULT(1),\n"\
+"  memberRevisionCounter integer NOT NULL DEFAULT(1)\n"\
 ");\n"\
 "\n"\
 "CREATE TABLE Node (\n"\
@@ -58,10 +59,12 @@
 "  nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
 "  authorized integer NOT NULL DEFAULT(0),\n"\
 "  activeBridge integer NOT NULL DEFAULT(0),\n"\
+"  memberRevision integer NOT NULL DEFAULT(0)\n"\
 "  PRIMARY KEY (networkId, nodeId)\n"\
 ");\n"\
 "\n"\
 "CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
+"CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);\n"\
 "\n"\
 "CREATE TABLE Relay (\n"\
 "  networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\