浏览代码

Revert "remove redundant writes when changes come from Central"

This reverts commit f9396f979f82f39424dc36b2e81d52d0e00464e0.
Grant Limberg 4 年之前
父节点
当前提交
c80843e496
共有 1 个文件被更改,包括 357 次插入365 次删除
  1. 357 365
      controller/PostgreSQL.cpp

+ 357 - 365
controller/PostgreSQL.cpp

@@ -1078,165 +1078,160 @@ void PostgreSQL::commitThread()
 			const std::string objtype = (*config)["objtype"];
 			if (objtype == "member") {
 				try {
-					bool fromCentral = OSUtils::jsonBool((*config)["fromCentral"], false);
-					if (!fromCentral) {
-						// Central already writes all of this to the DB on a change.
-						// No need for the controller to do it as well.
-						std::string memberId = (*config)["id"];
-						std::string networkId = (*config)["nwid"];
-						std::string identity = (*config)["identity"];
-						std::string target = "NULL";
-
-						if (!(*config)["remoteTraceTarget"].is_null()) {
-							target = (*config)["remoteTraceTarget"];
-						}
+					std::string memberId = (*config)["id"];
+					std::string networkId = (*config)["nwid"];
+					std::string identity = (*config)["identity"];
+					std::string target = "NULL";
 
-						std::string caps = OSUtils::jsonDump((*config)["capabilities"], -1);
-						std::string lastAuthTime = std::to_string((long long)(*config)["lastAuthorizedTime"]);
-						std::string lastDeauthTime = std::to_string((long long)(*config)["lastDeauthorizedTime"]);
-						std::string rtraceLevel = std::to_string((int)(*config)["remoteTraceLevel"]);
-						std::string rev = std::to_string((unsigned long long)(*config)["revision"]);
-						std::string tags = OSUtils::jsonDump((*config)["tags"], -1);
-						std::string vmajor = std::to_string((int)(*config)["vMajor"]);
-						std::string vminor = std::to_string((int)(*config)["vMinor"]);
-						std::string vrev = std::to_string((int)(*config)["vRev"]);
-						std::string vproto = std::to_string((int)(*config)["vProto"]);
-						const char *values[19] = {
-							memberId.c_str(),
-							networkId.c_str(),
-							((*config)["activeBridge"] ? "true" : "false"),
-							((*config)["authorized"] ? "true" : "false"),
-							caps.c_str(),
-							identity.c_str(),
-							lastAuthTime.c_str(),
-							lastDeauthTime.c_str(),
-							((*config)["noAutoAssignIps"] ? "true" : "false"),
-							rtraceLevel.c_str(),
-							(target == "NULL") ? NULL : target.c_str(),
-							rev.c_str(),
-							tags.c_str(),
-							vmajor.c_str(),
-							vminor.c_str(),
-							vrev.c_str(),
-							vproto.c_str()
-						};
+					if (!(*config)["remoteTraceTarget"].is_null()) {
+						target = (*config)["remoteTraceTarget"];
+					}
 
-						PGresult *res = PQexec(conn, "BEGIN");
-						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error beginning update transaction: %s\n", PQresultErrorMessage(res));
-							PQclear(res);
-							delete config;
-							config = nullptr;
-							continue;
-						}
-						
-						
-						res = PQexecParams(conn,
-							"INSERT INTO ztc_member (id, network_id, active_bridge, authorized, capabilities, "
-							"identity, last_authorized_time, last_deauthorized_time, no_auto_assign_ips, "
-							"remote_trace_level, remote_trace_target, revision, tags, v_major, v_minor, v_rev, v_proto) "
-							"VALUES ($1, $2, $3, $4, $5, $6, "
-							"TO_TIMESTAMP($7::double precision/1000), TO_TIMESTAMP($8::double precision/1000), "
-							"$9, $10, $11, $12, $13, $14, $15, $16, $17) ON CONFLICT (network_id, id) DO UPDATE SET "
-							"active_bridge = EXCLUDED.active_bridge, authorized = EXCLUDED.authorized, capabilities = EXCLUDED.capabilities, "
-							"identity = EXCLUDED.identity, last_authorized_time = EXCLUDED.last_authorized_time, "
-							"last_deauthorized_time = EXCLUDED.last_deauthorized_time, no_auto_assign_ips = EXCLUDED.no_auto_assign_ips, "
-							"remote_trace_level = EXCLUDED.remote_trace_level, remote_trace_target = EXCLUDED.remote_trace_target, "
-							"revision = EXCLUDED.revision+1, tags = EXCLUDED.tags, v_major = EXCLUDED.v_major, "
-							"v_minor = EXCLUDED.v_minor, v_rev = EXCLUDED.v_rev, v_proto = EXCLUDED.v_proto",
-							17,
-							NULL,
-							values,
-							NULL,
-							NULL,
-							0);
+					std::string caps = OSUtils::jsonDump((*config)["capabilities"], -1);
+					std::string lastAuthTime = std::to_string((long long)(*config)["lastAuthorizedTime"]);
+					std::string lastDeauthTime = std::to_string((long long)(*config)["lastDeauthorizedTime"]);
+					std::string rtraceLevel = std::to_string((int)(*config)["remoteTraceLevel"]);
+					std::string rev = std::to_string((unsigned long long)(*config)["revision"]);
+					std::string tags = OSUtils::jsonDump((*config)["tags"], -1);
+					std::string vmajor = std::to_string((int)(*config)["vMajor"]);
+					std::string vminor = std::to_string((int)(*config)["vMinor"]);
+					std::string vrev = std::to_string((int)(*config)["vRev"]);
+					std::string vproto = std::to_string((int)(*config)["vProto"]);
+					const char *values[19] = {
+						memberId.c_str(),
+						networkId.c_str(),
+						((*config)["activeBridge"] ? "true" : "false"),
+						((*config)["authorized"] ? "true" : "false"),
+						caps.c_str(),
+						identity.c_str(),
+						lastAuthTime.c_str(),
+						lastDeauthTime.c_str(),
+						((*config)["noAutoAssignIps"] ? "true" : "false"),
+						rtraceLevel.c_str(),
+						(target == "NULL") ? NULL : target.c_str(),
+						rev.c_str(),
+						tags.c_str(),
+						vmajor.c_str(),
+						vminor.c_str(),
+						vrev.c_str(),
+						vproto.c_str()
+					};
 
-						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error updating member: %s\n", PQresultErrorMessage(res));
-							fprintf(stderr, "%s", OSUtils::jsonDump(*config, 2).c_str());
-							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
-							continue;
-						}
+					PGresult *res = PQexec(conn, "BEGIN");
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error beginning update transaction: %s\n", PQresultErrorMessage(res));
+						PQclear(res);
+						delete config;
+						config = nullptr;
+						continue;
+					}
+					
+					
+					res = PQexecParams(conn,
+						"INSERT INTO ztc_member (id, network_id, active_bridge, authorized, capabilities, "
+						"identity, last_authorized_time, last_deauthorized_time, no_auto_assign_ips, "
+						"remote_trace_level, remote_trace_target, revision, tags, v_major, v_minor, v_rev, v_proto) "
+						"VALUES ($1, $2, $3, $4, $5, $6, "
+						"TO_TIMESTAMP($7::double precision/1000), TO_TIMESTAMP($8::double precision/1000), "
+						"$9, $10, $11, $12, $13, $14, $15, $16, $17) ON CONFLICT (network_id, id) DO UPDATE SET "
+						"active_bridge = EXCLUDED.active_bridge, authorized = EXCLUDED.authorized, capabilities = EXCLUDED.capabilities, "
+						"identity = EXCLUDED.identity, last_authorized_time = EXCLUDED.last_authorized_time, "
+						"last_deauthorized_time = EXCLUDED.last_deauthorized_time, no_auto_assign_ips = EXCLUDED.no_auto_assign_ips, "
+						"remote_trace_level = EXCLUDED.remote_trace_level, remote_trace_target = EXCLUDED.remote_trace_target, "
+						"revision = EXCLUDED.revision+1, tags = EXCLUDED.tags, v_major = EXCLUDED.v_major, "
+						"v_minor = EXCLUDED.v_minor, v_rev = EXCLUDED.v_rev, v_proto = EXCLUDED.v_proto",
+						17,
+						NULL,
+						values,
+						NULL,
+						NULL,
+						0);
 
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error updating member: %s\n", PQresultErrorMessage(res));
+						fprintf(stderr, "%s", OSUtils::jsonDump(*config, 2).c_str());
 						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
+					}
 
-						const char *v2[2] = {
-							memberId.c_str(),
-							networkId.c_str()
-						};
+					PQclear(res);
 
-						res = PQexecParams(conn,
-							"DELETE FROM ztc_member_ip_assignment WHERE member_id = $1 AND network_id = $2",
-							2,
-							NULL,
-							v2,
-							NULL,
-							NULL,
-							0);
+					const char *v2[2] = {
+						memberId.c_str(),
+						networkId.c_str()
+					};
 
-						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error updating IP address assignments: %s\n", PQresultErrorMessage(res));
-							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));;
-							delete config;
-							config = nullptr;
-							continue;
-						}
+					res = PQexecParams(conn,
+						"DELETE FROM ztc_member_ip_assignment WHERE member_id = $1 AND network_id = $2",
+						2,
+						NULL,
+						v2,
+						NULL,
+						NULL,
+						0);
 
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error updating IP address assignments: %s\n", PQresultErrorMessage(res));
 						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));;
+						delete config;
+						config = nullptr;
+						continue;
+					}
 
-						std::vector<std::string> assignments;
-						bool ipAssignError = false;
-						for (auto i = (*config)["ipAssignments"].begin(); i != (*config)["ipAssignments"].end(); ++i) {
-							std::string addr = *i;
+					PQclear(res);
 
-							if (std::find(assignments.begin(), assignments.end(), addr) != assignments.end()) {
-								continue;
-							}
+					std::vector<std::string> assignments;
+					bool ipAssignError = false;
+					for (auto i = (*config)["ipAssignments"].begin(); i != (*config)["ipAssignments"].end(); ++i) {
+						std::string addr = *i;
 
-							const char *v3[3] = {
-								memberId.c_str(),
-								networkId.c_str(),
-								addr.c_str()
-							};
-
-							res = PQexecParams(conn,
-								"INSERT INTO ztc_member_ip_assignment (member_id, network_id, address) VALUES ($1, $2, $3) ON CONFLICT (network_id, member_id, address) DO NOTHING",
-								3,
-								NULL,
-								v3,
-								NULL,
-								NULL,
-								0);
-
-							if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-								fprintf(stderr, "ERROR: Error setting IP addresses for member: %s\n", PQresultErrorMessage(res));
-								PQclear(res);
-								PQclear(PQexec(conn, "ROLLBACK"));
-								ipAssignError = true;
-								break;
-							}
-							PQclear(res);
-							assignments.push_back(addr);
-						}
-						if (ipAssignError) {
-							delete config;
-							config = nullptr;
+						if (std::find(assignments.begin(), assignments.end(), addr) != assignments.end()) {
 							continue;
 						}
 
-						res = PQexec(conn, "COMMIT");
+						const char *v3[3] = {
+							memberId.c_str(),
+							networkId.c_str(),
+							addr.c_str()
+						};
+
+						res = PQexecParams(conn,
+							"INSERT INTO ztc_member_ip_assignment (member_id, network_id, address) VALUES ($1, $2, $3) ON CONFLICT (network_id, member_id, address) DO NOTHING",
+							3,
+							NULL,
+							v3,
+							NULL,
+							NULL,
+							0);
+
 						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error committing member transaction: %s\n", PQresultErrorMessage(res));
+							fprintf(stderr, "ERROR: Error setting IP addresses for member: %s\n", PQresultErrorMessage(res));
 							PQclear(res);
 							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
-							continue;
+							ipAssignError = true;
+							break;
 						}
+						PQclear(res);
+						assignments.push_back(addr);
+					}
+					if (ipAssignError) {
+						delete config;
+						config = nullptr;
+						continue;
+					}
+
+					res = PQexec(conn, "COMMIT");
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error committing member transaction: %s\n", PQresultErrorMessage(res));
+						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
 					}
 
 					const uint64_t nwidInt = OSUtils::jsonIntHex((*config)["nwid"], 0ULL);
@@ -1259,274 +1254,271 @@ void PostgreSQL::commitThread()
 				}
 			} else if (objtype == "network") {
 				try {
-					bool fromCentral = OSUtils::jsonBool((*config)["fromCentral"], false);
-					if (!fromCentral) {
-						std::string id = (*config)["id"];
-						std::string controllerId = _myAddressStr.c_str();
-						std::string name = (*config)["name"];
-						std::string remoteTraceTarget("NULL");
-						if (!(*config)["remoteTraceTarget"].is_null()) {
-							remoteTraceTarget = (*config)["remoteTraceTarget"];
-						}
-						std::string rulesSource;
-						if ((*config)["rulesSource"].is_string()) {
-							rulesSource = (*config)["rulesSource"];
-						}
-						std::string caps = OSUtils::jsonDump((*config)["capabilitles"], -1);
-						std::string now = std::to_string(OSUtils::now());
-						std::string mtu = std::to_string((int)(*config)["mtu"]);
-						std::string mcastLimit = std::to_string((int)(*config)["multicastLimit"]);
-						std::string rtraceLevel = std::to_string((int)(*config)["remoteTraceLevel"]);
-						std::string rules = OSUtils::jsonDump((*config)["rules"], -1);
-						std::string tags = OSUtils::jsonDump((*config)["tags"], -1);
-						std::string v4mode = OSUtils::jsonDump((*config)["v4AssignMode"],-1);
-						std::string v6mode = OSUtils::jsonDump((*config)["v6AssignMode"], -1);
-						bool enableBroadcast = (*config)["enableBroadcast"];
-						bool isPrivate = (*config)["private"];
-
-						const char *values[16] = {
-							id.c_str(),
-							controllerId.c_str(),
-							caps.c_str(),
-							enableBroadcast ? "true" : "false",
-							now.c_str(),
-							mtu.c_str(),
-							mcastLimit.c_str(),
-							name.c_str(),
-							isPrivate ? "true" : "false",
-							rtraceLevel.c_str(),
-							(remoteTraceTarget == "NULL" ? NULL : remoteTraceTarget.c_str()),
-							rules.c_str(),
-							rulesSource.c_str(),
-							tags.c_str(),
-							v4mode.c_str(),
-							v6mode.c_str(),
-						};
-
-						PGresult *res = PQexec(conn, "BEGIN");
-						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error beginnning transaction: %s\n", PQresultErrorMessage(res));
-							PQclear(res);
-							delete config;
-							config = nullptr;
-							continue;
-						}
+					std::string id = (*config)["id"];
+					std::string controllerId = _myAddressStr.c_str();
+					std::string name = (*config)["name"];
+					std::string remoteTraceTarget("NULL");
+					if (!(*config)["remoteTraceTarget"].is_null()) {
+						remoteTraceTarget = (*config)["remoteTraceTarget"];
+					}
+					std::string rulesSource;
+					if ((*config)["rulesSource"].is_string()) {
+						rulesSource = (*config)["rulesSource"];
+					}
+					std::string caps = OSUtils::jsonDump((*config)["capabilitles"], -1);
+					std::string now = std::to_string(OSUtils::now());
+					std::string mtu = std::to_string((int)(*config)["mtu"]);
+					std::string mcastLimit = std::to_string((int)(*config)["multicastLimit"]);
+					std::string rtraceLevel = std::to_string((int)(*config)["remoteTraceLevel"]);
+					std::string rules = OSUtils::jsonDump((*config)["rules"], -1);
+					std::string tags = OSUtils::jsonDump((*config)["tags"], -1);
+					std::string v4mode = OSUtils::jsonDump((*config)["v4AssignMode"],-1);
+					std::string v6mode = OSUtils::jsonDump((*config)["v6AssignMode"], -1);
+					bool enableBroadcast = (*config)["enableBroadcast"];
+					bool isPrivate = (*config)["private"];
+
+					const char *values[16] = {
+						id.c_str(),
+						controllerId.c_str(),
+						caps.c_str(),
+						enableBroadcast ? "true" : "false",
+						now.c_str(),
+						mtu.c_str(),
+						mcastLimit.c_str(),
+						name.c_str(),
+						isPrivate ? "true" : "false",
+						rtraceLevel.c_str(),
+						(remoteTraceTarget == "NULL" ? NULL : remoteTraceTarget.c_str()),
+						rules.c_str(),
+						rulesSource.c_str(),
+						tags.c_str(),
+						v4mode.c_str(),
+						v6mode.c_str(),
+					};
 
+					PGresult *res = PQexec(conn, "BEGIN");
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error beginnning transaction: %s\n", PQresultErrorMessage(res));
 						PQclear(res);
+						delete config;
+						config = nullptr;
+						continue;
+					}
 
-						// This ugly query exists because when we want to mirror networks to/from
-						// another data store (e.g. FileDB or LFDB) it is possible to get a network
-						// that doesn't exist in Central's database. This does an upsert and sets
-						// the owner_id to the "first" global admin in the user DB if the record
-						// did not previously exist. If the record already exists owner_id is left
-						// unchanged, so owner_id should be left out of the update clause.
-						res = PQexecParams(conn,
-							"INSERT INTO ztc_network (id, creation_time, owner_id, controller_id, capabilities, enable_broadcast, "
-							"last_modified, mtu, multicast_limit, name, private, "
-							"remote_trace_level, remote_trace_target, rules, rules_source, "
-							"tags, v4_assign_mode, v6_assign_mode) VALUES ("
-							"$1, TO_TIMESTAMP($5::double precision/1000), "
-							"(SELECT user_id AS owner_id FROM ztc_global_permissions WHERE authorize = true AND del = true AND modify = true AND read = true LIMIT 1),"
-							"$2, $3, $4, TO_TIMESTAMP($5::double precision/1000), "
-							"$6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) "
-							"ON CONFLICT (id) DO UPDATE set controller_id = EXCLUDED.controller_id, "
-							"capabilities = EXCLUDED.capabilities, enable_broadcast = EXCLUDED.enable_broadcast, "
-							"last_modified = EXCLUDED.last_modified, mtu = EXCLUDED.mtu, "
-							"multicast_limit = EXCLUDED.multicast_limit, name = EXCLUDED.name, "
-							"private = EXCLUDED.private, remote_trace_level = EXCLUDED.remote_trace_level, "
-							"remote_trace_target = EXCLUDED.remote_trace_target, rules = EXCLUDED.rules, "
-							"rules_source = EXCLUDED.rules_source, tags = EXCLUDED.tags, "
-							"v4_assign_mode = EXCLUDED.v4_assign_mode, v6_assign_mode = EXCLUDED.v6_assign_mode",
-							16,
-							NULL,
-							values,
-							NULL,
-							NULL,
-							0);
+					PQclear(res);
 
-						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error updating network record: %s\n", PQresultErrorMessage(res));
-							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
-							continue;
-						}
+					// This ugly query exists because when we want to mirror networks to/from
+					// another data store (e.g. FileDB or LFDB) it is possible to get a network
+					// that doesn't exist in Central's database. This does an upsert and sets
+					// the owner_id to the "first" global admin in the user DB if the record
+					// did not previously exist. If the record already exists owner_id is left
+					// unchanged, so owner_id should be left out of the update clause.
+					res = PQexecParams(conn,
+						"INSERT INTO ztc_network (id, creation_time, owner_id, controller_id, capabilities, enable_broadcast, "
+						"last_modified, mtu, multicast_limit, name, private, "
+						"remote_trace_level, remote_trace_target, rules, rules_source, "
+						"tags, v4_assign_mode, v6_assign_mode) VALUES ("
+						"$1, TO_TIMESTAMP($5::double precision/1000), "
+						"(SELECT user_id AS owner_id FROM ztc_global_permissions WHERE authorize = true AND del = true AND modify = true AND read = true LIMIT 1),"
+						"$2, $3, $4, TO_TIMESTAMP($5::double precision/1000), "
+						"$6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) "
+						"ON CONFLICT (id) DO UPDATE set controller_id = EXCLUDED.controller_id, "
+						"capabilities = EXCLUDED.capabilities, enable_broadcast = EXCLUDED.enable_broadcast, "
+						"last_modified = EXCLUDED.last_modified, mtu = EXCLUDED.mtu, "
+						"multicast_limit = EXCLUDED.multicast_limit, name = EXCLUDED.name, "
+						"private = EXCLUDED.private, remote_trace_level = EXCLUDED.remote_trace_level, "
+						"remote_trace_target = EXCLUDED.remote_trace_target, rules = EXCLUDED.rules, "
+						"rules_source = EXCLUDED.rules_source, tags = EXCLUDED.tags, "
+						"v4_assign_mode = EXCLUDED.v4_assign_mode, v6_assign_mode = EXCLUDED.v6_assign_mode",
+						16,
+						NULL,
+						values,
+						NULL,
+						NULL,
+						0);
 
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error updating network record: %s\n", PQresultErrorMessage(res));
 						PQclear(res);
-				
-						const char *params[1] = {
-							id.c_str()
-						};
-						res = PQexecParams(conn,
-							"DELETE FROM ztc_network_assignment_pool WHERE network_id = $1",
-							1,
-							NULL,
-							params,
-							NULL,
-							NULL,
-							0);
-						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error updating assignment pool: %s\n", PQresultErrorMessage(res));
-							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
-							continue;
-						}
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
+					}
 
+					PQclear(res);
+			
+					const char *params[1] = {
+						id.c_str()
+					};
+					res = PQexecParams(conn,
+						"DELETE FROM ztc_network_assignment_pool WHERE network_id = $1",
+						1,
+						NULL,
+						params,
+						NULL,
+						NULL,
+						0);
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error updating assignment pool: %s\n", PQresultErrorMessage(res));
 						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
+					}
 
-						auto pool = (*config)["ipAssignmentPools"];
-						bool err = false;
-						for (auto i = pool.begin(); i != pool.end(); ++i) {
-							std::string start = (*i)["ipRangeStart"];
-							std::string end = (*i)["ipRangeEnd"];
-							const char *p[3] = {
-								id.c_str(),
-								start.c_str(),
-								end.c_str()
-							};
-
-							res = PQexecParams(conn,
-								"INSERT INTO ztc_network_assignment_pool (network_id, ip_range_start, ip_range_end) "
-								"VALUES ($1, $2, $3)",
-								3,
-								NULL,
-								p,
-								NULL,
-								NULL,
-								0);
-							if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-								fprintf(stderr, "ERROR: Error updating assignment pool: %s\n", PQresultErrorMessage(res));
-								PQclear(res);
-								err = true;
-								break;
-							}
-							PQclear(res);
-						}
-						if (err) {
-							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
-							continue;
-						}
+					PQclear(res);
+
+					auto pool = (*config)["ipAssignmentPools"];
+					bool err = false;
+					for (auto i = pool.begin(); i != pool.end(); ++i) {
+						std::string start = (*i)["ipRangeStart"];
+						std::string end = (*i)["ipRangeEnd"];
+						const char *p[3] = {
+							id.c_str(),
+							start.c_str(),
+							end.c_str()
+						};
 
 						res = PQexecParams(conn,
-							"DELETE FROM ztc_network_route WHERE network_id = $1",
-							1,
+							"INSERT INTO ztc_network_assignment_pool (network_id, ip_range_start, ip_range_end) "
+							"VALUES ($1, $2, $3)",
+							3,
 							NULL,
-							params,
+							p,
 							NULL,
 							NULL,
 							0);
-
 						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error updating routes: %s\n", PQresultErrorMessage(res));
+							fprintf(stderr, "ERROR: Error updating assignment pool: %s\n", PQresultErrorMessage(res));
 							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
-							continue;
+							err = true;
+							break;
 						}
+						PQclear(res);
+					}
+					if (err) {
+						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
+					}
 
+					res = PQexecParams(conn,
+						"DELETE FROM ztc_network_route WHERE network_id = $1",
+						1,
+						NULL,
+						params,
+						NULL,
+						NULL,
+						0);
 
-						auto routes = (*config)["routes"];
-						err = false;
-						for (auto i = routes.begin(); i != routes.end(); ++i) {
-							std::string t = (*i)["target"];
-							std::vector<std::string> target;
-							std::istringstream f(t);
-							std::string s;
-							while(std::getline(f, s, '/')) {
-								target.push_back(s);
-							}
-							if (target.empty() || target.size() != 2) {
-								continue;
-							}
-							std::string targetAddr = target[0];
-							std::string targetBits = target[1];
-							std::string via = "NULL";
-							if (!(*i)["via"].is_null()) {
-								via = (*i)["via"];
-							}
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error updating routes: %s\n", PQresultErrorMessage(res));
+						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
+					}
 
-							const char *p[4] = {
-								id.c_str(),
-								targetAddr.c_str(),
-								targetBits.c_str(),
-								(via == "NULL" ? NULL : via.c_str()),
-							};
-
-							res = PQexecParams(conn,
-								"INSERT INTO ztc_network_route (network_id, address, bits, via) VALUES ($1, $2, $3, $4)",
-								4,
-								NULL,
-								p,
-								NULL,
-								NULL,
-								0);
-
-							if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-								fprintf(stderr, "ERROR: Error updating routes: %s\n", PQresultErrorMessage(res));
-								PQclear(res);
-								err = true;
-								break;
-							}
-							PQclear(res);
+
+					auto routes = (*config)["routes"];
+					err = false;
+					for (auto i = routes.begin(); i != routes.end(); ++i) {
+						std::string t = (*i)["target"];
+						std::vector<std::string> target;
+						std::istringstream f(t);
+						std::string s;
+						while(std::getline(f, s, '/')) {
+							target.push_back(s);
 						}
-						if (err) {
-							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
+						if (target.empty() || target.size() != 2) {
 							continue;
 						}
-						auto dns = (*config)["dns"];
-						std::string domain = dns["domain"];
-						std::stringstream servers;
-						servers << "{";
-						for (auto j = dns["servers"].begin(); j < dns["servers"].end(); ++j) {
-							servers << *j;
-							if ( (j+1) != dns["servers"].end()) {
-								servers << ",";
-							}
+						std::string targetAddr = target[0];
+						std::string targetBits = target[1];
+						std::string via = "NULL";
+						if (!(*i)["via"].is_null()) {
+							via = (*i)["via"];
 						}
-						servers << "}";
 
-						const char *p[3] = {
+						const char *p[4] = {
 							id.c_str(),
-							domain.c_str(),
-							servers.str().c_str()
+							targetAddr.c_str(),
+							targetBits.c_str(),
+							(via == "NULL" ? NULL : via.c_str()),
 						};
 
-						res = PQexecParams(conn, "INSERT INTO ztc_network_dns (network_id, domain, servers) VALUES ($1, $2, $3) ON CONFLICT (network_id) DO UPDATE SET domain = EXCLUDED.domain, servers = EXCLUDED.servers",
-							3,
+						res = PQexecParams(conn,
+							"INSERT INTO ztc_network_route (network_id, address, bits, via) VALUES ($1, $2, $3, $4)",
+							4,
 							NULL,
 							p,
 							NULL,
 							NULL,
 							0);
+
 						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error updating DNS: %s\n", PQresultErrorMessage(res));
+							fprintf(stderr, "ERROR: Error updating routes: %s\n", PQresultErrorMessage(res));
 							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));
 							err = true;
 							break;
 						}
 						PQclear(res);
-
-						res = PQexec(conn, "COMMIT");
-						if (PQresultStatus(res) != PGRES_COMMAND_OK) {
-							fprintf(stderr, "ERROR: Error committing network update: %s\n", PQresultErrorMessage(res));
-							PQclear(res);
-							PQclear(PQexec(conn, "ROLLBACK"));
-							delete config;
-							config = nullptr;
-							continue;
+					}
+					if (err) {
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
+					}
+					auto dns = (*config)["dns"];
+					std::string domain = dns["domain"];
+					std::stringstream servers;
+					servers << "{";
+					for (auto j = dns["servers"].begin(); j < dns["servers"].end(); ++j) {
+						servers << *j;
+						if ( (j+1) != dns["servers"].end()) {
+							servers << ",";
 						}
+					}
+					servers << "}";
+
+					const char *p[3] = {
+						id.c_str(),
+						domain.c_str(),
+						servers.str().c_str()
+					};
+
+					res = PQexecParams(conn, "INSERT INTO ztc_network_dns (network_id, domain, servers) VALUES ($1, $2, $3) ON CONFLICT (network_id) DO UPDATE SET domain = EXCLUDED.domain, servers = EXCLUDED.servers",
+						3,
+						NULL,
+						p,
+						NULL,
+						NULL,
+						0);
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error updating DNS: %s\n", PQresultErrorMessage(res));
 						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));
+						err = true;
+						break;
 					}
+					PQclear(res);
+
+					res = PQexec(conn, "COMMIT");
+					if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+						fprintf(stderr, "ERROR: Error committing network update: %s\n", PQresultErrorMessage(res));
+						PQclear(res);
+						PQclear(PQexec(conn, "ROLLBACK"));
+						delete config;
+						config = nullptr;
+						continue;
+					}
+					PQclear(res);
 
 					const uint64_t nwidInt = OSUtils::jsonIntHex((*config)["nwid"], 0ULL);
 					if (nwidInt) {
@@ -1647,7 +1639,7 @@ void PostgreSQL::commitThread()
 			fprintf(stderr, "ERROR: Error getting objtype: %s\n", e.what());
 		}
 
-		std::this_thread::sleep_for(std::chrono::milliseconds(1));
+		std::this_thread::sleep_for(std::chrono::milliseconds(100));
 	}
 
 	PQfinish(conn);