-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathblocks.go
117 lines (87 loc) · 1.79 KB
/
blocks.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
package wavelet
import (
"fmt"
"sync"
"github.com/perlin-network/wavelet/store"
)
type Blocks struct {
sync.RWMutex
store store.KV
buffer []*Block
latest uint32
oldest uint32
limit uint8
}
func NewBlocks(store store.KV, limit uint8) (*Blocks, error) {
r := &Blocks{
store: store,
buffer: make([]*Block, 0, limit),
limit: limit,
}
blocks, latest, oldest, err := LoadBlocks(store)
if err != nil {
return r, err
}
r.buffer = blocks
r.latest = latest
r.oldest = oldest
return r, nil
}
func (b *Blocks) Oldest() *Block {
b.RLock()
block := b.buffer[b.oldest]
b.RUnlock()
return block
}
func (b *Blocks) Latest() *Block {
b.RLock()
block := b.buffer[b.latest]
b.RUnlock()
return block
}
func (b *Blocks) LatestHeight() uint64 {
return b.Latest().Index
}
// Save stores the block on disk. It returns the oldest
// block that should be pruned, if any.
func (b *Blocks) Save(block *Block) (*Block, error) {
b.Lock()
if len(b.buffer) > 0 {
b.latest = (b.latest + 1) % uint32(b.limit)
if b.oldest == b.latest {
b.oldest = (b.oldest + 1) % uint32(b.limit)
}
}
var oldBlock *Block
if uint8(len(b.buffer)) < b.limit {
b.buffer = append(b.buffer, block)
} else {
oldBlock = b.buffer[b.latest]
b.buffer[b.latest] = block
}
err := StoreBlock(b.store, *block, b.latest, b.oldest, uint8(len(b.buffer)))
b.Unlock()
return oldBlock, err
}
func (b *Blocks) GetByIndex(ix uint64) (*Block, error) {
var block *Block
b.RLock()
for _, r := range b.buffer {
if ix == r.Index {
block = r
break
}
}
b.RUnlock()
if block == nil {
return nil, fmt.Errorf("no block found for index - %d", ix)
}
return block, nil
}
func (b *Blocks) Clone() []*Block {
b.RLock()
blocks := make([]*Block, len(b.buffer))
copy(blocks, b.buffer)
b.RUnlock()
return blocks
}