-
Notifications
You must be signed in to change notification settings - Fork 0
/
peerinfo.go
135 lines (124 loc) · 2.82 KB
/
peerinfo.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
package manage
import (
"context"
"sync"
"sync/atomic"
"time"
"github.com/turingchain2020/turingchain/queue"
"github.com/turingchain2020/turingchain/types"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
)
// PeerInfoManager peer info manager
type PeerInfoManager struct {
ctx context.Context
peerInfo sync.Map
client queue.Client
host host.Host
maxHeight int64
}
type peerStoreInfo struct {
storeTime time.Time
peer *types.Peer
}
// NewPeerInfoManager new peer info manager
func NewPeerInfoManager(ctx context.Context, host host.Host, cli queue.Client) *PeerInfoManager {
peerInfoManage := &PeerInfoManager{
ctx: ctx,
client: cli,
host: host,
}
go peerInfoManage.start()
return peerInfoManage
}
// Refresh refreshes peer info
func (p *PeerInfoManager) Refresh(peer *types.Peer) {
if peer == nil {
return
}
storeInfo := peerStoreInfo{
storeTime: time.Now(),
peer: peer,
}
p.peerInfo.Store(peer.Name, &storeInfo)
if peer.GetHeader().GetHeight() > atomic.LoadInt64(&p.maxHeight) {
atomic.StoreInt64(&p.maxHeight, peer.GetHeader().GetHeight())
}
}
// Fetch returns info of given peer
func (p *PeerInfoManager) Fetch(pid peer.ID) *types.Peer {
key := pid.Pretty()
v, ok := p.peerInfo.Load(key)
if !ok {
return nil
}
if info, ok := v.(*peerStoreInfo); ok {
if time.Since(info.storeTime) > time.Minute {
p.peerInfo.Delete(key)
return nil
}
return info.peer
}
return nil
}
// FetchAll returns all peers info
func (p *PeerInfoManager) FetchAll() []*types.Peer {
var peers []*types.Peer
var self *types.Peer
p.peerInfo.Range(func(key, value interface{}) bool {
info := value.(*peerStoreInfo)
if time.Since(info.storeTime) > time.Minute {
p.peerInfo.Delete(key)
return true
}
if key.(string) == p.host.ID().Pretty() {
self = info.peer
return true
}
peers = append(peers, info.peer)
return true
})
if self != nil {
peers = append(peers, self)
}
return peers
}
// PeerHeight returns block height of given peer
func (p *PeerInfoManager) PeerHeight(pid peer.ID) int64 {
v, ok := p.peerInfo.Load(pid.Pretty())
if !ok {
return -1
}
info, ok := v.(*peerStoreInfo)
if !ok {
return -1
}
if info.peer.GetHeader() == nil {
return -1
}
return info.peer.GetHeader().Height
}
// PeerMaxHeight returns max block height of all connected peers.
func (p *PeerInfoManager) PeerMaxHeight() int64 {
return atomic.LoadInt64(&p.maxHeight)
}
func (p *PeerInfoManager) start() {
for {
select {
case <-p.ctx.Done():
return
case <-time.After(time.Second * 30):
p.prune()
}
}
}
func (p *PeerInfoManager) prune() {
p.peerInfo.Range(func(key interface{}, value interface{}) bool {
info := value.(*peerStoreInfo)
if time.Since(info.storeTime) > time.Minute {
p.peerInfo.Delete(key)
return true
}
return true
})
}