forked from RaghavSood/ripple
/
ledgerset.go
119 lines (102 loc) · 2.6 KB
/
ledgerset.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
package data
import (
"fmt"
"github.com/willf/bitset"
"sort"
"time"
)
type LedgerSlice []uint32
func (s LedgerSlice) Len() int { return len(s) }
func (s LedgerSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s LedgerSlice) Less(i, j int) bool { return s[i] < s[j] }
func (s LedgerSlice) Sorted() LedgerSlice { sort.Sort(s); return s }
type LedgerRange struct {
Start uint32
End uint32
Max uint32
}
type Work struct {
*LedgerRange
MissingLedgers LedgerSlice
MissingNodes []Hash256
}
type LedgerSet struct {
ledgers *bitset.BitSet
start uint32
taken map[uint32]time.Time
returned uint64
duration time.Duration
}
func NewLedgerSet(start, capacity uint32) *LedgerSet {
return &LedgerSet{
ledgers: bitset.New(uint(capacity)).Complement(),
start: start,
taken: make(map[uint32]time.Time),
}
}
func (l *LedgerSet) String() string {
var rate float64
if l.returned > 0 {
rate = l.duration.Seconds() / float64(l.returned)
}
return fmt.Sprintf("Count: %d Taken: %d Avg: %0.04f secs", l.Count(), l.Taken(), rate)
}
func (l *LedgerSet) Taken() uint32 {
return uint32(len(l.taken))
}
func (l *LedgerSet) Max() uint32 {
return uint32(l.ledgers.Len())
}
func (l *LedgerSet) Count() uint32 {
return uint32(l.ledgers.Len() - l.ledgers.Count())
}
func (l *LedgerSet) Extend(i uint32) {
for j, length := uint(i-1), l.ledgers.Len(); j > length; j-- {
l.ledgers.Set(j)
}
}
func (l *LedgerSet) Set(i uint32) time.Duration {
l.Extend(i)
l.ledgers.Clear(uint(i))
if when, ok := l.taken[i]; ok {
delete(l.taken, i)
l.returned++
duration := time.Now().Sub(when)
l.duration += duration
return duration
}
return time.Duration(0)
}
func (l *LedgerSet) take(i uint32) bool {
if !l.ledgers.Test(uint(i)) {
return false
}
when, ok := l.taken[i]
if !ok || (ok && time.Now().Sub(when).Seconds() > 90) {
l.taken[i] = time.Now()
return true
}
return false
}
func (l *LedgerSet) TakeMiddle(r *LedgerRange) LedgerSlice {
ledgers := make(LedgerSlice, 0, r.Max)
for start, end := max(r.Start, l.start), min(r.End, uint32(l.ledgers.Len())); start <= end && uint32(len(ledgers)) < r.Max; start++ {
if l.take(start) {
ledgers = append(ledgers, uint32(start))
}
}
return ledgers
}
func (l *LedgerSet) TakeBottom(n uint32) LedgerSlice {
r := &LedgerRange{l.start, uint32(l.ledgers.Len()), n}
return l.TakeMiddle(r)
}
func (l *LedgerSet) TakeTop(n uint32) LedgerSlice {
ledgers := make(LedgerSlice, 0, n)
for i := uint32(l.ledgers.Len()) - 1; i >= l.start && len(ledgers) < int(n); i-- {
if l.take(i) {
ledgers = append(ledgers, i)
}
}
return ledgers.Sorted()
}