@@ -126,8 +126,15 @@ type topicRegisterReq struct {
126
126
}
127
127
128
128
type topicSearchReq struct {
129
- topic Topic
130
- found chan <- string
129
+ topic Topic
130
+ found chan <- * Node
131
+ lookup chan <- bool
132
+ delay time.Duration
133
+ }
134
+
135
+ type topicSearchResult struct {
136
+ target lookupInfo
137
+ nodes []* Node
131
138
}
132
139
133
140
type timeoutEvent struct {
@@ -263,16 +270,23 @@ func (net *Network) lookup(target common.Hash, stopOnMatch bool) []*Node {
263
270
break
264
271
}
265
272
// Wait for the next reply.
266
- for _ , n := range <- reply {
267
- if n != nil && ! seen [n .ID ] {
268
- seen [n .ID ] = true
269
- result .push (n , bucketSize )
270
- if stopOnMatch && n .sha == target {
271
- return result .entries
273
+ select {
274
+ case nodes := <- reply :
275
+ for _ , n := range nodes {
276
+ if n != nil && ! seen [n .ID ] {
277
+ seen [n .ID ] = true
278
+ result .push (n , bucketSize )
279
+ if stopOnMatch && n .sha == target {
280
+ return result .entries
281
+ }
272
282
}
273
283
}
284
+ pendingQueries --
285
+ case <- time .After (respTimeout ):
286
+ // forget all pending requests, start new ones
287
+ pendingQueries = 0
288
+ reply = make (chan []* Node , alpha )
274
289
}
275
- pendingQueries --
276
290
}
277
291
return result .entries
278
292
}
@@ -293,18 +307,20 @@ func (net *Network) RegisterTopic(topic Topic, stop <-chan struct{}) {
293
307
}
294
308
}
295
309
296
- func (net * Network ) SearchTopic (topic Topic , stop <- chan struct {}, found chan <- string ) {
297
- select {
298
- case net .topicSearchReq <- topicSearchReq {topic , found }:
299
- case <- net .closed :
300
- return
301
- }
302
- select {
303
- case <- net .closed :
304
- case <- stop :
310
+ func (net * Network ) SearchTopic (topic Topic , setPeriod <- chan time.Duration , found chan <- * Node , lookup chan <- bool ) {
311
+ for {
305
312
select {
306
- case net .topicSearchReq <- topicSearchReq {topic , nil }:
307
313
case <- net .closed :
314
+ return
315
+ case delay , ok := <- setPeriod :
316
+ select {
317
+ case net .topicSearchReq <- topicSearchReq {topic : topic , found : found , lookup : lookup , delay : delay }:
318
+ case <- net .closed :
319
+ return
320
+ }
321
+ if ! ok {
322
+ return
323
+ }
308
324
}
309
325
}
310
326
}
@@ -347,6 +363,13 @@ func (net *Network) reqTableOp(f func()) (called bool) {
347
363
348
364
// TODO: external address handling.
349
365
366
+ type topicSearchInfo struct {
367
+ lookupChn chan <- bool
368
+ period time.Duration
369
+ }
370
+
371
+ const maxSearchCount = 5
372
+
350
373
func (net * Network ) loop () {
351
374
var (
352
375
refreshTimer = time .NewTicker (autoRefreshInterval )
@@ -385,10 +408,12 @@ func (net *Network) loop() {
385
408
topicRegisterLookupTarget lookupInfo
386
409
topicRegisterLookupDone chan []* Node
387
410
topicRegisterLookupTick = time .NewTimer (0 )
388
- topicSearchLookupTarget lookupInfo
389
411
searchReqWhenRefreshDone []topicSearchReq
412
+ searchInfo = make (map [Topic ]topicSearchInfo )
413
+ activeSearchCount int
390
414
)
391
- topicSearchLookupDone := make (chan []* Node , 1 )
415
+ topicSearchLookupDone := make (chan topicSearchResult , 100 )
416
+ topicSearch := make (chan Topic , 100 )
392
417
<- topicRegisterLookupTick .C
393
418
394
419
statsDump := time .NewTicker (10 * time .Second )
@@ -504,21 +529,52 @@ loop:
504
529
case req := <- net .topicSearchReq :
505
530
if refreshDone == nil {
506
531
debugLog ("<-net.topicSearchReq" )
507
- if req .found == nil {
508
- net .ticketStore .removeSearchTopic (req .topic )
532
+ info , ok := searchInfo [req .topic ]
533
+ if ok {
534
+ if req .delay == time .Duration (0 ) {
535
+ delete (searchInfo , req .topic )
536
+ net .ticketStore .removeSearchTopic (req .topic )
537
+ } else {
538
+ info .period = req .delay
539
+ searchInfo [req .topic ] = info
540
+ }
509
541
continue
510
542
}
511
- net .ticketStore .addSearchTopic (req .topic , req .found )
512
- if (topicSearchLookupTarget .target == common.Hash {}) {
513
- topicSearchLookupDone <- nil
543
+ if req .delay != time .Duration (0 ) {
544
+ var info topicSearchInfo
545
+ info .period = req .delay
546
+ info .lookupChn = req .lookup
547
+ searchInfo [req .topic ] = info
548
+ net .ticketStore .addSearchTopic (req .topic , req .found )
549
+ topicSearch <- req .topic
514
550
}
515
551
} else {
516
552
searchReqWhenRefreshDone = append (searchReqWhenRefreshDone , req )
517
553
}
518
554
519
- case nodes := <- topicSearchLookupDone :
520
- debugLog ("<-topicSearchLookupDone" )
521
- net .ticketStore .searchLookupDone (topicSearchLookupTarget , nodes , func (n * Node ) []byte {
555
+ case topic := <- topicSearch :
556
+ if activeSearchCount < maxSearchCount {
557
+ activeSearchCount ++
558
+ target := net .ticketStore .nextSearchLookup (topic )
559
+ go func () {
560
+ nodes := net .lookup (target .target , false )
561
+ topicSearchLookupDone <- topicSearchResult {target : target , nodes : nodes }
562
+ }()
563
+ }
564
+ period := searchInfo [topic ].period
565
+ if period != time .Duration (0 ) {
566
+ go func () {
567
+ time .Sleep (period )
568
+ topicSearch <- topic
569
+ }()
570
+ }
571
+
572
+ case res := <- topicSearchLookupDone :
573
+ activeSearchCount --
574
+ if lookupChn := searchInfo [res .target .topic ].lookupChn ; lookupChn != nil {
575
+ lookupChn <- net .ticketStore .radius [res .target .topic ].converged
576
+ }
577
+ net .ticketStore .searchLookupDone (res .target , res .nodes , func (n * Node ) []byte {
522
578
net .ping (n , n .addr ())
523
579
return n .pingEcho
524
580
}, func (n * Node , topic Topic ) []byte {
@@ -531,11 +587,6 @@ loop:
531
587
return nil
532
588
}
533
589
})
534
- topicSearchLookupTarget = net .ticketStore .nextSearchLookup ()
535
- target := topicSearchLookupTarget .target
536
- if (target != common.Hash {}) {
537
- go func () { topicSearchLookupDone <- net .lookup (target , false ) }()
538
- }
539
590
540
591
case <- statsDump .C :
541
592
debugLog ("<-statsDump.C" )
0 commit comments