Skip to content

Commit 5dbb05a

Browse files
[FAB-2779] Clear data in discovery
Removing expired alive msgs from discovery module msg store and references to those messages inside discovery module itself Change-Id: I76579209d0ff67e48d230864fff7a867217b84c6 Signed-off-by: Gennady Laventman <[email protected]>
1 parent aa84135 commit 5dbb05a

File tree

2 files changed

+127
-7
lines changed

2 files changed

+127
-7
lines changed

gossip/discovery/discovery_impl.go

+38-7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
)
3636

3737
const defaultHelloInterval = time.Duration(5) * time.Second
38+
const msgExpirationFactor = 20
3839

3940
var aliveExpirationCheckInterval time.Duration
4041
var maxConnectionAttempts = 120
@@ -105,7 +106,6 @@ func NewDiscoveryService(bootstrapPeers []string, self NetworkMember, comm CommS
105106
id2Member: make(map[string]*NetworkMember),
106107
aliveMembership: util.NewMembershipStore(),
107108
deadMembership: util.NewMembershipStore(),
108-
msgStore: msgstore.NewMessageStore(proto.NewGossipMessageComparator(0), func(m interface{}) {}),
109109
crypt: crypt,
110110
comm: comm,
111111
lock: &sync.RWMutex{},
@@ -115,6 +115,26 @@ func NewDiscoveryService(bootstrapPeers []string, self NetworkMember, comm CommS
115115
disclosurePolicy: disPol,
116116
}
117117

118+
policy := proto.NewGossipMessageComparator(0)
119+
trigger := func(m interface{}) {}
120+
aliveMsgTTL := getAliveExpirationTimeout() * msgExpirationFactor
121+
externalLock := func() { d.lock.Lock() }
122+
externalUnlock := func() { d.lock.Unlock() }
123+
callback := func(m interface{}) {
124+
msg := m.(*proto.SignedGossipMessage)
125+
if !msg.IsAliveMsg() {
126+
return
127+
}
128+
id := msg.GetAliveMsg().Membership.PkiId
129+
d.aliveMembership.Remove(id)
130+
d.deadMembership.Remove(id)
131+
delete(d.id2Member, string(id))
132+
delete(d.deadLastTS, string(id))
133+
delete(d.aliveLastTS, string(id))
134+
}
135+
136+
d.msgStore = msgstore.NewMessageStoreExpirable(policy, trigger, aliveMsgTTL, externalLock, externalUnlock, callback)
137+
118138
go d.periodicalSendAlive()
119139
go d.periodicalCheckAlive()
120140
go d.handleMessages()
@@ -308,7 +328,9 @@ func (d *gossipDiscoveryImpl) handleMsgFromComm(m *proto.SignedGossipMessage) {
308328
return
309329
}
310330

311-
d.handleAliveMessage(selfInfoGossipMsg)
331+
if d.msgStore.CheckValid(m) {
332+
d.handleAliveMessage(selfInfoGossipMsg)
333+
}
312334

313335
var internalEndpoint string
314336
if m.Envelope.SecretEnvelope != nil {
@@ -323,13 +345,13 @@ func (d *gossipDiscoveryImpl) handleMsgFromComm(m *proto.SignedGossipMessage) {
323345
}
324346

325347
if m.IsAliveMsg() {
326-
added := d.msgStore.Add(m)
327-
if !added {
348+
349+
if !d.msgStore.Add(m) {
328350
return
329351
}
330-
d.comm.Gossip(m)
331-
332352
d.handleAliveMessage(m)
353+
354+
d.comm.Gossip(m)
333355
return
334356
}
335357

@@ -345,7 +367,10 @@ func (d *gossipDiscoveryImpl) handleMsgFromComm(m *proto.SignedGossipMessage) {
345367
return
346368
}
347369

348-
d.handleAliveMessage(am)
370+
if d.msgStore.CheckValid(m) {
371+
d.handleAliveMessage(am)
372+
}
373+
349374
}
350375

351376
for _, env := range memResp.Dead {
@@ -359,6 +384,11 @@ func (d *gossipDiscoveryImpl) handleMsgFromComm(m *proto.SignedGossipMessage) {
359384
continue
360385
}
361386

387+
if !d.msgStore.CheckValid(m) {
388+
//Newer alive message exist
389+
return
390+
}
391+
362392
newDeadMembers := []*proto.SignedGossipMessage{}
363393
d.lock.RLock()
364394
if _, known := d.id2Member[string(dm.GetAliveMsg().Membership.PkiId)]; !known {
@@ -902,6 +932,7 @@ func (d *gossipDiscoveryImpl) Stop() {
902932
defer d.logger.Info("Stopped")
903933
d.logger.Info("Stopping")
904934
atomic.StoreInt32(&d.toDieFlag, int32(1))
935+
d.msgStore.Stop()
905936
d.toDieChan <- struct{}{}
906937
}
907938

gossip/discovery/discovery_test.go

+89
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,96 @@ func TestFilterOutLocalhost(t *testing.T) {
790790
assert.NotEqual(t, endpoints[2], endpoints[0])
791791
}
792792

793+
func TestMsgStoreExpiration(t *testing.T) {
794+
t.Parallel()
795+
nodeNum := 4
796+
bootPeers := []string{bootPeer(12611), bootPeer(12612)}
797+
instances := []*gossipInstance{}
798+
799+
inst := createDiscoveryInstance(12611, "d1", bootPeers)
800+
instances = append(instances, inst)
801+
802+
inst = createDiscoveryInstance(12612, "d2", bootPeers)
803+
instances = append(instances, inst)
804+
805+
for i := 3; i <= nodeNum; i++ {
806+
id := fmt.Sprintf("d%d", i)
807+
inst = createDiscoveryInstance(12610+i, id, bootPeers)
808+
instances = append(instances, inst)
809+
}
810+
811+
assertMembership(t, instances, nodeNum-1)
812+
813+
waitUntilOrFailBlocking(t, instances[nodeNum-1].Stop)
814+
waitUntilOrFailBlocking(t, instances[nodeNum-2].Stop)
815+
816+
assertMembership(t, instances, nodeNum-3)
817+
818+
checkMessages := func() bool {
819+
for _, inst := range instances[:len(instances)-2] {
820+
for _, downInst := range instances[len(instances)-2:] {
821+
downCastInst := inst.Discovery.(*gossipDiscoveryImpl)
822+
downCastInst.lock.RLock()
823+
if _, exist := downCastInst.aliveLastTS[string(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid)]; exist {
824+
downCastInst.lock.RUnlock()
825+
return false
826+
}
827+
if _, exist := downCastInst.deadLastTS[string(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid)]; exist {
828+
downCastInst.lock.RUnlock()
829+
return false
830+
}
831+
if _, exist := downCastInst.id2Member[string(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid)]; exist {
832+
downCastInst.lock.RUnlock()
833+
return false
834+
}
835+
if downCastInst.aliveMembership.MsgByID(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid) != nil {
836+
downCastInst.lock.RUnlock()
837+
return false
838+
}
839+
if downCastInst.deadMembership.MsgByID(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid) != nil {
840+
downCastInst.lock.RUnlock()
841+
return false
842+
}
843+
downCastInst.lock.RUnlock()
844+
}
845+
}
846+
return true
847+
}
848+
849+
waitUntilTimeoutOrFail(t, checkMessages, timeout*2)
850+
851+
assertMembership(t, instances[:len(instances)-2], nodeNum-3)
852+
853+
peerToResponse := &NetworkMember{
854+
Metadata: []byte{},
855+
PKIid: []byte(fmt.Sprintf("localhost:%d", 12612)),
856+
Endpoint: fmt.Sprintf("localhost:%d", 12612),
857+
InternalEndpoint: fmt.Sprintf("localhost:%d", 12612),
858+
}
859+
860+
downCastInstance := instances[0].Discovery.(*gossipDiscoveryImpl)
861+
memResp := downCastInstance.createMembershipResponse(peerToResponse)
862+
863+
downCastInstance.comm.SendToPeer(peerToResponse, (&proto.GossipMessage{
864+
Tag: proto.GossipMessage_EMPTY,
865+
Nonce: uint64(0),
866+
Content: &proto.GossipMessage_MemRes{
867+
MemRes: memResp,
868+
},
869+
}).NoopSign())
870+
871+
time.Sleep(getAliveExpirationTimeout())
872+
873+
assert.True(t, checkMessages(), "Validating lost message with already dead and expired nodes failed")
874+
875+
stopInstances(t, instances[:len(instances)-2])
876+
}
877+
793878
func waitUntilOrFail(t *testing.T, pred func() bool) {
879+
waitUntilTimeoutOrFail(t, pred, timeout)
880+
}
881+
882+
func waitUntilTimeoutOrFail(t *testing.T, pred func() bool, timeout time.Duration) {
794883
start := time.Now()
795884
limit := start.UnixNano() + timeout.Nanoseconds()
796885
for time.Now().UnixNano() < limit {

0 commit comments

Comments
 (0)