-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsuid.go
83 lines (63 loc) · 1.38 KB
/
suid.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
package asdf
import (
"encoding/binary"
"encoding/hex"
"sync/atomic"
"time"
)
const suidSize = 16
type Suid [suidSize]byte
func (me *Suid) Seq() uint32 {
return binary.BigEndian.Uint32((*me)[12:])
}
func (me *Suid) ToString() string {
return hex.EncodeToString((*me)[:])
}
func (me *Suid) FromString(s string) error {
if len(s) != 2*suidSize {
return ErrBadLen
} else if buf, err := hex.DecodeString(s); nil != err {
return err
} else {
copy((*me)[:], buf)
return nil
}
}
type ISuID interface {
Generate() Suid
}
type suidGenerator struct {
name string
unix uint32
rand [8]byte
address *uint32
}
func (me suidGenerator) Generate() Suid {
suid := Suid{}
binary.BigEndian.PutUint32(suid[0:4], me.unix)
copy(suid[4:12], me.rand[:])
binary.BigEndian.PutUint32(suid[12:], atomic.AddUint32(me.address, 1))
return suid
}
func SuidGenerator(name string) ISuID {
seqAddress := (*uint32)(nil)
suidLock.Handle(func() {
address, ok := suidMap[name]
if !ok {
seq := uint32(RandSeed.Int31() & 0xffff)
address = &seq
suidMap[name] = address
}
seqAddress = address
})
generator := &suidGenerator{
name: name,
address: seqAddress,
unix: uint32(time.Now().Unix()),
}
RandBuffer(generator.rand[:]).Rand()
Log.Debug("new suid generator:%+v", generator)
return generator
}
var suidLock = &AccessLock{}
var suidMap = make(map[string]*uint32)