Eliminate some poorly thought out optimizations from the netconf/controller interaction,

and go ahead and bump version to 1.0.4.

For a while in 1.0.3 -dev I was trying to optimize out repeated network controller
requests by using a ratcheting mechanism. If the client received a network config
that was indeed different from the one it had, it would respond by instantlly
requesting it again.

Not sure what I was thinking. It's fundamentally unsafe to respond to a message
with another message of the same type -- it risks a race condition. In this case
that's exactly what could happen.

It just isn't worth the added complexity to avoid a tiny, tiny amount of network
overhead, so I've taken this whole path out.

A few extra bytes every two minutes isn't worth fretting about, but as I recall
the reason for this optimization was to save CPU on the controller. This can be
achieved by just caching responses in memory *there* and serving those same
responses back out if they haven't changed.

I think I developed that 'ratcheting' stuff before I went full time on this. It's
hard to develop stuff like this without hours of sustained focus.
This commit is contained in:
Adam Ierymenko 2015-07-23 09:50:10 -07:00
parent e2a2993b18
commit 3ba54c7e35
7 changed files with 55 additions and 80 deletions

View file

@ -392,28 +392,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
const unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN);
const std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen);
if (dict.length()) {
if (nw->setConfiguration(Dictionary(dict)) == 2) { // 2 == accepted and actually new
/* If this configuration was indeed new, we do another
* controller request with its revision. We do this in
* order to (a) tell the network controller we got it (it
* won't send a duplicate if ts == current), and (b)
* get another one if the controller is changing rapidly
* until we finally have the final version.
*
* Note that we don't do this for network controllers with
* versions <= 1.0.3, since those regenerate a new controller
* with a new revision every time. In that case this double
* confirmation would create a race condition. */
const SharedPtr<NetworkConfig> nc(nw->config2());
if ((peer->atLeastVersion(1,0,3))&&(nc)&&(nc->revision() > 0)) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append((uint64_t)nw->id());
outp.append((uint16_t)0); // no meta-data
outp.append((uint64_t)nc->revision());
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
}
}
nw->setConfiguration(Dictionary(dict));
TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str());
}
}
@ -692,6 +671,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
if (RR->localNetworkController) {
Dictionary netconf;
switch(RR->localNetworkController->doNetworkConfigRequest((h > 0) ? InetAddress() : _remoteAddress,RR->identity,peer->identity(),nwid,metaData,haveRevision,netconf)) {
case NetworkController::NETCONF_QUERY_OK: {
const std::string netconfStr(netconf.toString());
if (netconfStr.length() > 0xffff) { // sanity check since field ix 16-bit
@ -712,8 +692,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
}
}
} break;
case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: // nothing to do -- netconf has not changed
break;
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
@ -723,6 +702,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
} break;
case NetworkController::NETCONF_QUERY_ACCESS_DENIED: {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
@ -732,12 +712,15 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
} break;
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR:
TRACE("NETWORK_CONFIG_REQUEST failed: internal error: %s",netconf.get("error","(unknown)").c_str());
break;
default:
TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()");
break;
}
} else {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);