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