1
16
17 package selectors
18
19 import (
20 "fmt"
21 "strings"
22 "sync"
23
24 pkglabels "k8s.io/apimachinery/pkg/labels"
25 )
26
27
28
29 type BiMultimap struct {
30 mux sync.RWMutex
31
32
33 labeledObjects map[Key]*labeledObject
34 selectingObjects map[Key]*selectingObject
35
36
37 labeledBySelecting map[selectorKey]*labeledObjects
38 selectingByLabeled map[labelsKey]*selectingObjects
39 }
40
41
42 func NewBiMultimap() *BiMultimap {
43 return &BiMultimap{
44 labeledObjects: make(map[Key]*labeledObject),
45 selectingObjects: make(map[Key]*selectingObject),
46 labeledBySelecting: make(map[selectorKey]*labeledObjects),
47 selectingByLabeled: make(map[labelsKey]*selectingObjects),
48 }
49 }
50
51
52 type Key struct {
53 Name string
54 Namespace string
55 }
56
57
58 func Parse(s string) (key Key) {
59 ns := strings.SplitN(s, "/", 2)
60 if len(ns) == 2 {
61 key.Namespace = ns[0]
62 key.Name = ns[1]
63 } else {
64 key.Name = ns[0]
65 }
66 return key
67 }
68
69 func (k Key) String() string {
70 return fmt.Sprintf("%v/%v", k.Namespace, k.Name)
71 }
72
73 type selectorKey struct {
74 key string
75 namespace string
76 }
77
78 type selectingObject struct {
79 key Key
80 selector pkglabels.Selector
81
82
83 selectorKey selectorKey
84 }
85
86 type selectingObjects struct {
87 objects map[Key]*selectingObject
88 refCount int
89 }
90
91 type labelsKey struct {
92 key string
93 namespace string
94 }
95
96 type labeledObject struct {
97 key Key
98 labels map[string]string
99
100
101 labelsKey labelsKey
102 }
103
104 type labeledObjects struct {
105 objects map[Key]*labeledObject
106 refCount int
107 }
108
109
110
111 func (m *BiMultimap) Put(key Key, labels map[string]string) {
112 m.mux.Lock()
113 defer m.mux.Unlock()
114
115 labelsKey := labelsKey{
116 key: pkglabels.Set(labels).String(),
117 namespace: key.Namespace,
118 }
119 if l, ok := m.labeledObjects[key]; ok {
120
121 if labelsKey == l.labelsKey {
122
123 return
124 }
125
126 m.delete(key)
127 }
128
129 labels = copyLabels(labels)
130 labeledObject := &labeledObject{
131 key: key,
132 labels: labels,
133 labelsKey: labelsKey,
134 }
135 m.labeledObjects[key] = labeledObject
136
137 if _, ok := m.selectingByLabeled[labelsKey]; !ok {
138
139 selecting := &selectingObjects{
140 objects: make(map[Key]*selectingObject),
141 }
142 set := pkglabels.Set(labels)
143 for _, s := range m.selectingObjects {
144 if s.key.Namespace != key.Namespace {
145 continue
146 }
147 if s.selector.Matches(set) {
148 selecting.objects[s.key] = s
149 }
150 }
151
152 m.selectingByLabeled[labelsKey] = selecting
153 }
154 selecting := m.selectingByLabeled[labelsKey]
155 selecting.refCount++
156 for _, sObject := range selecting.objects {
157
158 labeled := m.labeledBySelecting[sObject.selectorKey]
159 labeled.objects[labeledObject.key] = labeledObject
160 }
161 }
162
163
164 func (m *BiMultimap) Delete(key Key) {
165 m.mux.Lock()
166 defer m.mux.Unlock()
167 m.delete(key)
168 }
169
170 func (m *BiMultimap) delete(key Key) {
171 if _, ok := m.labeledObjects[key]; !ok {
172
173 return
174 }
175 labeledObject := m.labeledObjects[key]
176 labelsKey := labeledObject.labelsKey
177 defer delete(m.labeledObjects, key)
178 if _, ok := m.selectingByLabeled[labelsKey]; !ok {
179
180 return
181 }
182
183 for _, selectingObject := range m.selectingByLabeled[labelsKey].objects {
184 selectorKey := selectingObject.selectorKey
185
186 delete(m.labeledBySelecting[selectorKey].objects, key)
187 }
188 m.selectingByLabeled[labelsKey].refCount--
189
190 if m.selectingByLabeled[labelsKey].refCount == 0 {
191 delete(m.selectingByLabeled, labelsKey)
192 }
193 }
194
195
196 func (m *BiMultimap) Exists(key Key) bool {
197 m.mux.RLock()
198 defer m.mux.RUnlock()
199
200 _, exists := m.labeledObjects[key]
201 return exists
202 }
203
204
205
206 func (m *BiMultimap) PutSelector(key Key, selector pkglabels.Selector) {
207 m.mux.Lock()
208 defer m.mux.Unlock()
209
210 selectorKey := selectorKey{
211 key: selector.String(),
212 namespace: key.Namespace,
213 }
214 if s, ok := m.selectingObjects[key]; ok {
215
216 if selectorKey == s.selectorKey {
217
218 return
219 }
220
221 m.deleteSelector(key)
222 }
223
224 selectingObject := &selectingObject{
225 key: key,
226 selector: selector,
227 selectorKey: selectorKey,
228 }
229 m.selectingObjects[key] = selectingObject
230
231 if _, ok := m.labeledBySelecting[selectorKey]; !ok {
232
233 labeled := &labeledObjects{
234 objects: make(map[Key]*labeledObject),
235 }
236 for _, l := range m.labeledObjects {
237 if l.key.Namespace != key.Namespace {
238 continue
239 }
240 set := pkglabels.Set(l.labels)
241 if selector.Matches(set) {
242 labeled.objects[l.key] = l
243 }
244 }
245
246 m.labeledBySelecting[selectorKey] = labeled
247 }
248 labeled := m.labeledBySelecting[selectorKey]
249 labeled.refCount++
250 for _, labeledObject := range labeled.objects {
251
252 selecting := m.selectingByLabeled[labeledObject.labelsKey]
253 selecting.objects[selectingObject.key] = selectingObject
254 }
255 }
256
257
258
259 func (m *BiMultimap) DeleteSelector(key Key) {
260 m.mux.Lock()
261 defer m.mux.Unlock()
262 m.deleteSelector(key)
263 }
264
265 func (m *BiMultimap) deleteSelector(key Key) {
266 if _, ok := m.selectingObjects[key]; !ok {
267
268 return
269 }
270 selectingObject := m.selectingObjects[key]
271 selectorKey := selectingObject.selectorKey
272 defer delete(m.selectingObjects, key)
273 if _, ok := m.labeledBySelecting[selectorKey]; !ok {
274
275 return
276 }
277
278 for _, labeledObject := range m.labeledBySelecting[selectorKey].objects {
279 labelsKey := labeledObject.labelsKey
280
281 delete(m.selectingByLabeled[labelsKey].objects, key)
282 }
283 m.labeledBySelecting[selectorKey].refCount--
284
285 if m.labeledBySelecting[selectorKey].refCount == 0 {
286 delete(m.labeledBySelecting, selectorKey)
287 }
288 }
289
290
291 func (m *BiMultimap) SelectorExists(key Key) bool {
292 m.mux.RLock()
293 defer m.mux.RUnlock()
294
295 _, exists := m.selectingObjects[key]
296 return exists
297 }
298
299
300
301 func (m *BiMultimap) KeepOnly(keys []Key) {
302 m.mux.Lock()
303 defer m.mux.Unlock()
304
305 keyMap := make(map[Key]bool)
306 for _, k := range keys {
307 keyMap[k] = true
308 }
309 for k := range m.labeledObjects {
310 if !keyMap[k] {
311 m.delete(k)
312 }
313 }
314 }
315
316
317
318
319 func (m *BiMultimap) KeepOnlySelectors(keys []Key) {
320 m.mux.Lock()
321 defer m.mux.Unlock()
322
323 keyMap := make(map[Key]bool)
324 for _, k := range keys {
325 keyMap[k] = true
326 }
327 for k := range m.selectingObjects {
328 if !keyMap[k] {
329 m.deleteSelector(k)
330 }
331 }
332 }
333
334
335
336 func (m *BiMultimap) Select(key Key) (keys []Key, ok bool) {
337 m.mux.RLock()
338 defer m.mux.RUnlock()
339
340 selectingObject, ok := m.selectingObjects[key]
341 if !ok {
342
343 return nil, false
344 }
345 keys = make([]Key, 0)
346 if labeled, ok := m.labeledBySelecting[selectingObject.selectorKey]; ok {
347 for _, labeledObject := range labeled.objects {
348 keys = append(keys, labeledObject.key)
349 }
350 }
351 return keys, true
352 }
353
354
355
356 func (m *BiMultimap) ReverseSelect(key Key) (keys []Key, ok bool) {
357 m.mux.RLock()
358 defer m.mux.RUnlock()
359
360 labeledObject, ok := m.labeledObjects[key]
361 if !ok {
362
363 return []Key{}, false
364 }
365 keys = make([]Key, 0)
366 if selecting, ok := m.selectingByLabeled[labeledObject.labelsKey]; ok {
367 for _, selectingObject := range selecting.objects {
368 keys = append(keys, selectingObject.key)
369 }
370 }
371 return keys, true
372 }
373
374 func copyLabels(labels map[string]string) map[string]string {
375 l := make(map[string]string)
376 for k, v := range labels {
377 l[k] = v
378 }
379 return l
380 }
381
View as plain text