github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/topicsdb/thread_pool.go (about) 1 package topicsdb 2 3 import ( 4 "context" 5 "time" 6 7 "github.com/unicornultrafoundation/go-helios/native/idx" 8 "github.com/unicornultrafoundation/go-u2u/common" 9 "github.com/unicornultrafoundation/go-u2u/core/types" 10 11 "github.com/unicornultrafoundation/go-u2u/utils/dbutil/threads" 12 ) 13 14 // withThreadPool wraps the index and limits its threads in use 15 type withThreadPool struct { 16 *index 17 } 18 19 // FindInBlocks returns all log records of block range by pattern. 1st pattern element is an address. 20 func (tt *withThreadPool) FindInBlocks(ctx context.Context, from, to idx.Block, pattern [][]common.Hash) (logs []*types.Log, err error) { 21 err = tt.ForEachInBlocks( 22 ctx, 23 from, to, 24 pattern, 25 func(l *types.Log) bool { 26 logs = append(logs, l) 27 return true 28 }) 29 30 return 31 } 32 33 // ForEachInBlocks matches log records of block range by pattern. 1st pattern element is an address. 34 func (tt *withThreadPool) ForEachInBlocks(ctx context.Context, from, to idx.Block, pattern [][]common.Hash, onLog func(*types.Log) (gonext bool)) error { 35 if 0 < to && to < from { 36 return nil 37 } 38 39 if ctx == nil { 40 ctx = context.Background() 41 } 42 43 pattern, err := limitPattern(pattern) 44 if err != nil { 45 return err 46 } 47 48 onMatched := func(rec *logrec) (gonext bool, err error) { 49 rec.fetch(tt.table.Logrec) 50 if rec.err != nil { 51 err = rec.err 52 return 53 } 54 gonext = onLog(rec.result) 55 return 56 } 57 58 splitby := 0 59 parallels := 0 60 for i := range pattern { 61 parallels += len(pattern[i]) 62 if len(pattern[splitby]) < len(pattern[i]) { 63 splitby = i 64 } 65 } 66 rest := pattern[splitby] 67 parallels -= len(rest) 68 69 if parallels >= threads.GlobalPool.Cap() { 70 return ErrTooBigTopics 71 } 72 73 for len(rest) > 0 { 74 got, release := threads.GlobalPool.Lock(parallels + len(rest)) 75 if got <= parallels { 76 release(got) 77 select { 78 case <-time.After(time.Millisecond): 79 continue 80 case <-ctx.Done(): 81 return ctx.Err() 82 } 83 } 84 85 onDbIterator := func() { 86 release(1) 87 } 88 89 pattern[splitby] = rest[:got-parallels] 90 rest = rest[got-parallels:] 91 err = tt.searchParallel(ctx, pattern, uint64(from), uint64(to), onMatched, onDbIterator) 92 if err != nil { 93 return err 94 } 95 } 96 97 return nil 98 } 99 100 func min(a, b int) int { 101 if a < b { 102 return a 103 } 104 return b 105 }