| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package memory | 5 package memory |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "fmt" | 9 "fmt" |
| 10 "sync" | 10 "sync" |
| 11 "sync/atomic" | 11 "sync/atomic" |
| 12 | 12 |
| 13 ds "github.com/luci/gae/service/datastore" | 13 ds "github.com/luci/gae/service/datastore" |
| 14 "github.com/luci/gae/service/datastore/serialize" | 14 "github.com/luci/gae/service/datastore/serialize" |
| 15 "github.com/luci/luci-go/common/errors" | 15 "github.com/luci/luci-go/common/errors" |
| 16 "golang.org/x/net/context" | 16 "golang.org/x/net/context" |
| 17 ) | 17 ) |
| 18 | 18 |
| 19 //////////////////////////////// dataStoreData ///////////////////////////////// | 19 //////////////////////////////// dataStoreData ///////////////////////////////// |
| 20 | 20 |
| 21 type dataStoreData struct { | 21 type dataStoreData struct { |
| 22 rwlock sync.RWMutex | 22 rwlock sync.RWMutex |
| 23 // See README.md for head schema. | 23 // See README.md for head schema. |
| 24 head *memStore | 24 head *memStore |
| 25 snap *memStore | 25 snap *memStore |
| 26 // For testing, see SetTransactionRetryCount. | 26 // For testing, see SetTransactionRetryCount. |
| 27 txnFakeRetry int | 27 txnFakeRetry int |
| 28 // true means that head always == snap | 28 // true means that head always == snap |
| 29 consistent bool | 29 consistent bool |
| 30 // true means that queries with insufficent indexes will pause to add th
em |
| 31 // and then continue instead of failing. |
| 32 autoIndex bool |
| 30 } | 33 } |
| 31 | 34 |
| 32 var ( | 35 var ( |
| 33 _ = memContextObj((*dataStoreData)(nil)) | 36 _ = memContextObj((*dataStoreData)(nil)) |
| 34 _ = sync.Locker((*dataStoreData)(nil)) | 37 _ = sync.Locker((*dataStoreData)(nil)) |
| 35 ) | 38 ) |
| 36 | 39 |
| 37 func newDataStoreData() *dataStoreData { | 40 func newDataStoreData() *dataStoreData { |
| 38 head := newMemStore() | 41 head := newMemStore() |
| 39 return &dataStoreData{ | 42 return &dataStoreData{ |
| (...skipping 19 matching lines...) Expand all Loading... |
| 59 func (d *dataStoreData) setConsistent(always bool) { | 62 func (d *dataStoreData) setConsistent(always bool) { |
| 60 d.Lock() | 63 d.Lock() |
| 61 defer d.Unlock() | 64 defer d.Unlock() |
| 62 | 65 |
| 63 d.consistent = always | 66 d.consistent = always |
| 64 if d.consistent { | 67 if d.consistent { |
| 65 d.snap = d.head.Snapshot() | 68 d.snap = d.head.Snapshot() |
| 66 } | 69 } |
| 67 } | 70 } |
| 68 | 71 |
| 72 func (d *dataStoreData) addIndexes(ns string, idxs []*ds.IndexDefinition) { |
| 73 d.Lock() |
| 74 defer d.Unlock() |
| 75 addIndexes(d.head, ns, idxs) |
| 76 if d.consistent { |
| 77 d.snap = d.head.Snapshot() |
| 78 } |
| 79 } |
| 80 |
| 81 func (d *dataStoreData) setAutoIndex(enable bool) { |
| 82 d.Lock() |
| 83 defer d.Unlock() |
| 84 d.autoIndex = enable |
| 85 } |
| 86 |
| 87 func (d *dataStoreData) maybeAutoIndex(err error) bool { |
| 88 mi, ok := err.(*ErrMissingIndex) |
| 89 if !ok { |
| 90 return false |
| 91 } |
| 92 |
| 93 d.rwlock.RLock() |
| 94 ai := d.autoIndex |
| 95 d.rwlock.RUnlock() |
| 96 |
| 97 if !ai { |
| 98 return false |
| 99 } |
| 100 |
| 101 d.addIndexes(mi.ns, []*ds.IndexDefinition{mi.Missing}) |
| 102 return true |
| 103 } |
| 104 |
| 69 func (d *dataStoreData) getQuerySnaps(consistent bool) (idx, head *memStore) { | 105 func (d *dataStoreData) getQuerySnaps(consistent bool) (idx, head *memStore) { |
| 70 d.rwlock.RLock() | 106 d.rwlock.RLock() |
| 71 defer d.rwlock.RUnlock() | 107 defer d.rwlock.RUnlock() |
| 72 if d.consistent { | 108 if d.consistent { |
| 73 // snap is already a consistent snapshot of head | 109 // snap is already a consistent snapshot of head |
| 74 return d.snap, d.snap | 110 return d.snap, d.snap |
| 75 } | 111 } |
| 76 | 112 |
| 77 head = d.head.Snapshot() | 113 head = d.head.Snapshot() |
| 78 if consistent { | 114 if consistent { |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 | 525 |
| 490 func rpmWoCtx(data []byte, ns string) (ds.PropertyMap, error) { | 526 func rpmWoCtx(data []byte, ns string) (ds.PropertyMap, error) { |
| 491 return serialize.ReadPropertyMap(bytes.NewBuffer(data), | 527 return serialize.ReadPropertyMap(bytes.NewBuffer(data), |
| 492 serialize.WithoutContext, globalAppID, ns) | 528 serialize.WithoutContext, globalAppID, ns) |
| 493 } | 529 } |
| 494 | 530 |
| 495 func rpm(data []byte) (ds.PropertyMap, error) { | 531 func rpm(data []byte) (ds.PropertyMap, error) { |
| 496 return serialize.ReadPropertyMap(bytes.NewBuffer(data), | 532 return serialize.ReadPropertyMap(bytes.NewBuffer(data), |
| 497 serialize.WithContext, "", "") | 533 serialize.WithContext, "", "") |
| 498 } | 534 } |
| OLD | NEW |