cache.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package datastore
  2. import (
  3. "fmt"
  4. "sync"
  5. store "github.com/docker/docker/libnetwork/internal/kvstore"
  6. )
  7. type kvMap map[string]KVObject
  8. type cache struct {
  9. mu sync.Mutex
  10. kmm map[string]kvMap
  11. ds store.Store
  12. }
  13. func newCache(ds store.Store) *cache {
  14. return &cache{kmm: make(map[string]kvMap), ds: ds}
  15. }
  16. func (c *cache) kmap(kvObject KVObject) (kvMap, error) {
  17. var err error
  18. c.mu.Lock()
  19. keyPrefix := Key(kvObject.KeyPrefix()...)
  20. kmap, ok := c.kmm[keyPrefix]
  21. c.mu.Unlock()
  22. if ok {
  23. return kmap, nil
  24. }
  25. kmap = kvMap{}
  26. kvList, err := c.ds.List(keyPrefix)
  27. if err != nil {
  28. if err == store.ErrKeyNotFound {
  29. // If the store doesn't have anything then there is nothing to
  30. // populate in the cache. Just bail out.
  31. goto out
  32. }
  33. return nil, fmt.Errorf("error while populating kmap: %v", err)
  34. }
  35. for _, kvPair := range kvList {
  36. // Ignore empty kvPair values
  37. if len(kvPair.Value) == 0 {
  38. continue
  39. }
  40. dstO := kvObject.New()
  41. err = dstO.SetValue(kvPair.Value)
  42. if err != nil {
  43. return nil, err
  44. }
  45. // Make sure the object has a correct view of the DB index in
  46. // case we need to modify it and update the DB.
  47. dstO.SetIndex(kvPair.LastIndex)
  48. kmap[Key(dstO.Key()...)] = dstO
  49. }
  50. out:
  51. // There may multiple go routines racing to fill the
  52. // cache. The one which places the kmap in c.kmm first
  53. // wins. The others should just use what the first populated.
  54. c.mu.Lock()
  55. kmapNew, ok := c.kmm[keyPrefix]
  56. if ok {
  57. c.mu.Unlock()
  58. return kmapNew, nil
  59. }
  60. c.kmm[keyPrefix] = kmap
  61. c.mu.Unlock()
  62. return kmap, nil
  63. }
  64. func (c *cache) add(kvObject KVObject, atomic bool) error {
  65. kmap, err := c.kmap(kvObject)
  66. if err != nil {
  67. return err
  68. }
  69. c.mu.Lock()
  70. // If atomic is true, cache needs to maintain its own index
  71. // for atomicity and the add needs to be atomic.
  72. if atomic {
  73. if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
  74. if prev.Index() != kvObject.Index() {
  75. c.mu.Unlock()
  76. return ErrKeyModified
  77. }
  78. }
  79. // Increment index
  80. index := kvObject.Index()
  81. index++
  82. kvObject.SetIndex(index)
  83. }
  84. kmap[Key(kvObject.Key()...)] = kvObject
  85. c.mu.Unlock()
  86. return nil
  87. }
  88. func (c *cache) del(kvObject KVObject, atomic bool) error {
  89. kmap, err := c.kmap(kvObject)
  90. if err != nil {
  91. return err
  92. }
  93. c.mu.Lock()
  94. // If atomic is true, cache needs to maintain its own index
  95. // for atomicity and del needs to be atomic.
  96. if atomic {
  97. if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
  98. if prev.Index() != kvObject.Index() {
  99. c.mu.Unlock()
  100. return ErrKeyModified
  101. }
  102. }
  103. }
  104. delete(kmap, Key(kvObject.Key()...))
  105. c.mu.Unlock()
  106. return nil
  107. }
  108. func (c *cache) get(kvObject KVObject) error {
  109. kmap, err := c.kmap(kvObject)
  110. if err != nil {
  111. return err
  112. }
  113. c.mu.Lock()
  114. defer c.mu.Unlock()
  115. o, ok := kmap[Key(kvObject.Key()...)]
  116. if !ok {
  117. return ErrKeyNotFound
  118. }
  119. return o.CopyTo(kvObject)
  120. }
  121. func (c *cache) list(kvObject KVObject) ([]KVObject, error) {
  122. kmap, err := c.kmap(kvObject)
  123. if err != nil {
  124. return nil, err
  125. }
  126. c.mu.Lock()
  127. defer c.mu.Unlock()
  128. var kvol []KVObject
  129. for _, v := range kmap {
  130. kvol = append(kvol, v)
  131. }
  132. return kvol, nil
  133. }