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 |