-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathIDGenerator.go
88 lines (72 loc) · 2.12 KB
/
IDGenerator.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
package probing
import (
"math"
"github.com/google/uuid"
)
type sequenceBucket struct {
bitmap []bool
usedCount int64
}
type idGenerator struct {
awaitingSequences map[uuid.UUID]*sequenceBucket
currentCount int
currentUUID uuid.UUID
oldestUUIDQueue []uuid.UUID
totalOutstandingSequences int64
deletionPolicyFn func(*idGenerator)
}
func newIDGenerator(deletionPolicy func(*idGenerator)) *idGenerator {
return &idGenerator{
awaitingSequences: make(map[uuid.UUID]*sequenceBucket),
deletionPolicyFn: deletionPolicy,
}
}
func (g *idGenerator) next() (uuid.UUID, int) {
if g.currentCount == 0 {
g.currentUUID = uuid.New()
}
var ok bool
if _, ok = g.awaitingSequences[g.currentUUID]; !ok {
inFlightSeqs := new(sequenceBucket)
inFlightSeqs.bitmap = make([]bool, math.MaxUint16)
g.awaitingSequences[g.currentUUID] = inFlightSeqs
g.oldestUUIDQueue = append(g.oldestUUIDQueue, g.currentUUID)
}
nextSeq := g.currentCount
nextUUID := g.currentUUID
g.totalOutstandingSequences++
g.awaitingSequences[g.currentUUID].bitmap[g.currentCount] = true
g.awaitingSequences[g.currentUUID].usedCount++
// Run the deletion policy. May modify awaitingSequences
g.deletionPolicyFn(g)
g.currentCount = (g.currentCount + 1) % math.MaxUint16
return nextUUID, nextSeq
}
func (g *idGenerator) find(UUID uuid.UUID, sequenceNum int) bool {
if val, ok := g.awaitingSequences[UUID]; ok {
return val.bitmap[sequenceNum]
}
return false
}
func (g *idGenerator) retire(UUID uuid.UUID, sequenceNum int) {
if val, ok := g.awaitingSequences[UUID]; ok {
val.bitmap[sequenceNum] = false
val.usedCount--
}
g.totalOutstandingSequences--
}
func (g *idGenerator) retireBucket(UUID uuid.UUID) {
if val, ok := g.awaitingSequences[UUID]; ok {
g.totalOutstandingSequences -= val.usedCount
delete(g.awaitingSequences, UUID)
}
}
func RemoveAfterMaxItems(maxItems int64) func(*idGenerator) {
return func(g *idGenerator) {
if g.totalOutstandingSequences == maxItems {
toDeleteUUID := g.oldestUUIDQueue[0]
g.oldestUUIDQueue = g.oldestUUIDQueue[1:]
g.retireBucket(toDeleteUUID)
}
}
}