store.go 7.5 KB

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