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

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

Issue 1916463004: impl/memory: Disallow empty namespace. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/gae@master
Patch Set: Remove memcache. Created 4 years, 8 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/dummy/dummy.go ('k') | impl/memory/datastore_query_execution_test.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 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 "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, wantTxn bool) ds.Raw Interface {
23 » » ns := curGID(ic).namespace 23 » » ns, hasNS := curGID(ic).getNamespace()
24 maybeTxnCtx := cur(ic) 24 maybeTxnCtx := cur(ic)
25 25
26 needResetCtx := false 26 needResetCtx := false
27 if !wantTxn { 27 if !wantTxn {
28 rootctx := curNoTxn(ic) 28 rootctx := curNoTxn(ic)
29 if rootctx != maybeTxnCtx { 29 if rootctx != maybeTxnCtx {
30 needResetCtx = true 30 needResetCtx = true
31 maybeTxnCtx = rootctx 31 maybeTxnCtx = rootctx
32 } 32 }
33 } 33 }
34 34
35 dsd := maybeTxnCtx.Get(memContextDSIdx) 35 dsd := maybeTxnCtx.Get(memContextDSIdx)
36 if x, ok := dsd.(*dataStoreData); ok { 36 if x, ok := dsd.(*dataStoreData); ok {
37 if needResetCtx { 37 if needResetCtx {
38 ic = context.WithValue(ic, memContextKey, maybeT xnCtx) 38 ic = context.WithValue(ic, memContextKey, maybeT xnCtx)
39 } 39 }
40 » » » return &dsImpl{x, ns, ic} 40 » » » return &dsImpl{x, ns, hasNS, ic}
41 } 41 }
42 » » return &txnDsImpl{dsd.(*txnDataStoreData), ns} 42 » » return &txnDsImpl{dsd.(*txnDataStoreData), ns, hasNS}
43 }) 43 })
44 } 44 }
45 45
46 // NewDatastore creates a new standalone memory implementation of the datastore, 46 // NewDatastore creates a new standalone memory implementation of the datastore,
47 // suitable for embedding for doing in-memory data organization. 47 // suitable for embedding for doing in-memory data organization.
48 // 48 //
49 // It's configured by default with the following settings: 49 // It's configured by default with the following settings:
50 // * AutoIndex(true) 50 // * AutoIndex(true)
51 // * Consistent(true) 51 // * Consistent(true)
52 // * DisableSpecialEntities(true) 52 // * DisableSpecialEntities(true)
53 // 53 //
54 // These settings can of course be changed by using the Testable() interface. 54 // These settings can of course be changed by using the Testable() interface.
55 func NewDatastore(aid, ns string) (ds.Interface, error) { 55 func NewDatastore(aid, ns string) (ds.Interface, error) {
56 ctx := UseWithAppID(context.Background(), aid) 56 ctx := UseWithAppID(context.Background(), aid)
57 » ctx, err := info.Get(ctx).Namespace(ns) 57
58 » if err != nil { 58 » if ns != "" {
59 » » return nil, err 59 » » var err error
60 » » ctx, err = info.Get(ctx).Namespace(ns)
61 » » if err != nil {
62 » » » return nil, err
63 » » }
60 } 64 }
65
61 ret := ds.Get(ctx) 66 ret := ds.Get(ctx)
62 t := ret.Testable() 67 t := ret.Testable()
63 t.AutoIndex(true) 68 t.AutoIndex(true)
64 t.Consistent(true) 69 t.Consistent(true)
65 t.DisableSpecialEntities(true) 70 t.DisableSpecialEntities(true)
66 return ret, nil 71 return ret, nil
67 } 72 }
68 73
69 //////////////////////////////////// dsImpl //////////////////////////////////// 74 //////////////////////////////////// dsImpl ////////////////////////////////////
70 75
71 // dsImpl exists solely to bind the current c to the datastore data. 76 // dsImpl exists solely to bind the current c to the datastore data.
72 type dsImpl struct { 77 type dsImpl struct {
73 » data *dataStoreData 78 » data *dataStoreData
74 » ns string 79 » ns string
75 » c context.Context 80 » hasNS bool
81 » c context.Context
76 } 82 }
77 83
78 var _ ds.RawInterface = (*dsImpl)(nil) 84 var _ ds.RawInterface = (*dsImpl)(nil)
79 85
80 func (d *dsImpl) AllocateIDs(incomplete *ds.Key, n int) (int64, error) { 86 func (d *dsImpl) AllocateIDs(incomplete *ds.Key, n int) (int64, error) {
81 return d.data.allocateIDs(incomplete, n) 87 return d.data.allocateIDs(incomplete, n)
82 } 88 }
83 89
84 func (d *dsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMultiC B) error { 90 func (d *dsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMultiC B) error {
85 d.data.putMulti(keys, vals, cb) 91 d.data.putMulti(keys, vals, cb)
86 return nil 92 return nil
87 } 93 }
88 94
89 func (d *dsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMul tiCB) error { 95 func (d *dsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMul tiCB) error {
90 return d.data.getMulti(keys, cb) 96 return d.data.getMulti(keys, cb)
91 } 97 }
92 98
93 func (d *dsImpl) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) error { 99 func (d *dsImpl) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) error {
94 d.data.delMulti(keys, cb) 100 d.data.delMulti(keys, cb)
95 return nil 101 return nil
96 } 102 }
97 103
98 func (d *dsImpl) DecodeCursor(s string) (ds.Cursor, error) { 104 func (d *dsImpl) DecodeCursor(s string) (ds.Cursor, error) {
99 return newCursor(s) 105 return newCursor(s)
100 } 106 }
101 107
102 func (d *dsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error { 108 func (d *dsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error {
109 if err := assertQueryNamespace(d.ns, d.hasNS); err != nil {
110 return err
111 }
112
103 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent()) 113 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent())
104 err := executeQuery(fq, d.data.aid, d.ns, false, idx, head, cb) 114 err := executeQuery(fq, d.data.aid, d.ns, false, idx, head, cb)
105 if d.data.maybeAutoIndex(err) { 115 if d.data.maybeAutoIndex(err) {
106 idx, head = d.data.getQuerySnaps(!fq.EventuallyConsistent()) 116 idx, head = d.data.getQuerySnaps(!fq.EventuallyConsistent())
107 err = executeQuery(fq, d.data.aid, d.ns, false, idx, head, cb) 117 err = executeQuery(fq, d.data.aid, d.ns, false, idx, head, cb)
108 } 118 }
109 return err 119 return err
110 } 120 }
111 121
112 func (d *dsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) { 122 func (d *dsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) {
123 if err := assertQueryNamespace(d.ns, d.hasNS); err != nil {
124 return 0, err
125 }
126
113 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent()) 127 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent())
114 ret, err = countQuery(fq, d.data.aid, d.ns, false, idx, head) 128 ret, err = countQuery(fq, d.data.aid, d.ns, false, idx, head)
115 if d.data.maybeAutoIndex(err) { 129 if d.data.maybeAutoIndex(err) {
116 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent()) 130 idx, head := d.data.getQuerySnaps(!fq.EventuallyConsistent())
117 ret, err = countQuery(fq, d.data.aid, d.ns, false, idx, head) 131 ret, err = countQuery(fq, d.data.aid, d.ns, false, idx, head)
118 } 132 }
119 return 133 return
120 } 134 }
121 135
122 func (d *dsImpl) AddIndexes(idxs ...*ds.IndexDefinition) { 136 func (d *dsImpl) AddIndexes(idxs ...*ds.IndexDefinition) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 d.data.setDisableSpecialEntities(enabled) 175 d.data.setDisableSpecialEntities(enabled)
162 } 176 }
163 177
164 func (d *dsImpl) Testable() ds.Testable { 178 func (d *dsImpl) Testable() ds.Testable {
165 return d 179 return d
166 } 180 }
167 181
168 ////////////////////////////////// txnDsImpl /////////////////////////////////// 182 ////////////////////////////////// txnDsImpl ///////////////////////////////////
169 183
170 type txnDsImpl struct { 184 type txnDsImpl struct {
171 » data *txnDataStoreData 185 » data *txnDataStoreData
172 » ns string 186 » ns string
187 » hasNS bool
173 } 188 }
174 189
175 var _ ds.RawInterface = (*txnDsImpl)(nil) 190 var _ ds.RawInterface = (*txnDsImpl)(nil)
176 191
177 func (d *txnDsImpl) AllocateIDs(incomplete *ds.Key, n int) (int64, error) { 192 func (d *txnDsImpl) AllocateIDs(incomplete *ds.Key, n int) (int64, error) {
178 return d.data.parent.allocateIDs(incomplete, n) 193 return d.data.parent.allocateIDs(incomplete, n)
179 } 194 }
180 195
181 func (d *txnDsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMul tiCB) error { 196 func (d *txnDsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMul tiCB) error {
182 return d.data.run(func() error { 197 return d.data.run(func() error {
(...skipping 12 matching lines...) Expand all
195 return d.data.run(func() error { 210 return d.data.run(func() error {
196 return d.data.delMulti(keys, cb) 211 return d.data.delMulti(keys, cb)
197 }) 212 })
198 } 213 }
199 214
200 func (d *txnDsImpl) DecodeCursor(s string) (ds.Cursor, error) { 215 func (d *txnDsImpl) DecodeCursor(s string) (ds.Cursor, error) {
201 return newCursor(s) 216 return newCursor(s)
202 } 217 }
203 218
204 func (d *txnDsImpl) Run(q *ds.FinalizedQuery, cb ds.RawRunCB) error { 219 func (d *txnDsImpl) Run(q *ds.FinalizedQuery, cb ds.RawRunCB) error {
220 if err := assertQueryNamespace(d.ns, d.hasNS); err != nil {
221 return err
222 }
223
205 // note that autoIndex has no effect inside transactions. This is becaus e 224 // note that autoIndex has no effect inside transactions. This is becaus e
206 // the transaction guarantees a consistent view of head at the time that the 225 // the transaction guarantees a consistent view of head at the time that the
207 // transaction opens. At best, we could add the index on head, but then return 226 // transaction opens. At best, we could add the index on head, but then return
208 // the error anyway, but adding the index then re-snapping at head would 227 // the error anyway, but adding the index then re-snapping at head would
209 // potentially reveal other entities not in the original transaction sna pshot. 228 // potentially reveal other entities not in the original transaction sna pshot.
210 // 229 //
211 // It's possible that if you have full-consistency and also auto index e nabled 230 // It's possible that if you have full-consistency and also auto index e nabled
212 // that this would make sense... but at that point you should probably j ust 231 // that this would make sense... but at that point you should probably j ust
213 // add the index up front. 232 // add the index up front.
214 return executeQuery(q, d.data.parent.aid, d.ns, true, d.data.snap, d.dat a.snap, cb) 233 return executeQuery(q, d.data.parent.aid, d.ns, true, d.data.snap, d.dat a.snap, cb)
215 } 234 }
216 235
217 func (d *txnDsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) { 236 func (d *txnDsImpl) Count(fq *ds.FinalizedQuery) (ret int64, err error) {
237 if err := assertQueryNamespace(d.ns, d.hasNS); err != nil {
238 return 0, err
239 }
240
218 return countQuery(fq, d.data.parent.aid, d.ns, true, d.data.snap, d.data .snap) 241 return countQuery(fq, d.data.parent.aid, d.ns, true, d.data.snap, d.data .snap)
219 } 242 }
220 243
221 func (*txnDsImpl) RunInTransaction(func(c context.Context) error, *ds.Transactio nOptions) error { 244 func (*txnDsImpl) RunInTransaction(func(c context.Context) error, *ds.Transactio nOptions) error {
222 return errors.New("datastore: nested transactions are not supported") 245 return errors.New("datastore: nested transactions are not supported")
223 } 246 }
224 247
225 func (*txnDsImpl) Testable() ds.Testable { 248 func (*txnDsImpl) Testable() ds.Testable {
226 return nil 249 return nil
227 } 250 }
251
252 func assertQueryNamespace(ns string, hasNS bool) error {
253 if ns == "" && hasNS {
254 // The user has set an empty namespace. Datastore does not suppo rt this
255 // for queries.
iannucci 2016/04/23 19:19:08 link to bug
256 return errors.New("namespace may not be present and empty")
257 }
258 return nil
259 }
OLDNEW
« no previous file with comments | « impl/dummy/dummy.go ('k') | impl/memory/datastore_query_execution_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698