store.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. )
  19. // Store is a generic object storage and processing interface. A
  20. // Store holds a map from string keys to accumulators, and has
  21. // operations to add, update, and delete a given object to/from the
  22. // accumulator currently associated with a given key. A Store also
  23. // knows how to extract the key from a given object, so many operations
  24. // are given only the object.
  25. //
  26. // In the simplest Store implementations each accumulator is simply
  27. // the last given object, or empty after Delete, and thus the Store's
  28. // behavior is simple storage.
  29. //
  30. // Reflector knows how to watch a server and update a Store. This
  31. // package provides a variety of implementations of Store.
  32. type Store interface {
  33. // Add adds the given object to the accumulator associated with the given object's key
  34. Add(obj interface{}) error
  35. // Update updates the given object in the accumulator associated with the given object's key
  36. Update(obj interface{}) error
  37. // Delete deletes the given object from the accumulator associated with the given object's key
  38. Delete(obj interface{}) error
  39. // List returns a list of all the currently non-empty accumulators
  40. List() []interface{}
  41. // ListKeys returns a list of all the keys currently associated with non-empty accumulators
  42. ListKeys() []string
  43. // Get returns the accumulator associated with the given object's key
  44. Get(obj interface{}) (item interface{}, exists bool, err error)
  45. // GetByKey returns the accumulator associated with the given key
  46. GetByKey(key string) (item interface{}, exists bool, err error)
  47. // Replace will delete the contents of the store, using instead the
  48. // given list. Store takes ownership of the list, you should not reference
  49. // it after calling this function.
  50. Replace([]interface{}, string) error
  51. // Resync is meaningless in the terms appearing here but has
  52. // meaning in some implementations that have non-trivial
  53. // additional behavior (e.g., DeltaFIFO).
  54. Resync() error
  55. }
  56. // KeyFunc knows how to make a key from an object. Implementations should be deterministic.
  57. type KeyFunc func(obj interface{}) (string, error)
  58. // KeyError will be returned any time a KeyFunc gives an error; it includes the object
  59. // at fault.
  60. type KeyError struct {
  61. Obj interface{}
  62. Err error
  63. }
  64. // Error gives a human-readable description of the error.
  65. func (k KeyError) Error() string {
  66. return fmt.Sprintf("couldn't create key for object %+v: %v", k.Obj, k.Err)
  67. }
  68. // ExplicitKey can be passed to MetaNamespaceKeyFunc if you have the key for
  69. // the object but not the object itself.
  70. type ExplicitKey string
  71. // MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make
  72. // keys for API objects which implement meta.Interface.
  73. // The key uses the format <namespace>/<name> unless <namespace> is empty, then
  74. // it's just <name>.
  75. //
  76. // TODO: replace key-as-string with a key-as-struct so that this
  77. // packing/unpacking won't be necessary.
  78. func MetaNamespaceKeyFunc(obj interface{}) (string, error) {
  79. if key, ok := obj.(ExplicitKey); ok {
  80. return string(key), nil
  81. }
  82. meta, err := meta.Accessor(obj)
  83. if err != nil {
  84. return "", fmt.Errorf("object has no meta: %v", err)
  85. }
  86. if len(meta.GetNamespace()) > 0 {
  87. return meta.GetNamespace() + "/" + meta.GetName(), nil
  88. }
  89. return meta.GetName(), nil
  90. }
  91. // SplitMetaNamespaceKey returns the namespace and name that
  92. // MetaNamespaceKeyFunc encoded into key.
  93. //
  94. // TODO: replace key-as-string with a key-as-struct so that this
  95. // packing/unpacking won't be necessary.
  96. func SplitMetaNamespaceKey(key string) (namespace, name string, err error) {
  97. parts := strings.Split(key, "/")
  98. switch len(parts) {
  99. case 1:
  100. // name only, no namespace
  101. return "", parts[0], nil
  102. case 2:
  103. // namespace and name
  104. return parts[0], parts[1], nil
  105. }
  106. return "", "", fmt.Errorf("unexpected key format: %q", key)
  107. }
  108. // `*cache` implements Indexer in terms of a ThreadSafeStore and an
  109. // associated KeyFunc.
  110. type cache struct {
  111. // cacheStorage bears the burden of thread safety for the cache
  112. cacheStorage ThreadSafeStore
  113. // keyFunc is used to make the key for objects stored in and retrieved from items, and
  114. // should be deterministic.
  115. keyFunc KeyFunc
  116. }
  117. var _ Store = &cache{}
  118. // Add inserts an item into the cache.
  119. func (c *cache) Add(obj interface{}) error {
  120. key, err := c.keyFunc(obj)
  121. if err != nil {
  122. return KeyError{obj, err}
  123. }
  124. c.cacheStorage.Add(key, obj)
  125. return nil
  126. }
  127. // Update sets an item in the cache to its updated state.
  128. func (c *cache) Update(obj interface{}) error {
  129. key, err := c.keyFunc(obj)
  130. if err != nil {
  131. return KeyError{obj, err}
  132. }
  133. c.cacheStorage.Update(key, obj)
  134. return nil
  135. }
  136. // Delete removes an item from the cache.
  137. func (c *cache) Delete(obj interface{}) error {
  138. key, err := c.keyFunc(obj)
  139. if err != nil {
  140. return KeyError{obj, err}
  141. }
  142. c.cacheStorage.Delete(key)
  143. return nil
  144. }
  145. // List returns a list of all the items.
  146. // List is completely threadsafe as long as you treat all items as immutable.
  147. func (c *cache) List() []interface{} {
  148. return c.cacheStorage.List()
  149. }
  150. // ListKeys returns a list of all the keys of the objects currently
  151. // in the cache.
  152. func (c *cache) ListKeys() []string {
  153. return c.cacheStorage.ListKeys()
  154. }
  155. // GetIndexers returns the indexers of cache
  156. func (c *cache) GetIndexers() Indexers {
  157. return c.cacheStorage.GetIndexers()
  158. }
  159. // Index returns a list of items that match on the index function
  160. // Index is thread-safe so long as you treat all items as immutable
  161. func (c *cache) Index(indexName string, obj interface{}) ([]interface{}, error) {
  162. return c.cacheStorage.Index(indexName, obj)
  163. }
  164. func (c *cache) IndexKeys(indexName, indexKey string) ([]string, error) {
  165. return c.cacheStorage.IndexKeys(indexName, indexKey)
  166. }
  167. // ListIndexFuncValues returns the list of generated values of an Index func
  168. func (c *cache) ListIndexFuncValues(indexName string) []string {
  169. return c.cacheStorage.ListIndexFuncValues(indexName)
  170. }
  171. func (c *cache) ByIndex(indexName, indexKey string) ([]interface{}, error) {
  172. return c.cacheStorage.ByIndex(indexName, indexKey)
  173. }
  174. func (c *cache) AddIndexers(newIndexers Indexers) error {
  175. return c.cacheStorage.AddIndexers(newIndexers)
  176. }
  177. // Get returns the requested item, or sets exists=false.
  178. // Get is completely threadsafe as long as you treat all items as immutable.
  179. func (c *cache) Get(obj interface{}) (item interface{}, exists bool, err error) {
  180. key, err := c.keyFunc(obj)
  181. if err != nil {
  182. return nil, false, KeyError{obj, err}
  183. }
  184. return c.GetByKey(key)
  185. }
  186. // GetByKey returns the request item, or exists=false.
  187. // GetByKey is completely threadsafe as long as you treat all items as immutable.
  188. func (c *cache) GetByKey(key string) (item interface{}, exists bool, err error) {
  189. item, exists = c.cacheStorage.Get(key)
  190. return item, exists, nil
  191. }
  192. // Replace will delete the contents of 'c', using instead the given list.
  193. // 'c' takes ownership of the list, you should not reference the list again
  194. // after calling this function.
  195. func (c *cache) Replace(list []interface{}, resourceVersion string) error {
  196. items := make(map[string]interface{}, len(list))
  197. for _, item := range list {
  198. key, err := c.keyFunc(item)
  199. if err != nil {
  200. return KeyError{item, err}
  201. }
  202. items[key] = item
  203. }
  204. c.cacheStorage.Replace(items, resourceVersion)
  205. return nil
  206. }
  207. // Resync is meaningless for one of these
  208. func (c *cache) Resync() error {
  209. return nil
  210. }
  211. // NewStore returns a Store implemented simply with a map and a lock.
  212. func NewStore(keyFunc KeyFunc) Store {
  213. return &cache{
  214. cacheStorage: NewThreadSafeStore(Indexers{}, Indices{}),
  215. keyFunc: keyFunc,
  216. }
  217. }
  218. // NewIndexer returns an Indexer implemented simply with a map and a lock.
  219. func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {
  220. return &cache{
  221. cacheStorage: NewThreadSafeStore(indexers, Indices{}),
  222. keyFunc: keyFunc,
  223. }
  224. }