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

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

Issue 1253263002: Make rawdatastore API safer for writing filters. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix comments Created 5 years, 4 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/raw_datastore.go ('k') | impl/memory/raw_datastore_query.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 "bytes" 8 "bytes"
9 "fmt" 9 "fmt"
10 "sync" 10 "sync"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } else { 100 } else {
101 idKey = groupIDsKey(key) 101 idKey = groupIDsKey(key)
102 } 102 }
103 id := incrementLocked(ents, idKey) 103 id := incrementLocked(ents, idKey)
104 key = rds.NewKey(key.AppID(), key.Namespace(), key.Kind(), "", i d, key.Parent()) 104 key = rds.NewKey(key.AppID(), key.Namespace(), key.Kind(), "", i d, key.Parent())
105 } 105 }
106 106
107 return ents, key 107 return ents, key
108 } 108 }
109 109
110 func (d *dataStoreData) put(ns string, key rds.Key, pls rds.PropertyLoadSaver) ( rds.Key, error) { 110 func (d *dataStoreData) putMulti(keys []rds.Key, vals []rds.PropertyLoadSaver, c b rds.PutMultiCB) {
111 » keys, errs := d.putMulti(ns, []rds.Key{key}, []rds.PropertyLoadSaver{pls })
112 » if errs == nil {
113 » » return keys[0], nil
114 » }
115 » return nil, errors.SingleError(errs)
116 }
117
118 func (d *dataStoreData) putMulti(ns string, keys []rds.Key, plss []rds.PropertyL oadSaver) ([]rds.Key, error) {
119 » pmaps, err := putMultiPrelim(ns, keys, plss)
120 » if err != nil {
121 » » return nil, err
122 » }
123 » return d.putMultiInner(keys, pmaps)
124 }
125
126 func putMultiPrelim(ns string, keys []rds.Key, plss []rds.PropertyLoadSaver) ([] rds.PropertyMap, error) {
127 » err := multiValid(keys, plss, ns, true, false)
128 » if err != nil {
129 » » return nil, err
130 » }
131 » pmaps := make([]rds.PropertyMap, len(keys))
132 » lme := errors.LazyMultiError{Size: len(keys)}
133 » for i, pls := range plss {
134 » » pm, err := pls.Save(false)
135 » » lme.Assign(i, err)
136 » » pmaps[i] = pm
137 » }
138 » return pmaps, lme.Get()
139 }
140
141 func (d *dataStoreData) putMultiInner(keys []rds.Key, data []rds.PropertyMap) ([ ]rds.Key, error) {
142 » retKeys := make([]rds.Key, len(keys))
143 » lme := errors.LazyMultiError{Size: len(keys)}
144 for i, k := range keys { 111 for i, k := range keys {
145 buf := &bytes.Buffer{} 112 buf := &bytes.Buffer{}
146 » » data[i].Write(buf, rds.WithoutContext) 113 » » pmap := vals[i].(rds.PropertyMap)
114 » » pmap.Write(buf, rds.WithoutContext)
147 dataBytes := buf.Bytes() 115 dataBytes := buf.Bytes()
148 116
149 » » rKey, err := func() (ret rds.Key, err error) { 117 » » k, err := func() (ret rds.Key, err error) {
150 d.rwlock.Lock() 118 d.rwlock.Lock()
151 defer d.rwlock.Unlock() 119 defer d.rwlock.Unlock()
152 120
153 ents, ret := d.entsKeyLocked(k) 121 ents, ret := d.entsKeyLocked(k)
154 incrementLocked(ents, groupMetaKey(ret)) 122 incrementLocked(ents, groupMetaKey(ret))
155 123
156 old := ents.Get(keyBytes(rds.WithoutContext, ret)) 124 old := ents.Get(keyBytes(rds.WithoutContext, ret))
157 oldPM := rds.PropertyMap(nil) 125 oldPM := rds.PropertyMap(nil)
158 if old != nil { 126 if old != nil {
159 if oldPM, err = rpmWoCtx(old, ret.Namespace()); err != nil { 127 if oldPM, err = rpmWoCtx(old, ret.Namespace()); err != nil {
160 return 128 return
161 } 129 }
162 } 130 }
163 » » » updateIndicies(d.store, ret, oldPM, data[i]) 131 » » » updateIndicies(d.store, ret, oldPM, pmap)
164 ents.Set(keyBytes(rds.WithoutContext, ret), dataBytes) 132 ents.Set(keyBytes(rds.WithoutContext, ret), dataBytes)
165 return 133 return
166 }() 134 }()
167 » » lme.Assign(i, err) 135 » » if cb != nil {
168 » » retKeys[i] = rKey 136 » » » cb(k, err)
137 » » }
169 } 138 }
170 return retKeys, lme.Get()
171 } 139 }
172 140
173 func getMultiInner(ns string, keys []rds.Key, plss []rds.PropertyLoadSaver, getC oll func() (*memCollection, error)) error { 141 func getMultiInner(keys []rds.Key, cb rds.GetMultiCB, getColl func() (*memCollec tion, error)) error {
174 » if err := multiValid(keys, plss, ns, false, true); err != nil {
175 » » return err
176 » }
177
178 » lme := errors.LazyMultiError{Size: len(keys)}
179
180 ents, err := getColl() 142 ents, err := getColl()
181 if err != nil { 143 if err != nil {
182 return err 144 return err
183 } 145 }
184 if ents == nil { 146 if ents == nil {
185 » » for i := range keys { 147 » » for range keys {
186 » » » lme.Assign(i, rds.ErrNoSuchEntity) 148 » » » cb(nil, rds.ErrNoSuchEntity)
187 } 149 }
188 » » return lme.Get() 150 » » return nil
189 } 151 }
190 152
191 » for i, k := range keys { 153 » for _, k := range keys {
192 pdata := ents.Get(keyBytes(rds.WithoutContext, k)) 154 pdata := ents.Get(keyBytes(rds.WithoutContext, k))
193 if pdata == nil { 155 if pdata == nil {
194 » » » lme.Assign(i, rds.ErrNoSuchEntity) 156 » » » cb(nil, rds.ErrNoSuchEntity)
195 continue 157 continue
196 } 158 }
197 159 » » cb(rpmWoCtx(pdata, k.Namespace()))
198 » » got, err := rpmWoCtx(pdata, ns)
199 » » if err != nil {
200 » » » lme.Assign(i, err)
201 » » » continue
202 » » }
203
204 » » lme.Assign(i, plss[i].Load(got))
205 } 160 }
206 » return lme.Get() 161 » return nil
207 } 162 }
208 163
209 func (d *dataStoreData) get(ns string, key rds.Key, pls rds.PropertyLoadSaver) e rror { 164 func (d *dataStoreData) getMulti(keys []rds.Key, cb rds.GetMultiCB) error {
210 » return errors.SingleError(d.getMulti(ns, []rds.Key{key}, []rds.PropertyL oadSaver{pls})) 165 » getMultiInner(keys, cb, func() (*memCollection, error) {
211 }
212
213 func (d *dataStoreData) getMulti(ns string, keys []rds.Key, plss []rds.PropertyL oadSaver) error {
214 » return getMultiInner(ns, keys, plss, func() (*memCollection, error) {
215 d.rwlock.RLock() 166 d.rwlock.RLock()
216 s := d.store.Snapshot() 167 s := d.store.Snapshot()
217 d.rwlock.RUnlock() 168 d.rwlock.RUnlock()
218 169
219 » » return s.GetCollection("ents:" + ns), nil 170 » » return s.GetCollection("ents:" + keys[0].Namespace()), nil
220 }) 171 })
172 return nil
221 } 173 }
222 174
223 func (d *dataStoreData) del(ns string, key rds.Key) (err error) { 175 func (d *dataStoreData) delMulti(keys []rds.Key, cb rds.DeleteMultiCB) {
224 » return errors.SingleError(d.delMulti(ns, []rds.Key{key}))
225 }
226
227 func (d *dataStoreData) delMulti(ns string, keys []rds.Key) error {
228 » lme := errors.LazyMultiError{Size: len(keys)}
229 toDel := make([][]byte, 0, len(keys)) 176 toDel := make([][]byte, 0, len(keys))
230 » for i, k := range keys { 177 » for _, k := range keys {
231 » » if !rds.KeyValid(k, ns, false) {
232 » » » lme.Assign(i, rds.ErrInvalidKey)
233 » » » continue
234 » » }
235 toDel = append(toDel, keyBytes(rds.WithoutContext, k)) 178 toDel = append(toDel, keyBytes(rds.WithoutContext, k))
236 } 179 }
237 » err := lme.Get() 180 » ns := keys[0].Namespace()
238 » if err != nil {
239 » » return err
240 » }
241 181
242 d.rwlock.Lock() 182 d.rwlock.Lock()
243 defer d.rwlock.Unlock() 183 defer d.rwlock.Unlock()
244 184
245 ents := d.store.GetCollection("ents:" + ns) 185 ents := d.store.GetCollection("ents:" + ns)
246 if ents == nil {
247 return nil
248 }
249 186
250 for i, k := range keys { 187 for i, k := range keys {
251 » » incrementLocked(ents, groupMetaKey(k)) 188 » » if ents != nil {
252 » » kb := toDel[i] 189 » » » incrementLocked(ents, groupMetaKey(k))
253 » » old := ents.Get(kb) 190 » » » kb := toDel[i]
254 » » oldPM := rds.PropertyMap(nil) 191 » » » if old := ents.Get(kb); old != nil {
255 » » if old != nil { 192 » » » » oldPM, err := rpmWoCtx(old, ns)
256 » » » if oldPM, err = rpmWoCtx(old, ns); err != nil { 193 » » » » if err != nil {
257 » » » » lme.Assign(i, err) 194 » » » » » if cb != nil {
258 » » » » continue 195 » » » » » » cb(err)
196 » » » » » }
197 » » » » » continue
198 » » » » }
199 » » » » updateIndicies(d.store, k, oldPM, nil)
200 » » » » ents.Delete(kb)
259 } 201 }
260 } 202 }
261 » » updateIndicies(d.store, k, oldPM, nil) 203 » » if cb != nil {
262 » » ents.Delete(kb) 204 » » » cb(nil)
205 » » }
263 } 206 }
264 return lme.Get()
265 } 207 }
266 208
267 func (d *dataStoreData) canApplyTxn(obj memContextObj) bool { 209 func (d *dataStoreData) canApplyTxn(obj memContextObj) bool {
268 // TODO(riannucci): implement with Flush/FlushRevert for persistance. 210 // TODO(riannucci): implement with Flush/FlushRevert for persistance.
269 211
270 txn := obj.(*txnDataStoreData) 212 txn := obj.(*txnDataStoreData)
271 for rk, muts := range txn.muts { 213 for rk, muts := range txn.muts {
272 if len(muts) == 0 { // read-only 214 if len(muts) == 0 { // read-only
273 continue 215 continue
274 } 216 }
(...skipping 14 matching lines...) Expand all
289 } 231 }
290 return true 232 return true
291 } 233 }
292 234
293 func (d *dataStoreData) applyTxn(c context.Context, obj memContextObj) { 235 func (d *dataStoreData) applyTxn(c context.Context, obj memContextObj) {
294 txn := obj.(*txnDataStoreData) 236 txn := obj.(*txnDataStoreData)
295 for _, muts := range txn.muts { 237 for _, muts := range txn.muts {
296 if len(muts) == 0 { // read-only 238 if len(muts) == 0 { // read-only
297 continue 239 continue
298 } 240 }
241 // TODO(riannucci): refactor to do just 1 putMulti, and 1 delMul ti
299 for _, m := range muts { 242 for _, m := range muts {
300 err := error(nil) 243 err := error(nil)
244 k := m.key
301 if m.data == nil { 245 if m.data == nil {
302 » » » » err = d.del(m.key.Namespace(), m.key) 246 » » » » d.delMulti([]rds.Key{k},
247 » » » » » func(e error) { err = e })
303 } else { 248 } else {
304 » » » » _, err = d.put(m.key.Namespace(), m.key, m.data) 249 » » » » d.putMulti([]rds.Key{m.key}, []rds.PropertyLoadS aver{m.data},
250 » » » » » func(_ rds.Key, e error) { err = e })
305 } 251 }
252 err = errors.SingleError(err)
306 if err != nil { 253 if err != nil {
307 panic(err) 254 panic(err)
308 } 255 }
309 } 256 }
310 } 257 }
311 } 258 }
312 259
313 func (d *dataStoreData) mkTxn(o *rds.TransactionOptions) memContextObj { 260 func (d *dataStoreData) mkTxn(o *rds.TransactionOptions) memContextObj {
314 return &txnDataStoreData{ 261 return &txnDataStoreData{
315 // alias to the main datastore's so that testing code can have p rimitive 262 // alias to the main datastore's so that testing code can have p rimitive
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 } 352 }
406 td.muts[rk] = []txnMutation{} 353 td.muts[rk] = []txnMutation{}
407 } 354 }
408 if !getOnly { 355 if !getOnly {
409 td.muts[rk] = append(td.muts[rk], txnMutation{key, data}) 356 td.muts[rk] = append(td.muts[rk], txnMutation{key, data})
410 } 357 }
411 358
412 return nil 359 return nil
413 } 360 }
414 361
415 func (td *txnDataStoreData) put(ns string, key rds.Key, pls rds.PropertyLoadSave r) (rds.Key, error) { 362 func (td *txnDataStoreData) putMulti(keys []rds.Key, vals []rds.PropertyLoadSave r, cb rds.PutMultiCB) {
416 » keys, errs := td.putMulti(ns, []rds.Key{key}, []rds.PropertyLoadSaver{pl s})
417 » if errs == nil {
418 » » return keys[0], nil
419 » }
420 » return nil, errors.SingleError(errs)
421 }
422
423 func (td *txnDataStoreData) putMulti(ns string, keys []rds.Key, plss []rds.Prope rtyLoadSaver) ([]rds.Key, error) {
424 » pmaps, err := putMultiPrelim(ns, keys, plss)
425 » if err != nil {
426 » » return nil, err
427 » }
428
429 » retKeys := make([]rds.Key, len(keys))
430 » lme := errors.LazyMultiError{Size: len(keys)}
431 for i, k := range keys { 363 for i, k := range keys {
432 func() { 364 func() {
433 td.parent.Lock() 365 td.parent.Lock()
434 defer td.parent.Unlock() 366 defer td.parent.Unlock()
435 _, k = td.parent.entsKeyLocked(k) 367 _, k = td.parent.entsKeyLocked(k)
436 }() 368 }()
437 » » lme.Assign(i, td.writeMutation(false, k, pmaps[i])) 369 » » err := td.writeMutation(false, k, vals[i].(rds.PropertyMap))
438 » » retKeys[i] = k 370 » » if cb != nil {
371 » » » cb(k, err)
372 » » }
439 } 373 }
440
441 return retKeys, lme.Get()
442 } 374 }
443 375
444 func (td *txnDataStoreData) get(ns string, key rds.Key, pls rds.PropertyLoadSave r) error { 376 func (td *txnDataStoreData) getMulti(keys []rds.Key, cb rds.GetMultiCB) error {
445 » return errors.SingleError(td.getMulti(ns, []rds.Key{key}, []rds.Property LoadSaver{pls})) 377 » return getMultiInner(keys, cb, func() (*memCollection, error) {
446 } 378 » » err := error(nil)
447 379 » » for _, key := range keys {
448 func (td *txnDataStoreData) getMulti(ns string, keys []rds.Key, plss []rds.Prope rtyLoadSaver) error { 380 » » » err = td.writeMutation(true, key, nil)
449 » return getMultiInner(ns, keys, plss, func() (*memCollection, error) { 381 » » » if err != nil {
450 » » lme := errors.LazyMultiError{Size: len(keys)} 382 » » » » return nil, err
451 » » for i, k := range keys { 383 » » » }
452 » » » lme.Assign(i, td.writeMutation(true, k, nil))
453 } 384 }
454 » » return td.snap.GetCollection("ents:" + ns), lme.Get() 385 » » return td.snap.GetCollection("ents:" + keys[0].Namespace()), nil
455 }) 386 })
456 } 387 }
457 388
458 func (td *txnDataStoreData) del(ns string, key rds.Key) error { 389 func (td *txnDataStoreData) delMulti(keys []rds.Key, cb rds.DeleteMultiCB) error {
459 » return errors.SingleError(td.delMulti(ns, []rds.Key{key})) 390 » for _, k := range keys {
460 } 391 » » err := td.writeMutation(false, k, nil)
461 392 » » if cb != nil {
462 func (td *txnDataStoreData) delMulti(ns string, keys []rds.Key) error { 393 » » » cb(err)
463 » lme := errors.LazyMultiError{Size: len(keys)}
464 » for i, k := range keys {
465 » » if !rds.KeyValid(k, ns, false) {
466 » » » lme.Assign(i, rds.ErrInvalidKey)
467 » » } else {
468 » » » lme.Assign(i, td.writeMutation(false, k, nil))
469 } 394 }
470 } 395 }
471 » return lme.Get() 396 » return nil
472 } 397 }
473 398
474 func keyBytes(ctx rds.KeyContext, key rds.Key) []byte { 399 func keyBytes(ctx rds.KeyContext, key rds.Key) []byte {
475 buf := &bytes.Buffer{} 400 buf := &bytes.Buffer{}
476 rds.WriteKey(buf, ctx, key) 401 rds.WriteKey(buf, ctx, key)
477 return buf.Bytes() 402 return buf.Bytes()
478 } 403 }
479 404
480 func rpmWoCtx(data []byte, ns string) (rds.PropertyMap, error) { 405 func rpmWoCtx(data []byte, ns string) (rds.PropertyMap, error) {
481 ret := rds.PropertyMap{} 406 ret := rds.PropertyMap{}
482 err := ret.Read(bytes.NewBuffer(data), rds.WithoutContext, globalAppID, ns) 407 err := ret.Read(bytes.NewBuffer(data), rds.WithoutContext, globalAppID, ns)
483 return ret, err 408 return ret, err
484 } 409 }
485 410
486 func rpm(data []byte) (rds.PropertyMap, error) { 411 func rpm(data []byte) (rds.PropertyMap, error) {
487 ret := rds.PropertyMap{} 412 ret := rds.PropertyMap{}
488 err := ret.Read(bytes.NewBuffer(data), rds.WithContext, "", "") 413 err := ret.Read(bytes.NewBuffer(data), rds.WithContext, "", "")
489 return ret, err 414 return ret, err
490 } 415 }
491 416
492 func multiValid(keys []rds.Key, plss []rds.PropertyLoadSaver, ns string, potenti alKey, allowSpecial bool) error { 417 type keyitem interface {
493 » vfn := func(k rds.Key) bool { 418 » Key() rds.Key
494 » » return !rds.KeyIncomplete(k) && rds.KeyValid(k, ns, allowSpecial )
495 » }
496 » if potentialKey {
497 » » vfn = func(k rds.Key) bool {
498 » » » // adds an id to k if it's incomplete.
499 » » » if rds.KeyIncomplete(k) {
500 » » » » k = rds.NewKey(k.AppID(), k.Namespace(), k.Kind( ), "", 1, k.Parent())
501 » » » }
502 » » » return rds.KeyValid(k, ns, allowSpecial)
503 » » }
504 » }
505
506 » if keys == nil || plss == nil {
507 » » return errors.New("gae: key or plss slices were nil")
508 » }
509 » if len(keys) != len(plss) {
510 » » return errors.New("gae: key and dst slices have different length ")
511 » }
512 » lme := errors.LazyMultiError{Size: len(keys)}
513 » for i, k := range keys {
514 » » if !vfn(k) {
515 » » » lme.Assign(i, rds.ErrInvalidKey)
516 » » }
517 » }
518 » return lme.Get()
519 } 419 }
OLDNEW
« no previous file with comments | « impl/memory/raw_datastore.go ('k') | impl/memory/raw_datastore_query.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698