@@ -27,27 +27,30 @@ var log = logging.Logger("connmgr")
27
27
//
28
28
// See configuration parameters in NewConnManager.
29
29
type BasicConnMgr struct {
30
- highWater int
31
- lowWater int
32
- connCount int32
33
- gracePeriod time.Duration
34
- segments segments
30
+ * decayer
31
+
32
+ cfg * BasicConnManagerConfig
33
+ segments segments
35
34
36
35
plk sync.RWMutex
37
36
protected map [peer.ID ]map [string ]struct {}
38
37
39
- trimTrigger chan chan <- struct {}
38
+ // channel-based semaphore that enforces only a single trim is in progress
39
+ trimRunningCh chan struct {}
40
+ trimTrigger chan chan <- struct {}
41
+ connCount int32
40
42
41
43
lastTrimMu sync.RWMutex
42
44
lastTrim time.Time
43
45
44
- silencePeriod time.Duration
45
-
46
46
ctx context.Context
47
47
cancel func ()
48
48
}
49
49
50
- var _ connmgr.ConnManager = (* BasicConnMgr )(nil )
50
+ var (
51
+ _ connmgr.ConnManager = (* BasicConnMgr )(nil )
52
+ _ connmgr.Decayer = (* BasicConnMgr )(nil )
53
+ )
51
54
52
55
type segment struct {
53
56
sync.Mutex
@@ -80,6 +83,7 @@ func (s *segment) tagInfoFor(p peer.ID) *peerInfo {
80
83
firstSeen : time .Now (), // this timestamp will be updated when the first Connected notification arrives.
81
84
temp : true ,
82
85
tags : make (map [string ]int ),
86
+ decaying : make (map [* decayingTag ]* connmgr.DecayingValue ),
83
87
conns : make (map [network.Conn ]time.Time ),
84
88
}
85
89
s .peers [p ] = pi
@@ -92,15 +96,32 @@ func (s *segment) tagInfoFor(p peer.ID) *peerInfo {
92
96
// their connections terminated) until 'low watermark' peers remain.
93
97
// * grace is the amount of time a newly opened connection is given before it becomes
94
98
// subject to pruning.
95
- func NewConnManager (low , hi int , grace time.Duration ) * BasicConnMgr {
99
+ func NewConnManager (low , hi int , grace time.Duration , opts ... Option ) * BasicConnMgr {
96
100
ctx , cancel := context .WithCancel (context .Background ())
97
- cm := & BasicConnMgr {
101
+
102
+ cfg := & BasicConnManagerConfig {
98
103
highWater : hi ,
99
104
lowWater : low ,
100
105
gracePeriod : grace ,
106
+ silencePeriod : SilencePeriod ,
107
+ }
108
+
109
+ for _ , o := range opts {
110
+ // TODO we're ignoring errors from options because we have no way to
111
+ // return them, or otherwise act on them.
112
+ _ = o (cfg )
113
+ }
114
+
115
+ if cfg .decayer == nil {
116
+ // Set the default decayer config.
117
+ cfg .decayer = (& DecayerCfg {}).WithDefaults ()
118
+ }
119
+
120
+ cm := & BasicConnMgr {
121
+ cfg : cfg ,
122
+ trimRunningCh : make (chan struct {}, 1 ),
101
123
trimTrigger : make (chan chan <- struct {}),
102
124
protected : make (map [peer.ID ]map [string ]struct {}, 16 ),
103
- silencePeriod : SilencePeriod ,
104
125
ctx : ctx ,
105
126
cancel : cancel ,
106
127
segments : func () (ret segments ) {
@@ -113,11 +134,17 @@ func NewConnManager(low, hi int, grace time.Duration) *BasicConnMgr {
113
134
}(),
114
135
}
115
136
137
+ decay , _ := NewDecayer (cfg .decayer , cm )
138
+ cm .decayer = decay
139
+
116
140
go cm .background ()
117
141
return cm
118
142
}
119
143
120
144
func (cm * BasicConnMgr ) Close () error {
145
+ if err := cm .decayer .Close (); err != nil {
146
+ return err
147
+ }
121
148
cm .cancel ()
122
149
return nil
123
150
}
@@ -151,10 +178,12 @@ func (cm *BasicConnMgr) Unprotect(id peer.ID, tag string) (protected bool) {
151
178
152
179
// peerInfo stores metadata for a given peer.
153
180
type peerInfo struct {
154
- id peer.ID
155
- tags map [string ]int // value for each tag
156
- value int // cached sum of all tag values
157
- temp bool // this is a temporary entry holding early tags, and awaiting connections
181
+ id peer.ID
182
+ tags map [string ]int // value for each tag
183
+ decaying map [* decayingTag ]* connmgr.DecayingValue // decaying tags
184
+
185
+ value int // cached sum of all tag values
186
+ temp bool // this is a temporary entry holding early tags, and awaiting connections
158
187
159
188
conns map [network.Conn ]time.Time // start time of each connection
160
189
@@ -199,7 +228,7 @@ func (cm *BasicConnMgr) background() {
199
228
var waiting chan <- struct {}
200
229
select {
201
230
case <- ticker .C :
202
- if atomic .LoadInt32 (& cm .connCount ) < int32 (cm .highWater ) {
231
+ if atomic .LoadInt32 (& cm .connCount ) < int32 (cm .cfg . highWater ) {
203
232
// Below high water, skip.
204
233
continue
205
234
}
@@ -235,7 +264,7 @@ func (cm *BasicConnMgr) trim() {
235
264
cm .lastTrimMu .RUnlock ()
236
265
237
266
// skip this attempt to trim if the last one just took place.
238
- if time .Since (lastTrim ) < cm .silencePeriod {
267
+ if time .Since (lastTrim ) < cm .cfg . silencePeriod {
239
268
return
240
269
}
241
270
@@ -256,21 +285,21 @@ func (cm *BasicConnMgr) trim() {
256
285
// getConnsToClose runs the heuristics described in TrimOpenConns and returns the
257
286
// connections to close.
258
287
func (cm * BasicConnMgr ) getConnsToClose () []network.Conn {
259
- if cm .lowWater == 0 || cm .highWater == 0 {
288
+ if cm .cfg . lowWater == 0 || cm . cfg .highWater == 0 {
260
289
// disabled
261
290
return nil
262
291
}
263
292
264
293
nconns := int (atomic .LoadInt32 (& cm .connCount ))
265
- if nconns <= cm .lowWater {
294
+ if nconns <= cm .cfg . lowWater {
266
295
log .Info ("open connection count below limit" )
267
296
return nil
268
297
}
269
298
270
299
npeers := cm .segments .countPeers ()
271
300
candidates := make ([]* peerInfo , 0 , npeers )
272
301
ncandidates := 0
273
- gracePeriodStart := time .Now ().Add (- cm .gracePeriod )
302
+ gracePeriodStart := time .Now ().Add (- cm .cfg . gracePeriod )
274
303
275
304
cm .plk .RLock ()
276
305
for _ , s := range cm .segments {
@@ -291,7 +320,7 @@ func (cm *BasicConnMgr) getConnsToClose() []network.Conn {
291
320
}
292
321
cm .plk .RUnlock ()
293
322
294
- if ncandidates < cm .lowWater {
323
+ if ncandidates < cm .cfg . lowWater {
295
324
log .Info ("open connection count above limit but too many are in the grace period" )
296
325
// We have too many connections but fewer than lowWater
297
326
// connections out of the grace period.
@@ -311,7 +340,7 @@ func (cm *BasicConnMgr) getConnsToClose() []network.Conn {
311
340
return left .value < right .value
312
341
})
313
342
314
- target := ncandidates - cm .lowWater
343
+ target := ncandidates - cm .cfg . lowWater
315
344
316
345
// slightly overallocate because we may have more than one conns per peer
317
346
selected := make ([]network.Conn , 0 , target + 10 )
@@ -363,6 +392,9 @@ func (cm *BasicConnMgr) GetTagInfo(p peer.ID) *connmgr.TagInfo {
363
392
for t , v := range pi .tags {
364
393
out .Tags [t ] = v
365
394
}
395
+ for t , v := range pi .decaying {
396
+ out .Tags [t .name ] = v .Value
397
+ }
366
398
for c , t := range pi .conns {
367
399
out .Conns [c .RemoteMultiaddr ().String ()] = t
368
400
}
@@ -439,10 +471,10 @@ func (cm *BasicConnMgr) GetInfo() CMInfo {
439
471
cm .lastTrimMu .RUnlock ()
440
472
441
473
return CMInfo {
442
- HighWater : cm .highWater ,
443
- LowWater : cm .lowWater ,
474
+ HighWater : cm .cfg . highWater ,
475
+ LowWater : cm .cfg . lowWater ,
444
476
LastTrim : lastTrim ,
445
- GracePeriod : cm .gracePeriod ,
477
+ GracePeriod : cm .cfg . gracePeriod ,
446
478
ConnCount : int (atomic .LoadInt32 (& cm .connCount )),
447
479
}
448
480
}
@@ -478,6 +510,7 @@ func (nn *cmNotifee) Connected(n network.Network, c network.Conn) {
478
510
id : id ,
479
511
firstSeen : time .Now (),
480
512
tags : make (map [string ]int ),
513
+ decaying : make (map [* decayingTag ]* connmgr.DecayingValue ),
481
514
conns : make (map [network.Conn ]time.Time ),
482
515
}
483
516
s .peers [id ] = pinfo
0 commit comments