github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/gossip/election/adapter.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package election 8 9 import ( 10 "bytes" 11 "sync" 12 "time" 13 14 "github.com/hyperledger/fabric/gossip/common" 15 "github.com/hyperledger/fabric/gossip/discovery" 16 "github.com/hyperledger/fabric/gossip/util" 17 proto "github.com/hyperledger/fabric/protos/gossip" 18 "github.com/op/go-logging" 19 ) 20 21 type msgImpl struct { 22 msg *proto.GossipMessage 23 } 24 25 func (mi *msgImpl) SenderID() peerID { 26 return mi.msg.GetLeadershipMsg().PkiId 27 } 28 29 func (mi *msgImpl) IsProposal() bool { 30 return !mi.IsDeclaration() 31 } 32 33 func (mi *msgImpl) IsDeclaration() bool { 34 return mi.msg.GetLeadershipMsg().IsDeclaration 35 } 36 37 type peerImpl struct { 38 member discovery.NetworkMember 39 } 40 41 func (pi *peerImpl) ID() peerID { 42 return peerID(pi.member.PKIid) 43 } 44 45 type gossip interface { 46 // Peers returns the NetworkMembers considered alive 47 Peers() []discovery.NetworkMember 48 49 // Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate. 50 // If passThrough is false, the messages are processed by the gossip layer beforehand. 51 // If passThrough is true, the gossip layer doesn't intervene and the messages 52 // can be used to send a reply back to the sender 53 Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage) 54 55 // Gossip sends a message to other peers to the network 56 Gossip(msg *proto.GossipMessage) 57 } 58 59 type adapterImpl struct { 60 gossip gossip 61 selfPKIid common.PKIidType 62 63 incTime uint64 64 seqNum uint64 65 66 channel common.ChainID 67 68 logger *logging.Logger 69 70 doneCh chan struct{} 71 stopOnce *sync.Once 72 } 73 74 // NewAdapter creates new leader election adapter 75 func NewAdapter(gossip gossip, pkiid common.PKIidType, channel common.ChainID) LeaderElectionAdapter { 76 return &adapterImpl{ 77 gossip: gossip, 78 selfPKIid: pkiid, 79 80 incTime: uint64(time.Now().UnixNano()), 81 seqNum: uint64(0), 82 83 channel: channel, 84 85 logger: util.GetLogger(util.LoggingElectionModule, ""), 86 87 doneCh: make(chan struct{}), 88 stopOnce: &sync.Once{}, 89 } 90 } 91 92 func (ai *adapterImpl) Gossip(msg Msg) { 93 ai.gossip.Gossip(msg.(*msgImpl).msg) 94 } 95 96 func (ai *adapterImpl) Accept() <-chan Msg { 97 adapterCh, _ := ai.gossip.Accept(func(message interface{}) bool { 98 // Get only leadership org and channel messages 99 return message.(*proto.GossipMessage).Tag == proto.GossipMessage_CHAN_AND_ORG && 100 message.(*proto.GossipMessage).IsLeadershipMsg() && 101 bytes.Equal(message.(*proto.GossipMessage).Channel, ai.channel) 102 }, false) 103 104 msgCh := make(chan Msg) 105 106 go func(inCh <-chan *proto.GossipMessage, outCh chan Msg, stopCh chan struct{}) { 107 for { 108 select { 109 case <-stopCh: 110 return 111 case gossipMsg, ok := <-inCh: 112 if ok { 113 outCh <- &msgImpl{gossipMsg} 114 } else { 115 return 116 } 117 } 118 } 119 }(adapterCh, msgCh, ai.doneCh) 120 return msgCh 121 } 122 123 func (ai *adapterImpl) CreateMessage(isDeclaration bool) Msg { 124 ai.seqNum++ 125 seqNum := ai.seqNum 126 127 leadershipMsg := &proto.LeadershipMessage{ 128 PkiId: ai.selfPKIid, 129 IsDeclaration: isDeclaration, 130 Timestamp: &proto.PeerTime{ 131 IncNum: ai.incTime, 132 SeqNum: seqNum, 133 }, 134 } 135 136 msg := &proto.GossipMessage{ 137 Nonce: 0, 138 Tag: proto.GossipMessage_CHAN_AND_ORG, 139 Content: &proto.GossipMessage_LeadershipMsg{LeadershipMsg: leadershipMsg}, 140 Channel: ai.channel, 141 } 142 return &msgImpl{msg} 143 } 144 145 func (ai *adapterImpl) Peers() []Peer { 146 peers := ai.gossip.Peers() 147 148 var res []Peer 149 for _, peer := range peers { 150 res = append(res, &peerImpl{peer}) 151 } 152 153 return res 154 } 155 156 func (ai *adapterImpl) Stop() { 157 stopFunc := func() { 158 close(ai.doneCh) 159 } 160 ai.stopOnce.Do(stopFunc) 161 }