-
Notifications
You must be signed in to change notification settings - Fork 727
/
Copy pathlabel_constraint.go
95 lines (82 loc) · 3.23 KB
/
label_constraint.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
// Copyright 2019 TiKV Project Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package placement
import (
"strings"
"github.com/tikv/pd/pkg/core"
"github.com/tikv/pd/pkg/slice"
)
// LabelConstraintOp defines how a LabelConstraint matches a store. It can be one of
// 'in', 'notIn', 'exists', or 'notExists'.
type LabelConstraintOp string
const (
// In restricts the store label value should in the value list.
// If label does not exist, `in` is always false.
In LabelConstraintOp = "in"
// NotIn restricts the store label value should not in the value list.
// If label does not exist, `notIn` is always true.
NotIn LabelConstraintOp = "notIn"
// Exists restricts the store should have the label.
Exists LabelConstraintOp = "exists"
// NotExists restricts the store should not have the label.
NotExists LabelConstraintOp = "notExists"
)
func validateOp(op LabelConstraintOp) bool {
return op == In || op == NotIn || op == Exists || op == NotExists
}
// LabelConstraint is used to filter store when trying to place peer of a region.
type LabelConstraint struct {
Key string `json:"key,omitempty"`
Op LabelConstraintOp `json:"op,omitempty"`
Values []string `json:"values,omitempty"`
}
// MatchStore checks if a store matches the constraint.
func (c *LabelConstraint) MatchStore(store *core.StoreInfo) bool {
switch c.Op {
case In:
label := store.GetLabelValue(c.Key)
return label != "" && slice.AnyOf(c.Values, func(i int) bool { return c.Values[i] == label })
case NotIn:
label := store.GetLabelValue(c.Key)
return label == "" || slice.NoneOf(c.Values, func(i int) bool { return c.Values[i] == label })
case Exists:
return store.GetLabelValue(c.Key) != ""
case NotExists:
return store.GetLabelValue(c.Key) == ""
}
return false
}
// For backward compatibility. Need to remove later.
var legacyExclusiveLabels = []string{core.EngineKey, "exclusive"}
// If a store has exclusiveLabels, it can only be selected when the label is
// explicitly specified in constraints.
func isExclusiveLabel(key string) bool {
// *Do not* change this behavior, we rely on it to physically isolate stores.
return strings.HasPrefix(key, "$") || slice.AnyOf(legacyExclusiveLabels, func(i int) bool {
return key == legacyExclusiveLabels[i]
})
}
// MatchLabelConstraints checks if a store matches label constraints list.
func MatchLabelConstraints(store *core.StoreInfo, constraints []LabelConstraint) bool {
if store == nil {
return false
}
for _, l := range store.GetLabels() {
if isExclusiveLabel(l.GetKey()) &&
slice.NoneOf(constraints, func(i int) bool { return constraints[i].Key == l.GetKey() }) {
return false
}
}
return slice.AllOf(constraints, func(i int) bool { return constraints[i].MatchStore(store) })
}