/
uuid.go
87 lines (69 loc) · 1.56 KB
/
uuid.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
package events
import (
"encoding/binary"
"sync/atomic"
"time"
"code.google.com/p/go-uuid/uuid"
)
var (
seq uint32
node = getNodeUint32()
)
func SetNodeId(id uint32) {
node = id
}
func getNodeUint32() uint32 {
n := uuid.NodeID()
return binary.BigEndian.Uint32(n)
}
type UUID []byte
// 8 bytes of UNIXNANO
// 4 bytes of counter
// 4 bytes of hardware address
//type UUID []byte
func NewSequentialUUID() UUID {
uuid := make([]byte, 16)
nano := time.Now().UnixNano()
incr := atomic.AddUint32(&seq, 1)
binary.BigEndian.PutUint64(uuid[0:], uint64(nano))
binary.BigEndian.PutUint32(uuid[8:], incr)
binary.BigEndian.PutUint32(uuid[12:], node)
return uuid
}
func (u UUID) Bytes() []byte {
return []byte(u)
}
func (u UUID) UnixNano() int64 {
return int64(binary.BigEndian.Uint64([]byte(u)))
}
func NewUUIDPrefix(nsec int64) []byte {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, uint64(nsec))
return b
}
func (u UUID) Time() time.Time {
nsec := binary.BigEndian.Uint64([]byte(u))
return time.Unix(0, int64(nsec))
}
func (u UUID) Node() uint32 {
return binary.BigEndian.Uint32([]byte(u)[12:])
}
func (u UUID) Sequence() uint32 {
return binary.BigEndian.Uint32([]byte(u)[8:])
}
func (u UUID) After(another UUID) bool {
if u.Node() != another.Node() {
panic("Can't match UUIDs from different nodes")
}
t1 := u.Time()
t2 := another.Time()
if t1 == t2 {
const halfway uint32 = 0xFFFFFFFF / 2
// clocks match, let us compare sequences with wrap
s1 := u.Sequence()
s2 := u.Sequence()
return s1-s2 < halfway
} else {
return t1.After(t2)
}
}