mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-31 20:21:56 +00:00
Reactors can be stopped or started at any time.
This commit is contained in:
123
p2p/switch.go
123
p2p/switch.go
@@ -29,89 +29,100 @@ or more `Channels`. So while sending outgoing messages is typically performed o
|
||||
incoming messages are received on the reactor.
|
||||
*/
|
||||
type Switch struct {
|
||||
reactors []Reactor
|
||||
chainId string
|
||||
reactors map[string]Reactor
|
||||
chDescs []*ChannelDescriptor
|
||||
reactorsByCh map[byte]Reactor
|
||||
peers *PeerSet
|
||||
dialing *CMap
|
||||
listeners *CMap // listenerName -> chan interface{}
|
||||
quit chan struct{}
|
||||
started uint32
|
||||
stopped uint32
|
||||
chainId string
|
||||
listeners *CMap // listenerName -> chan interface{}
|
||||
running uint32 // atomic
|
||||
}
|
||||
|
||||
var (
|
||||
ErrSwitchStopped = errors.New("Switch already stopped")
|
||||
ErrSwitchDuplicatePeer = errors.New("Duplicate peer")
|
||||
ErrSwitchStopped = errors.New("Switch stopped")
|
||||
)
|
||||
|
||||
const (
|
||||
peerDialTimeoutSeconds = 3
|
||||
)
|
||||
|
||||
func NewSwitch(reactors []Reactor) *Switch {
|
||||
|
||||
// Validate the reactors. no two reactors can share the same channel.
|
||||
chDescs := []*ChannelDescriptor{}
|
||||
reactorsByCh := make(map[byte]Reactor)
|
||||
for _, reactor := range reactors {
|
||||
reactorChannels := reactor.GetChannels()
|
||||
for _, chDesc := range reactorChannels {
|
||||
chId := chDesc.Id
|
||||
if reactorsByCh[chId] != nil {
|
||||
panic(fmt.Sprintf("Channel %X has multiple reactors %v & %v", chId, reactorsByCh[chId], reactor))
|
||||
}
|
||||
chDescs = append(chDescs, chDesc)
|
||||
reactorsByCh[chId] = reactor
|
||||
}
|
||||
}
|
||||
func NewSwitch() *Switch {
|
||||
|
||||
sw := &Switch{
|
||||
reactors: reactors,
|
||||
chDescs: chDescs,
|
||||
reactorsByCh: reactorsByCh,
|
||||
chainId: "",
|
||||
reactors: make(map[string]Reactor),
|
||||
chDescs: make([]*ChannelDescriptor, 0),
|
||||
reactorsByCh: make(map[byte]Reactor),
|
||||
peers: NewPeerSet(),
|
||||
dialing: NewCMap(),
|
||||
listeners: NewCMap(),
|
||||
quit: make(chan struct{}),
|
||||
stopped: 0,
|
||||
running: 0,
|
||||
}
|
||||
|
||||
return sw
|
||||
}
|
||||
|
||||
func (sw *Switch) Start() {
|
||||
if atomic.CompareAndSwapUint32(&sw.started, 0, 1) {
|
||||
log.Info("Starting Switch")
|
||||
for _, reactor := range sw.reactors {
|
||||
reactor.Start(sw)
|
||||
func (sw *Switch) SetChainId(hash []byte, network string) {
|
||||
sw.chainId = hex.EncodeToString(hash) + "-" + network
|
||||
}
|
||||
|
||||
func (sw *Switch) AddReactor(name string, reactor Reactor) {
|
||||
// Validate the reactor.
|
||||
// No two reactors can share the same channel.
|
||||
reactorChannels := reactor.GetChannels()
|
||||
for _, chDesc := range reactorChannels {
|
||||
chId := chDesc.Id
|
||||
if sw.reactorsByCh[chId] != nil {
|
||||
panic(fmt.Sprintf("Channel %X has multiple reactors %v & %v", chId, sw.reactorsByCh[chId], reactor))
|
||||
}
|
||||
sw.chDescs = append(sw.chDescs, chDesc)
|
||||
sw.reactorsByCh[chId] = reactor
|
||||
}
|
||||
sw.reactors[name] = reactor
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
func (sw *Switch) StartReactor(name string) {
|
||||
atomic.StoreUint32(&sw.running, 1)
|
||||
sw.reactors[name].Start(sw)
|
||||
}
|
||||
|
||||
// Convenience function
|
||||
func (sw *Switch) StartAll() {
|
||||
atomic.StoreUint32(&sw.running, 1)
|
||||
for _, reactor := range sw.reactors {
|
||||
reactor.Start(sw)
|
||||
}
|
||||
}
|
||||
|
||||
func (sw *Switch) Stop() {
|
||||
if atomic.CompareAndSwapUint32(&sw.stopped, 0, 1) {
|
||||
log.Info("Stopping Switch")
|
||||
close(sw.quit)
|
||||
// Stop each peer.
|
||||
for _, peer := range sw.peers.List() {
|
||||
peer.stop()
|
||||
}
|
||||
sw.peers = NewPeerSet()
|
||||
// Stop all reactors.
|
||||
for _, reactor := range sw.reactors {
|
||||
reactor.Stop()
|
||||
}
|
||||
func (sw *Switch) StopReactor(name string) {
|
||||
sw.reactors[name].Stop()
|
||||
}
|
||||
|
||||
// Convenience function
|
||||
// Not goroutine safe
|
||||
func (sw *Switch) StopAll() {
|
||||
atomic.StoreUint32(&sw.running, 0)
|
||||
// Stop each peer.
|
||||
for _, peer := range sw.peers.List() {
|
||||
peer.stop()
|
||||
}
|
||||
sw.peers = NewPeerSet()
|
||||
// Stop all reactors.
|
||||
for _, reactor := range sw.reactors {
|
||||
reactor.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
func (sw *Switch) Reactors() []Reactor {
|
||||
// Not goroutine safe
|
||||
func (sw *Switch) Reactors() map[string]Reactor {
|
||||
return sw.reactors
|
||||
}
|
||||
|
||||
func (sw *Switch) AddPeerWithConnection(conn net.Conn, outbound bool) (*Peer, error) {
|
||||
if atomic.LoadUint32(&sw.stopped) == 1 {
|
||||
if atomic.LoadUint32(&sw.running) == 0 {
|
||||
return nil, ErrSwitchStopped
|
||||
}
|
||||
|
||||
@@ -125,12 +136,12 @@ func (sw *Switch) AddPeerWithConnection(conn net.Conn, outbound bool) (*Peer, er
|
||||
return nil, ErrSwitchDuplicatePeer
|
||||
}
|
||||
|
||||
// Start the peer
|
||||
go peer.start()
|
||||
|
||||
// Notify listeners.
|
||||
sw.doAddPeer(peer)
|
||||
|
||||
// Start the peer
|
||||
go peer.start()
|
||||
|
||||
// Send handshake
|
||||
msg := &pexHandshakeMessage{ChainId: sw.chainId}
|
||||
peer.Send(PexChannel, msg)
|
||||
@@ -139,7 +150,7 @@ func (sw *Switch) AddPeerWithConnection(conn net.Conn, outbound bool) (*Peer, er
|
||||
}
|
||||
|
||||
func (sw *Switch) DialPeerWithAddress(addr *NetAddress) (*Peer, error) {
|
||||
if atomic.LoadUint32(&sw.stopped) == 1 {
|
||||
if atomic.LoadUint32(&sw.running) == 0 {
|
||||
return nil, ErrSwitchStopped
|
||||
}
|
||||
|
||||
@@ -168,7 +179,7 @@ func (sw *Switch) IsDialing(addr *NetAddress) bool {
|
||||
// trying to send for defaultSendTimeoutSeconds. Returns a channel
|
||||
// which receives success values for each attempted send (false if times out)
|
||||
func (sw *Switch) Broadcast(chId byte, msg interface{}) chan bool {
|
||||
if atomic.LoadUint32(&sw.stopped) == 1 {
|
||||
if atomic.LoadUint32(&sw.running) == 0 {
|
||||
return nil
|
||||
}
|
||||
successChan := make(chan bool, len(sw.peers.List()))
|
||||
@@ -223,16 +234,12 @@ func (sw *Switch) StopPeerGracefully(peer *Peer) {
|
||||
sw.doRemovePeer(peer, nil)
|
||||
}
|
||||
|
||||
func (sw *Switch) SetChainId(hash []byte, network string) {
|
||||
sw.chainId = hex.EncodeToString(hash) + "-" + network
|
||||
}
|
||||
|
||||
func (sw *Switch) IsListening() bool {
|
||||
return sw.listeners.Size() > 0
|
||||
}
|
||||
|
||||
func (sw *Switch) doAddPeer(peer *Peer) {
|
||||
for _, reactor := range sw.reactors {
|
||||
for name, reactor := range sw.reactors {
|
||||
reactor.AddPeer(peer)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user