store.go 9.3 KB

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