cubefs

Форк
0
144 строки · 4.3 Кб
1
// Copyright 2014 The Prometheus Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
package model
15

16
import (
17
	"sort"
18
)
19

20
// SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is
21
// used to separate label names, label values, and other strings from each other
22
// when calculating their combined hash value (aka signature aka fingerprint).
23
const SeparatorByte byte = 255
24

25
var (
26
	// cache the signature of an empty label set.
27
	emptyLabelSignature = hashNew()
28
)
29

30
// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
31
// given label set. (Collisions are possible but unlikely if the number of label
32
// sets the function is applied to is small.)
33
func LabelsToSignature(labels map[string]string) uint64 {
34
	if len(labels) == 0 {
35
		return emptyLabelSignature
36
	}
37

38
	labelNames := make([]string, 0, len(labels))
39
	for labelName := range labels {
40
		labelNames = append(labelNames, labelName)
41
	}
42
	sort.Strings(labelNames)
43

44
	sum := hashNew()
45
	for _, labelName := range labelNames {
46
		sum = hashAdd(sum, labelName)
47
		sum = hashAddByte(sum, SeparatorByte)
48
		sum = hashAdd(sum, labels[labelName])
49
		sum = hashAddByte(sum, SeparatorByte)
50
	}
51
	return sum
52
}
53

54
// labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as
55
// parameter (rather than a label map) and returns a Fingerprint.
56
func labelSetToFingerprint(ls LabelSet) Fingerprint {
57
	if len(ls) == 0 {
58
		return Fingerprint(emptyLabelSignature)
59
	}
60

61
	labelNames := make(LabelNames, 0, len(ls))
62
	for labelName := range ls {
63
		labelNames = append(labelNames, labelName)
64
	}
65
	sort.Sort(labelNames)
66

67
	sum := hashNew()
68
	for _, labelName := range labelNames {
69
		sum = hashAdd(sum, string(labelName))
70
		sum = hashAddByte(sum, SeparatorByte)
71
		sum = hashAdd(sum, string(ls[labelName]))
72
		sum = hashAddByte(sum, SeparatorByte)
73
	}
74
	return Fingerprint(sum)
75
}
76

77
// labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a
78
// faster and less allocation-heavy hash function, which is more susceptible to
79
// create hash collisions. Therefore, collision detection should be applied.
80
func labelSetToFastFingerprint(ls LabelSet) Fingerprint {
81
	if len(ls) == 0 {
82
		return Fingerprint(emptyLabelSignature)
83
	}
84

85
	var result uint64
86
	for labelName, labelValue := range ls {
87
		sum := hashNew()
88
		sum = hashAdd(sum, string(labelName))
89
		sum = hashAddByte(sum, SeparatorByte)
90
		sum = hashAdd(sum, string(labelValue))
91
		result ^= sum
92
	}
93
	return Fingerprint(result)
94
}
95

96
// SignatureForLabels works like LabelsToSignature but takes a Metric as
97
// parameter (rather than a label map) and only includes the labels with the
98
// specified LabelNames into the signature calculation. The labels passed in
99
// will be sorted by this function.
100
func SignatureForLabels(m Metric, labels ...LabelName) uint64 {
101
	if len(labels) == 0 {
102
		return emptyLabelSignature
103
	}
104

105
	sort.Sort(LabelNames(labels))
106

107
	sum := hashNew()
108
	for _, label := range labels {
109
		sum = hashAdd(sum, string(label))
110
		sum = hashAddByte(sum, SeparatorByte)
111
		sum = hashAdd(sum, string(m[label]))
112
		sum = hashAddByte(sum, SeparatorByte)
113
	}
114
	return sum
115
}
116

117
// SignatureWithoutLabels works like LabelsToSignature but takes a Metric as
118
// parameter (rather than a label map) and excludes the labels with any of the
119
// specified LabelNames from the signature calculation.
120
func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 {
121
	if len(m) == 0 {
122
		return emptyLabelSignature
123
	}
124

125
	labelNames := make(LabelNames, 0, len(m))
126
	for labelName := range m {
127
		if _, exclude := labels[labelName]; !exclude {
128
			labelNames = append(labelNames, labelName)
129
		}
130
	}
131
	if len(labelNames) == 0 {
132
		return emptyLabelSignature
133
	}
134
	sort.Sort(labelNames)
135

136
	sum := hashNew()
137
	for _, labelName := range labelNames {
138
		sum = hashAdd(sum, string(labelName))
139
		sum = hashAddByte(sum, SeparatorByte)
140
		sum = hashAdd(sum, string(m[labelName]))
141
		sum = hashAddByte(sum, SeparatorByte)
142
	}
143
	return sum
144
}
145

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.