/
vector.go
102 lines (85 loc) · 2.63 KB
/
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
100
101
102
package vecfc
import (
"encoding/binary"
"math"
"github.com/Ecosystem-Knowledge/lachesis-base/inter/idx"
)
/*
* Use binary form for optimization, to avoid serialization. As a result, DB cache works as elements cache.
*/
type (
// LowestAfterSeq is a vector of lowest events (their Seq) which do observe the source event
LowestAfterSeq []byte
// HighestBeforeSeq is a vector of highest events (their Seq + IsForkDetected) which are observed by source event
HighestBeforeSeq []byte
// BranchSeq encodes Seq and MinSeq into 8 bytes
BranchSeq struct {
Seq idx.Event
MinSeq idx.Event
}
)
// NewLowestAfterSeq creates new LowestAfterSeq vector.
func NewLowestAfterSeq(size idx.Validator) *LowestAfterSeq {
b := make(LowestAfterSeq, size*4)
return &b
}
// NewHighestBeforeSeq creates new HighestBeforeSeq vector.
func NewHighestBeforeSeq(size idx.Validator) *HighestBeforeSeq {
b := make(HighestBeforeSeq, size*8)
return &b
}
// Get i's position in the byte-encoded vector clock
func (b LowestAfterSeq) Get(i idx.Validator) idx.Event {
for i >= b.Size() {
return 0
}
return idx.Event(binary.LittleEndian.Uint32(b[i*4 : (i+1)*4]))
}
// Size of the vector clock
func (b LowestAfterSeq) Size() idx.Validator {
return idx.Validator(len(b)) / 4
}
// Set i's position in the byte-encoded vector clock
func (b *LowestAfterSeq) Set(i idx.Validator, seq idx.Event) {
for i >= b.Size() {
// append zeros if exceeds size
*b = append(*b, []byte{0, 0, 0, 0}...)
}
binary.LittleEndian.PutUint32((*b)[i*4:(i+1)*4], uint32(seq))
}
// Size of the vector clock
func (b HighestBeforeSeq) Size() int {
return len(b) / 8
}
// Get i's position in the byte-encoded vector clock
func (b HighestBeforeSeq) Get(i idx.Validator) BranchSeq {
for int(i) >= b.Size() {
return BranchSeq{}
}
seq1 := binary.LittleEndian.Uint32(b[i*8 : i*8+4])
seq2 := binary.LittleEndian.Uint32(b[i*8+4 : i*8+8])
return BranchSeq{
Seq: idx.Event(seq1),
MinSeq: idx.Event(seq2),
}
}
// Set i's position in the byte-encoded vector clock
func (b *HighestBeforeSeq) Set(i idx.Validator, seq BranchSeq) {
for int(i) >= b.Size() {
// append zeros if exceeds size
*b = append(*b, []byte{0, 0, 0, 0, 0, 0, 0, 0}...)
}
binary.LittleEndian.PutUint32((*b)[i*8:i*8+4], uint32(seq.Seq))
binary.LittleEndian.PutUint32((*b)[i*8+4:i*8+8], uint32(seq.MinSeq))
}
var (
// forkDetectedSeq is a special marker of observed fork by a creator
forkDetectedSeq = BranchSeq{
Seq: 0,
MinSeq: idx.Event(math.MaxInt32),
}
)
// IsForkDetected returns true if observed fork by a creator (in combination of branches)
func (seq BranchSeq) IsForkDetected() bool {
return seq == forkDetectedSeq
}