2 Copyright 2014 The Kubernetes Authors.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
23 "k8s.io/apimachinery/pkg/api/meta"
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.
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
40 Get(obj interface{}) (item interface{}, exists bool, err error)
41 GetByKey(key string) (item interface{}, exists bool, err error)
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
50 // KeyFunc knows how to make a key from an object. Implementations should be deterministic.
51 type KeyFunc func(obj interface{}) (string, error)
53 // KeyError will be returned any time a KeyFunc gives an error; it includes the object
55 type KeyError struct {
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)
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
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
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
80 meta, err := meta.Accessor(obj)
82 return "", fmt.Errorf("object has no meta: %v", err)
84 if len(meta.GetNamespace()) > 0 {
85 return meta.GetNamespace() + "/" + meta.GetName(), nil
87 return meta.GetName(), nil
90 // SplitMetaNamespaceKey returns the namespace and name that
91 // MetaNamespaceKeyFunc encoded into key.
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, "/")
99 // name only, no namespace
100 return "", parts[0], nil
102 // namespace and name
103 return parts[0], parts[1], nil
106 return "", "", fmt.Errorf("unexpected key format: %q", key)
109 // cache responsibilities are limited to:
110 // 1. Computing keys for objects via keyFunc
111 // 2. Invoking methods of a ThreadSafeStorage interface
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.
120 var _ Store = &cache{}
122 // Add inserts an item into the cache.
123 func (c *cache) Add(obj interface{}) error {
124 key, err := c.keyFunc(obj)
126 return KeyError{obj, err}
128 c.cacheStorage.Add(key, obj)
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)
136 return KeyError{obj, err}
138 c.cacheStorage.Update(key, obj)
142 // Delete removes an item from the cache.
143 func (c *cache) Delete(obj interface{}) error {
144 key, err := c.keyFunc(obj)
146 return KeyError{obj, err}
148 c.cacheStorage.Delete(key)
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()
158 // ListKeys returns a list of all the keys of the objects currently
160 func (c *cache) ListKeys() []string {
161 return c.cacheStorage.ListKeys()
164 // GetIndexers returns the indexers of cache
165 func (c *cache) GetIndexers() Indexers {
166 return c.cacheStorage.GetIndexers()
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)
175 func (c *cache) IndexKeys(indexName, indexKey string) ([]string, error) {
176 return c.cacheStorage.IndexKeys(indexName, indexKey)
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)
184 func (c *cache) ByIndex(indexName, indexKey string) ([]interface{}, error) {
185 return c.cacheStorage.ByIndex(indexName, indexKey)
188 func (c *cache) AddIndexers(newIndexers Indexers) error {
189 return c.cacheStorage.AddIndexers(newIndexers)
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)
197 return nil, false, KeyError{obj, err}
199 return c.GetByKey(key)
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
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)
217 return KeyError{item, err}
221 c.cacheStorage.Replace(items, resourceVersion)
225 // Resync touches all items in the store to force processing
226 func (c *cache) Resync() error {
227 return c.cacheStorage.Resync()
230 // NewStore returns a Store implemented simply with a map and a lock.
231 func NewStore(keyFunc KeyFunc) Store {
233 cacheStorage: NewThreadSafeStore(Indexers{}, Indices{}),
238 // NewIndexer returns an Indexer implemented simply with a map and a lock.
239 func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {
241 cacheStorage: NewThreadSafeStore(indexers, Indices{}),