-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstorage_vector.go
99 lines (82 loc) · 2.09 KB
/
storage_vector.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
package negentropy
import (
"fmt"
"golang.org/x/exp/slices"
)
type NegentropyStorageVector struct {
items []Item
sealed bool
}
func (nsv *NegentropyStorageVector) Insert(timestamp uint32, id [ID_SIZE]byte) {
if nsv.sealed {
panic(fmt.Errorf("already sealed"))
}
nsv.items = append(nsv.items, Item{timestamp: timestamp, id: id})
}
func (nsv *NegentropyStorageVector) Seal() {
if nsv.sealed {
panic(fmt.Errorf("already sealed"))
}
nsv.sealed = true
slices.SortFunc(nsv.items, func(a, b Item) int {
if a.timestamp == b.timestamp {
return slices.Compare(a.id[:], b.id[:])
}
return int(a.timestamp - b.timestamp)
})
for i := 1; i < len(nsv.items); i++ {
if itemCompare(nsv.items[i-1], nsv.items[i]) == 0 {
panic(fmt.Errorf("duplicate Item inserted"))
}
}
}
func (nsv *NegentropyStorageVector) Unseal() {
nsv.sealed = false
}
func (nsv *NegentropyStorageVector) Size() int {
nsv.checkSealed()
return len(nsv.items)
}
func (nsv *NegentropyStorageVector) GetItem(i int) Item {
nsv.checkSealed()
return nsv.items[i]
}
func (nsv *NegentropyStorageVector) Iterate(begin, end int, cb func(Item) bool) {
nsv.checkSealed()
nsv.checkBounds(begin, end)
for i := begin; i < end; i++ {
if !cb(nsv.items[i]) {
break
}
}
}
func (nsv *NegentropyStorageVector) FindLowerBound(begin, end int, bound Item) int {
nsv.checkSealed()
nsv.checkBounds(begin, end)
v, ok := slices.BinarySearchFunc(nsv.items[begin:], end, func(a Item, _ int) int {
return itemCompare(a, bound)
})
if !ok {
fmt.Println("not found in slice")
}
return v
}
func (nsv *NegentropyStorageVector) Fingerprint(begin, end int) []byte {
out := NewAccumulator()
out.SetToZero()
nsv.Iterate(begin, end, func(item Item) bool {
out.Add(item.id[:])
return true
})
return out.GetFingerprint(end - begin)
}
func (nsv *NegentropyStorageVector) checkSealed() {
if !nsv.sealed {
panic(fmt.Errorf("not sealed"))
}
}
func (nsv *NegentropyStorageVector) checkBounds(begin, end int) {
if begin > end || end > len(nsv.items) {
panic(fmt.Errorf("bad range: %d > %d || %d > %d", begin, end, end, len(nsv.items)))
}
}