{"push_id":911229219,"size":4,"distinct_size":3,"ref":"refs/heads/gossip-broadcast-stall","head":"9ba07bf3d76271c5fcdb53917c96cd91be7ecb8f","before":"e87bcfe8a40357e4e75255bc920e039053c83a5f","commits":[{"sha":"cb6176fd8ac145d48eeaed2d9531587e53bac29a","author":{"email":"ac8fcaf748b7189c49a384a5580dc9e80633299a@gmail.com","name":"Matthias Radestock"},"message":"tweak ProtocolSender API\n\nmake SendProtocolMsg return an error; this isn't used at any call\nsites (yet) but is TRTTD.","distinct":false,"url":"https://api.github.com/repos/weaveworks/weave/commits/cb6176fd8ac145d48eeaed2d9531587e53bac29a"},{"sha":"28d7803deff526238fa2759cba76af76815d4ffd","author":{"email":"ac8fcaf748b7189c49a384a5580dc9e80633299a@gmail.com","name":"Matthias Radestock"},"message":"prevent stalling all broadcasts when single connection is blocked\n\nPreviously a GossipChannel had one GossipSender per broadcast source\npeer. That sender would stall when any of the next-hop connections\nwere blocked, causing broadcasts from the same source peer to be\naccumulate (via GossipData.Merge) locally even though it could be sent\ndown the remaining unblocked connections.\n\nWe can't just have a GossipSender per connection, because broadcast\nmessages carry the source peer and hence only messages from the same\nsource peer can be merged.\n\nThe obvious fix would be for GossipChannels to have a GossipSender per\ncombination of source peer and connection. But that is potentially\nO(n_peers * n_connections) GossipSenders, which in a fully connected\nmesh is O(n_peers^2).\n\nSo instead we do the following:\n\n1. We abandon the concept of GossipData. The gossip interfaces now\ndeal in encoded gossip. This simplifies the interface and its usage\nquite a lot and also makes it more amendable to possible future\nexposure via, say, HTTP.\n\n1. We get rid of the per broadcast source GossipSenders and instead\nsend broadcast messages via the per connection GossipSenders.\n\n2. Instead of single GossipData cell, GossipSenders contain a buffer\nof ProtocolMsgs. This buffer has a dynamic bound - the aggregate size\nof the encoded gossip must not exceed the size of the last complete\ngossip times a certain factor (currently set to 2). When the size is\nexceeded we clear the buffer and when the GossipSender is next ready\nto send it obtains a complete gossip and sends that. More on that\nbelow.\n\n3. GossipSenders shut down when the sending fails. This ensures that\nwe waste no cycles obtaining complete gossip data for dead\nconnections.\n\nThe buffering logic is best considered as a compression scheme. There\nare three types of gossip: complete, differential (\"send on everything\nnew I've learnt from receiving some gossip\") and incremental\n(GossipBroadcast). There is no point buffering more than the complete\ngossip size of differential gossip - we might as well just send the\ncomplete gossip. The situation is the same for incremental gossip\nexcept that replacing a bunch of incremental gossip with complete\ngossip makes propagation less efficient, and can delay convergence,\nsince incremental gossip propagates via optimal broadcast routing\nrather than neighbour gossiping. So we do give up something here. But\nit's better than either having unbounded buffers, or quadratic space\ncomplexity, or simply throwing away gossip when we cannot send it\nimmediately.\n\nNote that we are assuming here that GossipBroadcast and Gossip talk\nabout the same information. That is the case in all current uses, and\ndocumented in the Gossiper API by reference to a \"state\".\n\nThere is one wart here: SurrogateGossiper. It has no idea what\ncomplete gossip sizes are since it does not generate any complete\ngossip. So instead just buffers everything. Which is exactly what it\ndid previously, since it didn't know how to merge GossipData\neither. So no change, really.\n\nWith the per-broadcast-source GossipSenders gone, we can get rid of\nGossipSender gc...\n\nInstead of maintaining a Connection->GossipSender map in the\nGossipChannels - which we then need to gc when connections get closed\n- we keep gossip_channel_name->GossipSender maps in LocalConnections.\n\nAccess to the map is guarded by a separate lock, rather than re-using\nthe LocalConnection lock. This reduces lock contention and risk of\ndeadlock.\n\nIn the GossipSenders, we replace the Stop() method with a signalling\nchannel, i.e. senders stop when that channel gets closed. Handily, the\nLocalConnection.finished channel fits that description. So when a\nLocalConnection's run loop terminates, any existing and future\nassociated GossipSenders will end up terminating too.","distinct":true,"url":"https://api.github.com/repos/weaveworks/weave/commits/28d7803deff526238fa2759cba76af76815d4ffd"},{"sha":"83ce234edcec0f3f989c271c66faf397f69814f2","author":{"email":"ac8fcaf748b7189c49a384a5580dc9e80633299a@gmail.com","name":"Matthias Radestock"},"message":"optimisation: no need to re-encode relayed broadcasts","distinct":true,"url":"https://api.github.com/repos/weaveworks/weave/commits/83ce234edcec0f3f989c271c66faf397f69814f2"},{"sha":"9ba07bf3d76271c5fcdb53917c96cd91be7ecb8f","author":{"email":"ac8fcaf748b7189c49a384a5580dc9e80633299a@gmail.com","name":"Matthias Radestock"},"message":"remove workaround for #1793\n\nThe code now does provide all the necessary guarantees. In particular,\nthe GossipSender.sendAll mark ensures that any complete gossip sent is\nalways at least as up to date as it was when any previous message was\nsent (or dropped).\n\nFixes #1793.","distinct":true,"url":"https://api.github.com/repos/weaveworks/weave/commits/9ba07bf3d76271c5fcdb53917c96cd91be7ecb8f"}]}