Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / client-go / tools / cache / store.go
1 /*
2 Copyright 2014 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 package cache
18
19 import (
20         "fmt"
21         "strings"
22
23         "k8s.io/apimachinery/pkg/api/meta"
24 )
25
26 // Store is a generic object storage interface. Reflector knows how to watch a server
27 // and update a store. A generic store is provided, which allows Reflector to be used
28 // as a local caching system, and an LRU store, which allows Reflector to work like a
29 // queue of items yet to be processed.
30 //
31 // Store makes no assumptions about stored object identity; it is the responsibility
32 // of a Store implementation to provide a mechanism to correctly key objects and to
33 // define the contract for obtaining objects by some arbitrary key type.
34 type Store interface {
35         Add(obj interface{}) error
36         Update(obj interface{}) error
37         Delete(obj interface{}) error
38         List() []interface{}
39         ListKeys() []string
40         Get(obj interface{}) (item interface{}, exists bool, err error)
41         GetByKey(key string) (item interface{}, exists bool, err error)
42
43         // Replace will delete the contents of the store, using instead the
44         // given list. Store takes ownership of the list, you should not reference
45         // it after calling this function.
46         Replace([]interface{}, string) error
47         Resync() error
48 }
49
50 // KeyFunc knows how to make a key from an object. Implementations should be deterministic.
51 type KeyFunc func(obj interface{}) (string, error)
52
53 // KeyError will be returned any time a KeyFunc gives an error; it includes the object
54 // at fault.
55 type KeyError struct {
56         Obj interface{}
57         Err error
58 }
59
60 // Error gives a human-readable description of the error.
61 func (k KeyError) Error() string {
62         return fmt.Sprintf("couldn't create key for object %+v: %v", k.Obj, k.Err)
63 }
64
65 // ExplicitKey can be passed to MetaNamespaceKeyFunc if you have the key for
66 // the object but not the object itself.
67 type ExplicitKey string
68
69 // MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make
70 // keys for API objects which implement meta.Interface.
71 // The key uses the format <namespace>/<name> unless <namespace> is empty, then
72 // it's just <name>.
73 //
74 // TODO: replace key-as-string with a key-as-struct so that this
75 // packing/unpacking won't be necessary.
76 func MetaNamespaceKeyFunc(obj interface{}) (string, error) {
77         if key, ok := obj.(ExplicitKey); ok {
78                 return string(key), nil
79         }
80         meta, err := meta.Accessor(obj)
81         if err != nil {
82                 return "", fmt.Errorf("object has no meta: %v", err)
83         }
84         if len(meta.GetNamespace()) > 0 {
85                 return meta.GetNamespace() + "/" + meta.GetName(), nil
86         }
87         return meta.GetName(), nil
88 }
89
90 // SplitMetaNamespaceKey returns the namespace and name that
91 // MetaNamespaceKeyFunc encoded into key.
92 //
93 // TODO: replace key-as-string with a key-as-struct so that this
94 // packing/unpacking won't be necessary.
95 func SplitMetaNamespaceKey(key string) (namespace, name string, err error) {
96         parts := strings.Split(key, "/")
97         switch len(parts) {
98         case 1:
99                 // name only, no namespace
100                 return "", parts[0], nil
101         case 2:
102                 // namespace and name
103                 return parts[0], parts[1], nil
104         }
105
106         return "", "", fmt.Errorf("unexpected key format: %q", key)
107 }
108
109 // cache responsibilities are limited to:
110 //      1. Computing keys for objects via keyFunc
111 //  2. Invoking methods of a ThreadSafeStorage interface
112 type cache struct {
113         // cacheStorage bears the burden of thread safety for the cache
114         cacheStorage ThreadSafeStore
115         // keyFunc is used to make the key for objects stored in and retrieved from items, and
116         // should be deterministic.
117         keyFunc KeyFunc
118 }
119
120 var _ Store = &cache{}
121
122 // Add inserts an item into the cache.
123 func (c *cache) Add(obj interface{}) error {
124         key, err := c.keyFunc(obj)
125         if err != nil {
126                 return KeyError{obj, err}
127         }
128         c.cacheStorage.Add(key, obj)
129         return nil
130 }
131
132 // Update sets an item in the cache to its updated state.
133 func (c *cache) Update(obj interface{}) error {
134         key, err := c.keyFunc(obj)
135         if err != nil {
136                 return KeyError{obj, err}
137         }
138         c.cacheStorage.Update(key, obj)
139         return nil
140 }
141
142 // Delete removes an item from the cache.
143 func (c *cache) Delete(obj interface{}) error {
144         key, err := c.keyFunc(obj)
145         if err != nil {
146                 return KeyError{obj, err}
147         }
148         c.cacheStorage.Delete(key)
149         return nil
150 }
151
152 // List returns a list of all the items.
153 // List is completely threadsafe as long as you treat all items as immutable.
154 func (c *cache) List() []interface{} {
155         return c.cacheStorage.List()
156 }
157
158 // ListKeys returns a list of all the keys of the objects currently
159 // in the cache.
160 func (c *cache) ListKeys() []string {
161         return c.cacheStorage.ListKeys()
162 }
163
164 // GetIndexers returns the indexers of cache
165 func (c *cache) GetIndexers() Indexers {
166         return c.cacheStorage.GetIndexers()
167 }
168
169 // Index returns a list of items that match on the index function
170 // Index is thread-safe so long as you treat all items as immutable
171 func (c *cache) Index(indexName string, obj interface{}) ([]interface{}, error) {
172         return c.cacheStorage.Index(indexName, obj)
173 }
174
175 func (c *cache) IndexKeys(indexName, indexKey string) ([]string, error) {
176         return c.cacheStorage.IndexKeys(indexName, indexKey)
177 }
178
179 // ListIndexFuncValues returns the list of generated values of an Index func
180 func (c *cache) ListIndexFuncValues(indexName string) []string {
181         return c.cacheStorage.ListIndexFuncValues(indexName)
182 }
183
184 func (c *cache) ByIndex(indexName, indexKey string) ([]interface{}, error) {
185         return c.cacheStorage.ByIndex(indexName, indexKey)
186 }
187
188 func (c *cache) AddIndexers(newIndexers Indexers) error {
189         return c.cacheStorage.AddIndexers(newIndexers)
190 }
191
192 // Get returns the requested item, or sets exists=false.
193 // Get is completely threadsafe as long as you treat all items as immutable.
194 func (c *cache) Get(obj interface{}) (item interface{}, exists bool, err error) {
195         key, err := c.keyFunc(obj)
196         if err != nil {
197                 return nil, false, KeyError{obj, err}
198         }
199         return c.GetByKey(key)
200 }
201
202 // GetByKey returns the request item, or exists=false.
203 // GetByKey is completely threadsafe as long as you treat all items as immutable.
204 func (c *cache) GetByKey(key string) (item interface{}, exists bool, err error) {
205         item, exists = c.cacheStorage.Get(key)
206         return item, exists, nil
207 }
208
209 // Replace will delete the contents of 'c', using instead the given list.
210 // 'c' takes ownership of the list, you should not reference the list again
211 // after calling this function.
212 func (c *cache) Replace(list []interface{}, resourceVersion string) error {
213         items := make(map[string]interface{}, len(list))
214         for _, item := range list {
215                 key, err := c.keyFunc(item)
216                 if err != nil {
217                         return KeyError{item, err}
218                 }
219                 items[key] = item
220         }
221         c.cacheStorage.Replace(items, resourceVersion)
222         return nil
223 }
224
225 // Resync touches all items in the store to force processing
226 func (c *cache) Resync() error {
227         return c.cacheStorage.Resync()
228 }
229
230 // NewStore returns a Store implemented simply with a map and a lock.
231 func NewStore(keyFunc KeyFunc) Store {
232         return &cache{
233                 cacheStorage: NewThreadSafeStore(Indexers{}, Indices{}),
234                 keyFunc:      keyFunc,
235         }
236 }
237
238 // NewIndexer returns an Indexer implemented simply with a map and a lock.
239 func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {
240         return &cache{
241                 cacheStorage: NewThreadSafeStore(indexers, Indices{}),
242                 keyFunc:      keyFunc,
243         }
244 }