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

Side by Side Diff: service/datastore/datastore.go

Issue 2011773002: datastore: variadic Get, Put, Exists, Delete. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/gae@master
Patch Set: Created 4 years, 7 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
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 datastore 5 package datastore
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "io" 9 "io"
10 "io/ioutil" 10 "io/ioutil"
(...skipping 19 matching lines...) Expand all
30 30
31 func (d *datastoreImpl) KeyForObj(src interface{}) *Key { 31 func (d *datastoreImpl) KeyForObj(src interface{}) *Key {
32 ret, err := d.KeyForObjErr(src) 32 ret, err := d.KeyForObjErr(src)
33 if err != nil { 33 if err != nil {
34 panic(err) 34 panic(err)
35 } 35 }
36 return ret 36 return ret
37 } 37 }
38 38
39 func (d *datastoreImpl) KeyForObjErr(src interface{}) (*Key, error) { 39 func (d *datastoreImpl) KeyForObjErr(src interface{}) (*Key, error) {
40 » return newKeyObjErr(d.aid, d.ns, src) 40 » return newKeyObjErr(d.aid, d.ns, getMGS(src))
41 } 41 }
42 42
43 func (d *datastoreImpl) MakeKey(elems ...interface{}) *Key { 43 func (d *datastoreImpl) MakeKey(elems ...interface{}) *Key {
44 return MakeKey(d.aid, d.ns, elems...) 44 return MakeKey(d.aid, d.ns, elems...)
45 } 45 }
46 46
47 func (d *datastoreImpl) NewKey(kind, stringID string, intID int64, parent *Key) *Key { 47 func (d *datastoreImpl) NewKey(kind, stringID string, intID int64, parent *Key) *Key {
48 return NewKey(d.aid, d.ns, kind, stringID, intID, parent) 48 return NewKey(d.aid, d.ns, kind, stringID, intID, parent)
49 } 49 }
50 50
(...skipping 14 matching lines...) Expand all
65 if lst.StringID != "" { 65 if lst.StringID != "" {
66 pls.SetMeta("id", lst.StringID) 66 pls.SetMeta("id", lst.StringID)
67 } else { 67 } else {
68 pls.SetMeta("id", lst.IntID) 68 pls.SetMeta("id", lst.IntID)
69 } 69 }
70 pls.SetMeta("kind", lst.Kind) 70 pls.SetMeta("kind", lst.Kind)
71 pls.SetMeta("parent", key.Parent()) 71 pls.SetMeta("parent", key.Parent())
72 } 72 }
73 } 73 }
74 74
75 func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat multiArgType) { 75 func checkMultiSliceType(v interface{}) error {
76 » if reflect.TypeOf(v).Kind() == reflect.Slice {
77 » » return nil
78 » }
79 » return fmt.Errorf("argument must be a slice, not %T", v)
80
81 }
82
83 func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat *multiArgType) {
76 badSig := func() { 84 badSig := func() {
77 panic(fmt.Errorf( 85 panic(fmt.Errorf(
78 "cb does not match the required callback signature: `%T` != `func(TYPE, [CursorCB]) [error]`", 86 "cb does not match the required callback signature: `%T` != `func(TYPE, [CursorCB]) [error]`",
79 cbIface)) 87 cbIface))
80 } 88 }
81 89
82 if cbIface == nil { 90 if cbIface == nil {
83 badSig() 91 badSig()
84 } 92 }
85 93
86 // TODO(riannucci): Profile and determine if any of this is causing a re al 94 // TODO(riannucci): Profile and determine if any of this is causing a re al
87 // slowdown. Could potentially cache reflection stuff by cbTyp? 95 // slowdown. Could potentially cache reflection stuff by cbTyp?
88 cbTyp := reflect.TypeOf(cbIface) 96 cbTyp := reflect.TypeOf(cbIface)
89 97
90 if cbTyp.Kind() != reflect.Func { 98 if cbTyp.Kind() != reflect.Func {
91 badSig() 99 badSig()
92 } 100 }
93 101
94 numIn := cbTyp.NumIn() 102 numIn := cbTyp.NumIn()
95 if numIn != 1 && numIn != 2 { 103 if numIn != 1 && numIn != 2 {
96 badSig() 104 badSig()
97 } 105 }
98 106
99 firstArg := cbTyp.In(0) 107 firstArg := cbTyp.In(0)
100 if firstArg == typeOfKey { 108 if firstArg == typeOfKey {
101 isKey = true 109 isKey = true
102 } else { 110 } else {
103 » » mat = parseArg(firstArg, false) 111 » » mat = mustParseArg(firstArg)
104 if mat.newElem == nil { 112 if mat.newElem == nil {
105 badSig() 113 badSig()
106 } 114 }
107 } 115 }
108 116
109 hasCursorCB = numIn == 2 117 hasCursorCB = numIn == 2
110 if hasCursorCB && cbTyp.In(1) != typeOfCursorCB { 118 if hasCursorCB && cbTyp.In(1) != typeOfCursorCB {
111 badSig() 119 badSig()
112 } 120 }
113 121
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 *keys = append(*keys, k) 219 *keys = append(*keys, k)
212 return nil 220 return nil
213 }) 221 })
214 } 222 }
215 fq, err := q.Finalize() 223 fq, err := q.Finalize()
216 if err != nil { 224 if err != nil {
217 return err 225 return err
218 } 226 }
219 227
220 slice := v.Elem() 228 slice := v.Elem()
221 » mat := parseMultiArg(slice.Type()) 229 » mat := mustParseMultiArg(slice.Type())
222 if mat.newElem == nil { 230 if mat.newElem == nil {
223 panic(fmt.Errorf("invalid GetAll dst (non-concrete element type) : %T", dst)) 231 panic(fmt.Errorf("invalid GetAll dst (non-concrete element type) : %T", dst))
224 } 232 }
225 233
226 errs := map[int]error{} 234 errs := map[int]error{}
227 i := 0 235 i := 0
228 err = filterStop(d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ C ursorCB) error { 236 err = filterStop(d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ C ursorCB) error {
229 slice.Set(reflect.Append(slice, mat.newElem())) 237 slice.Set(reflect.Append(slice, mat.newElem()))
230 itm := slice.Index(i) 238 itm := slice.Index(i)
231 mat.setKey(itm, k) 239 mat.setKey(itm, k)
232 err := mat.setPM(itm, pm) 240 err := mat.setPM(itm, pm)
233 if err != nil { 241 if err != nil {
234 errs[i] = err 242 errs[i] = err
235 } 243 }
236 i++ 244 i++
237 return nil 245 return nil
238 })) 246 }))
239 if err == nil { 247 if err == nil {
240 if len(errs) > 0 { 248 if len(errs) > 0 {
241 me := make(errors.MultiError, slice.Len()) 249 me := make(errors.MultiError, slice.Len())
242 for i, e := range errs { 250 for i, e := range errs {
243 me[i] = e 251 me[i] = e
244 } 252 }
245 err = me 253 err = me
246 } 254 }
247 } 255 }
248 return err 256 return err
249 } 257 }
250 258
251 func isOkType(t reflect.Type) error { 259 func (d *datastoreImpl) ExistsMulti(keys ...*Key) (BoolList, error) {
dnj 2016/05/25 05:27:15 This check is moved into "multiarg.go".
252 » if t == nil {
253 » » return errors.New("no type information")
254 » }
255 » if t.Implements(typeOfPropertyLoadSaver) {
256 » » return nil
257 » }
258 » if t == typeOfKey {
259 » » return errors.New("not user datatype")
260 » }
261 » if t.Kind() != reflect.Ptr {
262 » » return errors.New("not a pointer")
263 » }
264 » if t.Elem().Kind() != reflect.Struct {
265 » » return errors.New("does not point to a struct")
266 » }
267 » return nil
268 }
269
270 func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) {
271 lme := errors.NewLazyMultiError(len(keys)) 260 lme := errors.NewLazyMultiError(len(keys))
272 ret := make(BoolList, len(keys)) 261 ret := make(BoolList, len(keys))
273 i := 0 262 i := 0
274 err := filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error { 263 err := filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error {
275 if err == nil { 264 if err == nil {
276 ret[i] = true 265 ret[i] = true
277 } else if err != ErrNoSuchEntity { 266 } else if err != ErrNoSuchEntity {
278 lme.Assign(i, err) 267 lme.Assign(i, err)
279 } 268 }
280 i++ 269 i++
281 return nil 270 return nil
282 })) 271 }))
283 if err != nil { 272 if err != nil {
284 return ret, err 273 return ret, err
285 } 274 }
286 return ret, lme.Get() 275 return ret, lme.Get()
287 } 276 }
288 277
289 func (d *datastoreImpl) Exists(k *Key) (bool, error) { 278 func (d *datastoreImpl) Exists(k *Key) (bool, error) {
290 » ret, err := d.ExistsMulti([]*Key{k}) 279 » ret, err := d.ExistsMulti(k)
291 return ret[0], errors.SingleError(err) 280 return ret[0], errors.SingleError(err)
292 } 281 }
293 282
294 func (d *datastoreImpl) Get(dst interface{}) (err error) { 283 func (d *datastoreImpl) Get(dst ...interface{}) (err error) {
295 » if err := isOkType(reflect.TypeOf(dst)); err != nil { 284 » mma, err := makeMetaMultiArg(dst)
296 » » panic(fmt.Errorf("invalid Get input type (%T): %s", dst, err)) 285 » if err != nil {
286 » » panic(err)
297 } 287 }
298 return errors.SingleError(d.GetMulti([]interface{}{dst}))
299 }
300 288
301 func (d *datastoreImpl) Put(src interface{}) (err error) { 289 » keys, pms, err := mma.getKeysPMs(d.aid, d.ns, true)
302 » if err := isOkType(reflect.TypeOf(src)); err != nil {
303 » » panic(fmt.Errorf("invalid Put input type (%T): %s", src, err))
304 » }
305 » return errors.SingleError(d.PutMulti([]interface{}{src}))
306 }
307
308 func (d *datastoreImpl) Delete(key *Key) (err error) {
309 » return errors.SingleError(d.DeleteMulti([]*Key{key}))
310 }
311
312 func (d *datastoreImpl) GetMulti(dst interface{}) error {
313 » slice := reflect.ValueOf(dst)
314 » mat := parseMultiArg(slice.Type())
315
316 » keys, pms, err := mat.GetKeysPMs(d.aid, d.ns, slice, true)
317 if err != nil { 290 if err != nil {
318 return err 291 return err
319 } 292 }
320 293
321 lme := errors.NewLazyMultiError(len(keys))
322 i := 0 294 i := 0
295 it := mma.iterator()
323 meta := NewMultiMetaGetter(pms) 296 meta := NewMultiMetaGetter(pms)
324 err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap , err error) error { 297 err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap , err error) error {
325 » » if !lme.Assign(i, err) { 298 » » it.next(func(mat *multiArgType, slot reflect.Value) error {
dnj 2016/05/25 05:27:15 Just a quick explanation, since Rietveld sorted th
326 » » » lme.Assign(i, mat.setPM(slice.Index(i), pm)) 299 » » » if err != nil {
327 » » } 300 » » » » return err
301 » » » }
302 » » » return mat.setPM(slot, pm)
303 » » })
304
328 i++ 305 i++
329 return nil 306 return nil
330 })) 307 }))
331 308
332 if err == nil { 309 if err == nil {
333 » » err = lme.Get() 310 » » err = it.error()
dnj 2016/05/25 05:27:15 (This returns the MultiError accumulated by "it").
311
312 » » if err != nil && len(dst) == 1 {
313 » » » // Single-argument Get will return a single error.
314 » » » err = errors.SingleError(err)
315 » » }
316 » }
317 » return err
318 }
319
320 func (d *datastoreImpl) GetMulti(dst interface{}) error {
321 » if err := checkMultiSliceType(dst); err != nil {
322 » » panic(err)
323 » }
324 » return d.Get(dst)
325 }
326
327 func (d *datastoreImpl) Put(src ...interface{}) (err error) {
328 » mma, err := makeMetaMultiArg(src)
329 » if err != nil {
330 » » panic(err)
331 » }
332
333 » keys, vals, err := mma.getKeysPMs(d.aid, d.ns, false)
334 » if err != nil {
335 » » return err
336 » }
337
338 » i := 0
339 » it := mma.iterator()
340 » err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) error {
341 » » it.next(func(mat *multiArgType, slot reflect.Value) error {
342 » » » if err != nil {
343 » » » » return err
344 » » » }
345 » » » if key != keys[i] {
346 » » » » mat.setKey(slot, key)
347 » » » }
348 » » » return nil
349 » » })
350
351 » » i++
352 » » return nil
353 » }))
354
355 » if err == nil {
356 » » err = it.error()
357
358 » » if err != nil && len(src) == 1 {
359 » » » // Single-argument Get will return a single error.
360 » » » err = errors.SingleError(err)
361 » » }
334 } 362 }
335 return err 363 return err
336 } 364 }
337 365
338 func (d *datastoreImpl) PutMulti(src interface{}) error { 366 func (d *datastoreImpl) PutMulti(src interface{}) error {
339 » slice := reflect.ValueOf(src) 367 » if err := checkMultiSliceType(src); err != nil {
340 » mat := parseMultiArg(slice.Type()) 368 » » panic(err)
341
342 » keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice, false)
343 » if err != nil {
344 » » return err
345 } 369 }
346 370 » return d.Put(src)
347 » lme := errors.NewLazyMultiError(len(keys))
348 » i := 0
349 » err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) error {
350 » » if !lme.Assign(i, err) && key != keys[i] {
351 » » » mat.setKey(slice.Index(i), key)
352 » » }
353 » » i++
354 » » return nil
355 » }))
356
357 » if err == nil {
358 » » err = lme.Get()
359 » }
360 » return err
361 } 371 }
362 372
363 func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) { 373 func (d *datastoreImpl) Delete(key *Key) (err error) {
374 » return errors.SingleError(d.DeleteMulti(key))
375 }
376
377 func (d *datastoreImpl) DeleteMulti(keys ...*Key) (err error) {
364 lme := errors.NewLazyMultiError(len(keys)) 378 lme := errors.NewLazyMultiError(len(keys))
365 i := 0 379 i := 0
366 extErr := filterStop(d.RawInterface.DeleteMulti(keys, func(internalErr e rror) error { 380 extErr := filterStop(d.RawInterface.DeleteMulti(keys, func(internalErr e rror) error {
367 lme.Assign(i, internalErr) 381 lme.Assign(i, internalErr)
368 i++ 382 i++
369 return nil 383 return nil
370 })) 384 }))
371 err = lme.Get() 385 err = lme.Get()
372 if err == nil { 386 if err == nil {
373 err = extErr 387 err = extErr
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 currentDir = filepath.Dir(currentDir) 475 currentDir = filepath.Dir(currentDir)
462 } 476 }
463 } 477 }
464 478
465 func filterStop(err error) error { 479 func filterStop(err error) error {
466 if err == Stop { 480 if err == Stop {
467 err = nil 481 err = nil
468 } 482 }
469 return err 483 return err
470 } 484 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698