Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / github.com / prometheus / common / model / signature.go
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 }