Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1572)

Side by Side Diff: impl/memory/datastore.go

Issue 2302743002: Interface update, per-method Contexts. (Closed)
Patch Set: Lightning talk licenses. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « impl/memory/context.go ('k') | impl/memory/datastore_data.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package memory 5 package memory
6 6
7 import ( 7 import (
8 "errors" 8 "errors"
9 "fmt" 9 "fmt"
10 10
11 "golang.org/x/net/context" 11 "golang.org/x/net/context"
12 12
13 ds "github.com/luci/gae/service/datastore" 13 ds "github.com/luci/gae/service/datastore"
14 "github.com/luci/gae/service/info" 14 "github.com/luci/gae/service/info"
15 ) 15 )
16 16
17 //////////////////////////////////// public //////////////////////////////////// 17 //////////////////////////////////// public ////////////////////////////////////
18 18
19 // useRDS adds a gae.Datastore implementation to context, accessible 19 // useRDS adds a gae.Datastore implementation to context, accessible
20 // by gae.GetDS(c) 20 // by gae.GetDS(c)
21 func useRDS(c context.Context) context.Context { 21 func useRDS(c context.Context) context.Context {
22 » return ds.SetRawFactory(c, func(ic context.Context, wantTxn bool) ds.Raw Interface { 22 » return ds.SetRawFactory(c, func(ic context.Context) ds.RawInterface {
23 » » ns, hasNS := curGID(ic).getNamespace() 23 » » kc := ds.GetKeyContext(ic)
24 » » maybeTxnCtx := cur(ic) 24 » » memCtx, isTxn := cur(ic)
25 25 » » dsd := memCtx.Get(memContextDSIdx)
26 » » needResetCtx := false 26 » » if isTxn {
27 » » if !wantTxn { 27 » » » return &txnDsImpl{ic, dsd.(*txnDataStoreData), kc}
28 » » » rootctx := curNoTxn(ic)
29 » » » if rootctx != maybeTxnCtx {
30 » » » » needResetCtx = true
31 » » » » maybeTxnCtx = rootctx
32 » » » }
33 } 28 }
34 29 » » return &dsImpl{ic, dsd.(*dataStoreData), kc}
35 » » dsd := maybeTxnCtx.Get(memContextDSIdx)
36 » » if x, ok := dsd.(*dataStoreData); ok {
37 » » » if needResetCtx {
38 » » » » ic = context.WithValue(ic, memContextKey, maybeT xnCtx)
39 » » » }
40 » » » return &dsImpl{x, ns, hasNS, ic}
41 » » }
42 » » return &txnDsImpl{dsd.(*txnDataStoreData), ns, hasNS}
43 }) 30 })
44 } 31 }
45 32
46 // NewDatastore creates a new standalone memory implementation of the datastore, 33 // NewDatastore creates a new standalone memory implementation of the datastore,
47 // suitable for embedding for doing in-memory data organization. 34 // suitable for embedding for doing in-memory data organization.
48 // 35 //
49 // It's configured by default with the following settings: 36 // It's configured by default with the following settings:
50 // * AutoIndex(true) 37 // * AutoIndex(true)
51 // * Consistent(true) 38 // * Consistent(true)
52 // * DisableSpecialEntities(true) 39 // * DisableSpecialEntities(true)
53 // 40 //
54 // These settings can of course be changed by using the Testable() interface. 41 // These settings can of course be changed by using the Testable interface.
55 func NewDatastore(inf info.Interface) ds.Interface { 42 func NewDatastore(c context.Context, inf info.RawInterface) ds.RawInterface {
56 » fqAppID := inf.FullyQualifiedAppID() 43 » kc := ds.GetKeyContext(c)
57 » ns, hasNS := inf.GetNamespace()
58 44
59 » memctx := newMemContext(fqAppID) 45 » memctx := newMemContext(kc.AppID)
60 46
61 dsCtx := info.Set(context.Background(), inf) 47 dsCtx := info.Set(context.Background(), inf)
62 » rds := &dsImpl{memctx.Get(memContextDSIdx).(*dataStoreData), ns, hasNS, dsCtx} 48 » rds := &dsImpl{dsCtx, memctx.Get(memContextDSIdx).(*dataStoreData), kc}
63 49
64 » ret := ds.Get(ds.SetRaw(dsCtx, rds)) 50 » ret := ds.Raw(ds.SetRaw(dsCtx, rds))
65 » t := ret.Testable() 51 » t := ret.GetTestable()
66 t.AutoIndex(true) 52 t.AutoIndex(true)
67 t.Consistent(true) 53 t.Consistent(true)
68 t.DisableSpecialEntities(true) 54 t.DisableSpecialEntities(true)
69 55
70 return ret 56 return ret
71 } 57 }
72 58
73 //////////////////////////////////// dsImpl //////////////////////////////////// 59 //////////////////////////////////// dsImpl ////////////////////////////////////
74 60
75 // dsImpl exists solely to bind the current c to the datastore data. 61 // dsImpl exists solely to bind the current c to the datastore data.
76 type dsImpl struct { 62 type dsImpl struct {
77 » data *dataStoreData 63 » context.Context
78 » ns string 64
79 » hasNS bool 65 » data *dataStoreData
80 » c context.Context 66 » kc ds.KeyContext
81 } 67 }
82 68
83 var _ ds.RawInterface = (*dsImpl)(nil) 69 var _ ds.RawInterface = (*dsImpl)(nil)
84 70
85 func (d *dsImpl) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error { 71 func (d *dsImpl) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error {
86 return d.data.allocateIDs(keys, cb) 72 return d.data.allocateIDs(keys, cb)
87 } 73 }
88 74
89 func (d *dsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKeyCB) error { 75 func (d *dsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKeyCB) error {
90 d.data.putMulti(keys, vals, cb) 76 d.data.putMulti(keys, vals, cb)
91 return nil 77 return nil
92 } 78 }
93 79
94 func (d *dsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMul tiCB) error { 80 func (d *dsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMul tiCB) error {
95 return d.data.getMulti(keys, cb) 81 return d.data.getMulti(keys, cb)
96 } 82 }
97 83
98 func (d *dsImpl) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) error { 84 func (d *dsImpl) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) error {
99 d.data.delMulti(keys, cb) 85 d.data.delMulti(keys, cb)
100 return nil 86 return nil
101 } 87 }
102 88
103 func (d *dsImpl) DecodeCursor(s string) (ds.Cursor, error) { 89 func (d *dsImpl) DecodeCursor(s string) (ds.Cursor, error) {
104 return newCursor(s) 90 return newCursor(s)
105 } 91 }
106 92
107 func (d *dsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error { 93 func (d *dsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error {
108 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent()) 94 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent())
109 » err := executeQuery(fq, d.data.aid, d.ns, false, idx, head, cb) 95 » err := executeQuery(fq, d.kc, false, idx, head, cb)
110 if d.data.maybeAutoIndex(err) { 96 if d.data.maybeAutoIndex(err) {
111 idx, head = d.data.getQuerySnaps(!fq.EventuallyConsistent()) 97 idx, head = d.data.getQuerySnaps(!fq.EventuallyConsistent())
112 » » err = executeQuery(fq, d.data.aid, d.ns, false, idx, head, cb) 98 » » err = executeQuery(fq, d.kc, false, idx, head, cb)
113 } 99 }
114 return err 100 return err
115 } 101 }
116 102
117 func (d *dsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) { 103 func (d *dsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) {
118 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent()) 104 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent())
119 » ret, err = countQuery(fq, d.data.aid, d.ns, false, idx, head) 105 » ret, err = countQuery(fq, d.kc, false, idx, head)
120 if d.data.maybeAutoIndex(err) { 106 if d.data.maybeAutoIndex(err) {
121 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent()) 107 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent())
122 » » ret, err = countQuery(fq, d.data.aid, d.ns, false, idx, head) 108 » » ret, err = countQuery(fq, d.kc, false, idx, head)
123 } 109 }
124 return 110 return
125 } 111 }
126 112
113 func (d *dsImpl) WithoutTransaction() context.Context {
114 // Already not in a Transaction.
115 return d
116 }
117
118 func (*dsImpl) CurrentTransaction() ds.Transaction { return nil }
119
127 func (d *dsImpl) AddIndexes(idxs ...*ds.IndexDefinition) { 120 func (d *dsImpl) AddIndexes(idxs ...*ds.IndexDefinition) {
128 if len(idxs) == 0 { 121 if len(idxs) == 0 {
129 return 122 return
130 } 123 }
131 124
132 for _, i := range idxs { 125 for _, i := range idxs {
133 if !i.Compound() { 126 if !i.Compound() {
134 panic(fmt.Errorf("Attempted to add non-compound index: % s", i)) 127 panic(fmt.Errorf("Attempted to add non-compound index: % s", i))
135 } 128 }
136 } 129 }
(...skipping 22 matching lines...) Expand all
159 } 152 }
160 153
161 func (d *dsImpl) AutoIndex(enable bool) { 154 func (d *dsImpl) AutoIndex(enable bool) {
162 d.data.setAutoIndex(enable) 155 d.data.setAutoIndex(enable)
163 } 156 }
164 157
165 func (d *dsImpl) DisableSpecialEntities(enabled bool) { 158 func (d *dsImpl) DisableSpecialEntities(enabled bool) {
166 d.data.setDisableSpecialEntities(enabled) 159 d.data.setDisableSpecialEntities(enabled)
167 } 160 }
168 161
169 func (d *dsImpl) Testable() ds.Testable { 162 func (d *dsImpl) GetTestable() ds.Testable { return d }
170 » return d
171 }
172 163
173 ////////////////////////////////// txnDsImpl /////////////////////////////////// 164 ////////////////////////////////// txnDsImpl ///////////////////////////////////
174 165
175 type txnDsImpl struct { 166 type txnDsImpl struct {
176 » data *txnDataStoreData 167 » context.Context
177 » ns string 168
178 » hasNS bool 169 » data *txnDataStoreData
170 » kc ds.KeyContext
179 } 171 }
180 172
181 var _ ds.RawInterface = (*txnDsImpl)(nil) 173 var _ ds.RawInterface = (*txnDsImpl)(nil)
182 174
183 func (d *txnDsImpl) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error { 175 func (d *txnDsImpl) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error {
184 return d.data.parent.allocateIDs(keys, cb) 176 return d.data.parent.allocateIDs(keys, cb)
185 } 177 }
186 178
187 func (d *txnDsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKey CB) error { 179 func (d *txnDsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKey CB) error {
188 return d.data.run(func() error { 180 return d.data.run(func() error {
189 d.data.putMulti(keys, vals, cb) 181 d.data.putMulti(keys, vals, cb)
190 return nil 182 return nil
191 }) 183 })
192 } 184 }
193 185
194 func (d *txnDsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.Get MultiCB) error { 186 func (d *txnDsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.Get MultiCB) error {
195 return d.data.run(func() error { 187 return d.data.run(func() error {
196 return d.data.getMulti(keys, cb) 188 return d.data.getMulti(keys, cb)
197 }) 189 })
198 } 190 }
199 191
200 func (d *txnDsImpl) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) error { 192 func (d *txnDsImpl) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) error {
201 return d.data.run(func() error { 193 return d.data.run(func() error {
202 return d.data.delMulti(keys, cb) 194 return d.data.delMulti(keys, cb)
203 }) 195 })
204 } 196 }
205 197
206 func (d *txnDsImpl) DecodeCursor(s string) (ds.Cursor, error) { 198 func (d *txnDsImpl) DecodeCursor(s string) (ds.Cursor, error) { return newCursor (s) }
207 » return newCursor(s)
208 }
209 199
210 func (d *txnDsImpl) Run(q *ds.FinalizedQuery, cb ds.RawRunCB) error { 200 func (d *txnDsImpl) Run(q *ds.FinalizedQuery, cb ds.RawRunCB) error {
211 // note that autoIndex has no effect inside transactions. This is becaus e 201 // note that autoIndex has no effect inside transactions. This is becaus e
212 // the transaction guarantees a consistent view of head at the time that the 202 // the transaction guarantees a consistent view of head at the time that the
213 // transaction opens. At best, we could add the index on head, but then return 203 // transaction opens. At best, we could add the index on head, but then return
214 // the error anyway, but adding the index then re-snapping at head would 204 // the error anyway, but adding the index then re-snapping at head would
215 // potentially reveal other entities not in the original transaction sna pshot. 205 // potentially reveal other entities not in the original transaction sna pshot.
216 // 206 //
217 // It's possible that if you have full-consistency and also auto index e nabled 207 // It's possible that if you have full-consistency and also auto index e nabled
218 // that this would make sense... but at that point you should probably j ust 208 // that this would make sense... but at that point you should probably j ust
219 // add the index up front. 209 // add the index up front.
220 » return executeQuery(q, d.data.parent.aid, d.ns, true, d.data.snap, d.dat a.snap, cb) 210 » return executeQuery(q, d.kc, true, d.data.snap, d.data.snap, cb)
221 } 211 }
222 212
223 func (d *txnDsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) { 213 func (d *txnDsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) {
224 » return countQuery(fq, d.data.parent.aid, d.ns, true, d.data.snap, d.data .snap) 214 » return countQuery(fq, d.kc, true, d.data.snap, d.data.snap)
225 } 215 }
226 216
227 func (*txnDsImpl) RunInTransaction(func(c context.Context) error, *ds.Transactio nOptions) error { 217 func (*txnDsImpl) RunInTransaction(func(c context.Context) error, *ds.Transactio nOptions) error {
228 return errors.New("datastore: nested transactions are not supported") 218 return errors.New("datastore: nested transactions are not supported")
229 } 219 }
230 220
231 func (*txnDsImpl) Testable() ds.Testable { 221 func (d *txnDsImpl) WithoutTransaction() context.Context {
232 » return nil 222 » return context.WithValue(d, currentTxnKey, nil)
233 } 223 }
224
225 func (d *txnDsImpl) CurrentTransaction() ds.Transaction {
226 return d.data.txn
227 }
228
229 func (d *txnDsImpl) GetTestable() ds.Testable { return nil }
OLDNEW
« no previous file with comments | « impl/memory/context.go ('k') | impl/memory/datastore_data.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698