store.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2019 Yunion
  2. //
  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. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package cache
  15. import (
  16. "fmt"
  17. )
  18. // Store is a generic object storage interface. Reflector knows how to watch a server
  19. // and update a store. A generic store is provided, which allows Reflector to be used
  20. // as a local caching system, and an LRU store, which allows Reflector to work like a
  21. // queue of items yet to be processed.
  22. //
  23. // Store makes no assumptions about stored object identity; it is the responsibility
  24. // of a Store implementation to provide a mechanism to correctly key objects and to
  25. // define the contract for obtaining objects by some arbitrary key type.
  26. type Store interface {
  27. Add(obj interface{}) error
  28. Update(obj interface{}) error
  29. Delete(obj interface{}) error
  30. List() []interface{}
  31. ListKeys() []string
  32. Get(obj interface{}) (item interface{}, exists bool, err error)
  33. GetByKey(key string) (item interface{}, exists bool, err error)
  34. // Replace will delete the contents of the store, using instead the
  35. // given list. Store takes ownership of the list, you should not reference
  36. // it after calling this function.
  37. Replace([]interface{}, string) error
  38. Resync() error
  39. }
  40. // KeyFunc knows how to make a key from an object. Implementations should be deterministic.
  41. type KeyFunc func(obj interface{}) (string, error)
  42. // KeyError will be returned any time a KeyFunc gives an error; it includes the object
  43. // at fault.
  44. type KeyError struct {
  45. Obj interface{}
  46. Err error
  47. }
  48. // Error gives a human-readable description of the error.
  49. func (k KeyError) Error() string {
  50. return fmt.Sprintf("couldn't create key for object %+v: %v", k.Obj, k.Err)
  51. }
  52. // cache responsibilities are limited to:
  53. // 1. Computing keys for objects via keyFunc
  54. // 2. Invoking methods of a ThreadSafeStorage interface
  55. type cache struct {
  56. // cacheStorage bears the burden of thread safety for the cache
  57. cacheStorage ThreadSafeStore
  58. // keyFunc is used to make the key for objects stored in and retrieved from items, and
  59. // should be deterministic.
  60. keyFunc KeyFunc
  61. }
  62. var _ Store = &cache{}
  63. // Add inserts an item into the cache.
  64. func (c *cache) Add(obj interface{}) error {
  65. key, err := c.keyFunc(obj)
  66. if err != nil {
  67. return KeyError{obj, err}
  68. }
  69. c.cacheStorage.Add(key, obj)
  70. return nil
  71. }
  72. // Update sets an item in the cache to its updated state.
  73. func (c *cache) Update(obj interface{}) error {
  74. key, err := c.keyFunc(obj)
  75. if err != nil {
  76. return KeyError{obj, err}
  77. }
  78. c.cacheStorage.Update(key, obj)
  79. return nil
  80. }
  81. // Delete removes an item from the cache.
  82. func (c *cache) Delete(obj interface{}) error {
  83. key, err := c.keyFunc(obj)
  84. if err != nil {
  85. return KeyError{obj, err}
  86. }
  87. c.cacheStorage.Delete(key)
  88. return nil
  89. }
  90. // List returns a list of all the items.
  91. // List is completely threadsafe as long as you treat all items as immutable.
  92. func (c *cache) List() []interface{} {
  93. return c.cacheStorage.List()
  94. }
  95. // ListKeys returns a list of all the keys of the objects currently
  96. // in the cache.
  97. func (c *cache) ListKeys() []string {
  98. return c.cacheStorage.ListKeys()
  99. }
  100. // GetIndexers returns the indexers of cache
  101. func (c *cache) GetIndexers() Indexers {
  102. return c.cacheStorage.GetIndexers()
  103. }
  104. // Index returns a list of items that match on the index function
  105. // Index is thread-safe so long as you treat all items as immutable
  106. func (c *cache) Index(indexName string, obj interface{}) ([]interface{}, error) {
  107. return c.cacheStorage.Index(indexName, obj)
  108. }
  109. func (c *cache) IndexKeys(indexName, indexKey string) ([]string, error) {
  110. return c.cacheStorage.IndexKeys(indexName, indexKey)
  111. }
  112. // ListIndexFuncValues returns the list of generated values of an Index func
  113. func (c *cache) ListIndexFuncValues(indexName string) []string {
  114. return c.cacheStorage.ListIndexFuncValues(indexName)
  115. }
  116. func (c *cache) ByIndex(indexName, indexKey string) ([]interface{}, error) {
  117. return c.cacheStorage.ByIndex(indexName, indexKey)
  118. }
  119. func (c *cache) AddIndexers(newIndexers Indexers) error {
  120. return c.cacheStorage.AddIndexers(newIndexers)
  121. }
  122. // Get returns the requested item, or sets exists=false.
  123. // Get is completely threadsafe as long as you treat all items as immutable.
  124. func (c *cache) Get(obj interface{}) (item interface{}, exists bool, err error) {
  125. key, err := c.keyFunc(obj)
  126. if err != nil {
  127. return nil, false, KeyError{obj, err}
  128. }
  129. return c.GetByKey(key)
  130. }
  131. // GetByKey returns the request item, or exists=false.
  132. // GetByKey is completely threadsafe as long as you treat all items as immutable.
  133. func (c *cache) GetByKey(key string) (item interface{}, exists bool, err error) {
  134. item, exists = c.cacheStorage.Get(key)
  135. return item, exists, nil
  136. }
  137. // Replace will delete the contents of 'c', using instead the given list.
  138. // 'c' takes ownership of the list, you should not reference the list again
  139. // after calling this function.
  140. func (c *cache) Replace(list []interface{}, resourceVersion string) error {
  141. items := map[string]interface{}{}
  142. for _, item := range list {
  143. key, err := c.keyFunc(item)
  144. if err != nil {
  145. return KeyError{item, err}
  146. }
  147. items[key] = item
  148. }
  149. c.cacheStorage.Replace(items, resourceVersion)
  150. return nil
  151. }
  152. // Resync touches all items in the store to force processing
  153. func (c *cache) Resync() error {
  154. return c.cacheStorage.Resync()
  155. }
  156. // NewStore returns a Store implemented simply with a map and a lock.
  157. func NewStore(keyFunc KeyFunc) Store {
  158. return &cache{
  159. cacheStorage: NewThreadSafeStore(Indexers{}, Indices{}),
  160. keyFunc: keyFunc,
  161. }
  162. }
  163. // NewIndexer returns an Indexer implemented simply with a map and a lock.
  164. func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {
  165. return &cache{
  166. cacheStorage: NewThreadSafeStore(indexers, Indices{}),
  167. keyFunc: keyFunc,
  168. }
  169. }