Skip to content

Commit 281b7d7

Browse files
committed
[FAB-3241] Gossip: Do not send redundant StateInfo
In gossip, whenever the channel related metadata is updated, a "dirty flag" is turned on, and periodically a goroutine disseminates to peers if the dirty flag is turned on. There is a bug that this dirty flag is never turned off. This causes a redundant dissemination of StateInfo. The stateInfo is periodically pulled from peers via a pull mechanism anyway so there is no point in having periodical dissemination and thus the dirty flag should be turned off after dissemination. Change-Id: Ie508df33c28e007e952195faed7837db5641e41a Signed-off-by: Yacov Manevich <[email protected]>
1 parent 5eb5d07 commit 281b7d7

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

gossip/gossip/channel/channel.go

+3
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ func (gc *gossipChannel) publishStateInfo() {
251251
stateInfoMsg := gc.stateInfoMsg
252252
gc.RUnlock()
253253
gc.Gossip(stateInfoMsg)
254+
if len(gc.GetMembership()) > 0 {
255+
atomic.StoreInt32(&gc.shouldGossipStateInfo, int32(0))
256+
}
254257
}
255258

256259
func (gc *gossipChannel) createBlockPuller() pull.Mediator {

gossip/gossip/channel/channel_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,67 @@ func TestChannelGetPeers(t *testing.T) {
10881088
assert.Len(t, gc.GetPeers(), 0)
10891089
}
10901090

1091+
func TestOnDemandGossip(t *testing.T) {
1092+
t.Parallel()
1093+
1094+
// Scenario: update the metadata and ensure only 1 dissemination
1095+
// takes place when membership is not empty
1096+
1097+
cs := &cryptoService{}
1098+
adapter := new(gossipAdapterMock)
1099+
configureAdapter(adapter)
1100+
1101+
gossipedEvents := make(chan struct{})
1102+
1103+
conf := conf
1104+
conf.PublishStateInfoInterval = time.Millisecond * 200
1105+
adapter.On("GetConf").Return(conf)
1106+
adapter.On("GetMembership").Return([]discovery.NetworkMember{})
1107+
adapter.On("Gossip", mock.Anything).Run(func(mock.Arguments) {
1108+
gossipedEvents <- struct{}{}
1109+
})
1110+
gc := NewGossipChannel(pkiIDInOrg1, cs, channelA, adapter, api.JoinChannelMessage(&joinChanMsg{}))
1111+
defer gc.Stop()
1112+
select {
1113+
case <-gossipedEvents:
1114+
assert.Fail(t, "Should not have gossiped because metadata has not been updated yet")
1115+
case <-time.After(time.Millisecond * 500):
1116+
}
1117+
gc.UpdateStateInfo(createStateInfoMsg(0, pkiIDInOrg1, channelA))
1118+
select {
1119+
case <-gossipedEvents:
1120+
case <-time.After(time.Second):
1121+
assert.Fail(t, "Didn't gossip within a timely manner")
1122+
}
1123+
select {
1124+
case <-gossipedEvents:
1125+
case <-time.After(time.Second):
1126+
assert.Fail(t, "Should have gossiped a second time, because membership is empty")
1127+
}
1128+
adapter = new(gossipAdapterMock)
1129+
configureAdapter(adapter, []discovery.NetworkMember{{}}...)
1130+
adapter.On("Gossip", mock.Anything).Run(func(mock.Arguments) {
1131+
gossipedEvents <- struct{}{}
1132+
})
1133+
gc.(*gossipChannel).Adapter = adapter
1134+
select {
1135+
case <-gossipedEvents:
1136+
case <-time.After(time.Second):
1137+
assert.Fail(t, "Should have gossiped a third time")
1138+
}
1139+
select {
1140+
case <-gossipedEvents:
1141+
assert.Fail(t, "Should not have gossiped a fourth time, because dirty flag should have been turned off")
1142+
case <-time.After(time.Millisecond * 500):
1143+
}
1144+
gc.UpdateStateInfo(createStateInfoMsg(1, pkiIDInOrg1, channelA))
1145+
select {
1146+
case <-gossipedEvents:
1147+
case <-time.After(time.Second):
1148+
assert.Fail(t, "Should have gossiped a block now, because got a new StateInfo message")
1149+
}
1150+
}
1151+
10911152
func createDataUpdateMsg(nonce uint64) *proto.SignedGossipMessage {
10921153
return (&proto.GossipMessage{
10931154
Nonce: 0,

0 commit comments

Comments
 (0)