-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlayer.go
95 lines (88 loc) · 2.34 KB
/
layer.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
package expt
import (
"encoding/json"
"fmt"
"hash/fnv"
"github.com/pkg/errors"
)
var ErrSpec = errors.New("invalid spec")
//ModSpec 为闭区间如 [0-50][51-99]
type Layer struct {
Id string `json:"id"`
ModSpecToExpt map[string]uint32 `json:"modSpecToExpt"`
ModSpecToChildLayers map[string][]*Layer `json:"modSpecToChildLayers"`
modIdToExpt map[uint32]uint32
modIdToChildLayers map[uint32][]*Layer
}
func NewLayerFromSPEC(spec string) (*Layer, error) {
l := &Layer{}
if err := json.Unmarshal([]byte(spec), l); err != nil {
return nil, errors.Wrapf(err, "spec(%s)", spec)
}
if err := l.parseModId(); err != nil {
return nil, err
}
return l, nil
}
func (root *Layer) parseModId() error {
root.modIdToExpt = make(map[uint32]uint32)
root.modIdToChildLayers = make(map[uint32][]*Layer)
mmod := make(map[int]struct{})
checkmod := func(mod int) error {
if _, ok := mmod[mod]; ok {
return errors.Errorf("mod(%d) confict", mod)
}
mmod[mod] = struct{}{}
return nil
}
for spec, exptid := range root.ModSpecToExpt {
low, high, err := parseModSpec(spec)
if err != nil {
return errors.Wrapf(err, "%s", spec)
}
for mod := low; mod <= high; mod++ {
if err := checkmod(mod); err != nil {
return err
}
root.modIdToExpt[uint32(mod)] = exptid
}
}
for spec, childlayers := range root.ModSpecToChildLayers {
for _, child := range childlayers {
if err := child.parseModId(); err != nil {
return err
}
}
low, high, err := parseModSpec(spec)
if err != nil {
return errors.Wrapf(err, "%s", spec)
}
for mod := low; mod <= high; mod++ {
if err := checkmod(mod); err != nil {
return err
}
root.modIdToChildLayers[uint32(mod)] = childlayers
}
}
return nil
}
func (root *Layer) GetExptByHashId(hashid string) (exptids []uint32, err error) {
hash := fnv.New32()
if _, err = hash.Write([]byte(fmt.Sprintf("%s_%s", root.Id, hashid))); err != nil {
return exptids, errors.WithStack(err)
}
mod := hash.Sum32() % 100
if exptid, ok := root.modIdToExpt[mod]; ok {
return []uint32{exptid}, nil
}
if childs, ok := root.modIdToChildLayers[mod]; ok {
for _, child := range childs {
ids, err := child.GetExptByHashId(hashid)
if err != nil {
return exptids, errors.WithStack(err)
}
exptids = append(exptids, ids...)
}
}
return exptids, nil
}