-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhlc.go
81 lines (65 loc) · 1.46 KB
/
hlc.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
package hlc
import "fmt"
type Clock interface {
Now() int64
}
type HLC struct {
clock Clock
t Timestamp
}
type Timestamp struct {
ts int64
count int64
}
// Less compares timestamps by checking the timestamps first
// if they're equal then it uses the counters to break the tie.
// it returns true if incoming is less than t
func (t Timestamp) Less(incoming Timestamp) bool {
return t.ts < incoming.ts || (t.ts == incoming.ts && t.count < incoming.count)
}
func (t Timestamp) String() string {
return fmt.Sprintf("TS=%d Count=%d", t.ts, t.count)
}
func New() *HLC {
return &HLC{t: Timestamp{}, clock: PT{}}
}
func NewWithPT(pt Clock) *HLC {
return &HLC{t: Timestamp{}, clock: pt}
}
// Now should be called when sending an event or when a local event happens
func (h *HLC) Now() Timestamp {
t := h.t
h.t.ts = h.max(t.ts, h.clock.Now())
if h.t.ts != t.ts {
h.t.count = 0
return h.t
}
h.t.count++
return h.t
}
// Update should be called when receive an event
func (h *HLC) Update(incoming Timestamp) {
t := h.t
h.t.ts = h.max(t.ts, incoming.ts, h.clock.Now())
if h.t.ts == t.ts && incoming.ts == t.ts {
h.t.count = h.max(t.count, incoming.count) + 1
} else if t.ts == h.t.ts {
h.t.count++
} else if h.t.ts == incoming.ts {
h.t.count = incoming.count + 1
} else {
h.t.count = 0
}
}
func (h *HLC) max(vals ...int64) int64 {
if len(vals) == 0 {
return 0
}
m := vals[0]
for i := range vals {
if vals[i] > m {
m = vals[i]
}
}
return m
}