Since the datastore interface is common for persistent and
non-persistent objects we need to provide the same kind of sequencing
and atomicity guarantess to non-persistent data operations as we do for
persistent operations. So added sequencing and atomicity checks in the
data cache layer.
Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
| ... | ... |
@@ -86,25 +86,52 @@ out: |
| 86 | 86 |
return kmap, nil |
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 |
-func (c *cache) add(kvObject KVObject) error {
|
|
| 89 |
+func (c *cache) add(kvObject KVObject, atomic bool) error {
|
|
| 90 | 90 |
kmap, err := c.kmap(kvObject) |
| 91 | 91 |
if err != nil {
|
| 92 | 92 |
return err |
| 93 | 93 |
} |
| 94 | 94 |
|
| 95 | 95 |
c.Lock() |
| 96 |
+ // If atomic is true, cache needs to maintain its own index |
|
| 97 |
+ // for atomicity and the add needs to be atomic. |
|
| 98 |
+ if atomic {
|
|
| 99 |
+ if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
|
|
| 100 |
+ if prev.Index() != kvObject.Index() {
|
|
| 101 |
+ c.Unlock() |
|
| 102 |
+ return ErrKeyModified |
|
| 103 |
+ } |
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ // Increment index |
|
| 107 |
+ index := kvObject.Index() |
|
| 108 |
+ index++ |
|
| 109 |
+ kvObject.SetIndex(index) |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 96 | 112 |
kmap[Key(kvObject.Key()...)] = kvObject |
| 97 | 113 |
c.Unlock() |
| 98 | 114 |
return nil |
| 99 | 115 |
} |
| 100 | 116 |
|
| 101 |
-func (c *cache) del(kvObject KVObject) error {
|
|
| 117 |
+func (c *cache) del(kvObject KVObject, atomic bool) error {
|
|
| 102 | 118 |
kmap, err := c.kmap(kvObject) |
| 103 | 119 |
if err != nil {
|
| 104 | 120 |
return err |
| 105 | 121 |
} |
| 106 | 122 |
|
| 107 | 123 |
c.Lock() |
| 124 |
+ // If atomic is true, cache needs to maintain its own index |
|
| 125 |
+ // for atomicity and del needs to be atomic. |
|
| 126 |
+ if atomic {
|
|
| 127 |
+ if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
|
|
| 128 |
+ if prev.Index() != kvObject.Index() {
|
|
| 129 |
+ c.Unlock() |
|
| 130 |
+ return ErrKeyModified |
|
| 131 |
+ } |
|
| 132 |
+ } |
|
| 133 |
+ } |
|
| 134 |
+ |
|
| 108 | 135 |
delete(kmap, Key(kvObject.Key()...)) |
| 109 | 136 |
c.Unlock() |
| 110 | 137 |
return nil |
| ... | ... |
@@ -410,7 +410,9 @@ func (ds *datastore) PutObjectAtomic(kvObject KVObject) error {
|
| 410 | 410 |
|
| 411 | 411 |
add_cache: |
| 412 | 412 |
if ds.cache != nil {
|
| 413 |
- return ds.cache.add(kvObject) |
|
| 413 |
+ // If persistent store is skipped, sequencing needs to |
|
| 414 |
+ // happen in cache. |
|
| 415 |
+ return ds.cache.add(kvObject, kvObject.Skip()) |
|
| 414 | 416 |
} |
| 415 | 417 |
|
| 416 | 418 |
return nil |
| ... | ... |
@@ -435,7 +437,9 @@ func (ds *datastore) PutObject(kvObject KVObject) error {
|
| 435 | 435 |
|
| 436 | 436 |
add_cache: |
| 437 | 437 |
if ds.cache != nil {
|
| 438 |
- return ds.cache.add(kvObject) |
|
| 438 |
+ // If persistent store is skipped, sequencing needs to |
|
| 439 |
+ // happen in cache. |
|
| 440 |
+ return ds.cache.add(kvObject, kvObject.Skip()) |
|
| 439 | 441 |
} |
| 440 | 442 |
|
| 441 | 443 |
return nil |
| ... | ... |
@@ -537,7 +541,9 @@ func (ds *datastore) DeleteObject(kvObject KVObject) error {
|
| 537 | 537 |
|
| 538 | 538 |
// cleaup the cache first |
| 539 | 539 |
if ds.cache != nil {
|
| 540 |
- ds.cache.del(kvObject) |
|
| 540 |
+ // If persistent store is skipped, sequencing needs to |
|
| 541 |
+ // happen in cache. |
|
| 542 |
+ ds.cache.del(kvObject, kvObject.Skip()) |
|
| 541 | 543 |
} |
| 542 | 544 |
|
| 543 | 545 |
if kvObject.Skip() {
|
| ... | ... |
@@ -572,7 +578,9 @@ func (ds *datastore) DeleteObjectAtomic(kvObject KVObject) error {
|
| 572 | 572 |
del_cache: |
| 573 | 573 |
// cleanup the cache only if AtomicDelete went through successfully |
| 574 | 574 |
if ds.cache != nil {
|
| 575 |
- return ds.cache.del(kvObject) |
|
| 575 |
+ // If persistent store is skipped, sequencing needs to |
|
| 576 |
+ // happen in cache. |
|
| 577 |
+ return ds.cache.del(kvObject, kvObject.Skip()) |
|
| 576 | 578 |
} |
| 577 | 579 |
|
| 578 | 580 |
return nil |
| ... | ... |
@@ -585,7 +593,9 @@ func (ds *datastore) DeleteTree(kvObject KVObject) error {
|
| 585 | 585 |
|
| 586 | 586 |
// cleaup the cache first |
| 587 | 587 |
if ds.cache != nil {
|
| 588 |
- ds.cache.del(kvObject) |
|
| 588 |
+ // If persistent store is skipped, sequencing needs to |
|
| 589 |
+ // happen in cache. |
|
| 590 |
+ ds.cache.del(kvObject, kvObject.Skip()) |
|
| 589 | 591 |
} |
| 590 | 592 |
|
| 591 | 593 |
if kvObject.Skip() {
|