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

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: s/chn/chan/ Created 4 years, 6 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 | « no previous file | service/datastore/datastore_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 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) Exists(ent ...interface{}) (*ExistsResult, error) {
252 » if t == nil { 260 » mma, err := makeMetaMultiArg(ent, true)
253 » » return errors.New("no type information") 261 » if err != nil {
262 » » panic(err)
254 } 263 }
255 » if t.Implements(typeOfPropertyLoadSaver) { 264
265 » keys, _, err := mma.getKeysPMs(d.aid, d.ns, false)
266 » if err != nil {
267 » » return nil, err
268 » }
269
270 » i := 0
271 » var bt boolTracker
272 » it := mma.iterator(bt.init(mma))
273 » err = filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error {
274 » » it.next(func(*multiArgType, reflect.Value) error {
275 » » » return err
276 » » })
277 » » i++
256 return nil 278 return nil
279 }))
280 if err == nil {
281 err = bt.error()
282
283 if err != nil && len(ent) == 1 {
284 // Single-argument Exists will return a single error.
285 err = errors.SingleError(err)
286 }
257 } 287 }
258 » if t == typeOfKey { 288 » return bt.result(), err
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 } 289 }
269 290
270 func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) { 291 func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) {
271 » lme := errors.NewLazyMultiError(len(keys)) 292 » v, err := d.Exists(keys)
272 » ret := make(BoolList, len(keys))
273 » i := 0
274 » err := filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error {
275 » » if err == nil {
276 » » » ret[i] = true
277 » » } else if err != ErrNoSuchEntity {
278 » » » lme.Assign(i, err)
279 » » }
280 » » i++
281 » » return nil
282 » }))
283 if err != nil { 293 if err != nil {
284 » » return ret, err 294 » » return nil, err
285 } 295 }
286 » return ret, lme.Get() 296 » return v.List(0), nil
287 } 297 }
288 298
289 func (d *datastoreImpl) Exists(k *Key) (bool, error) { 299 func (d *datastoreImpl) Get(dst ...interface{}) (err error) {
290 » ret, err := d.ExistsMulti([]*Key{k}) 300 » mma, err := makeMetaMultiArg(dst, false)
291 » return ret[0], errors.SingleError(err) 301 » if err != nil {
292 } 302 » » panic(err)
303 » }
293 304
294 func (d *datastoreImpl) Get(dst interface{}) (err error) { 305 » keys, pms, err := mma.getKeysPMs(d.aid, d.ns, true)
295 » if err := isOkType(reflect.TypeOf(dst)); err != nil {
296 » » panic(fmt.Errorf("invalid Get input type (%T): %s", dst, err))
297 » }
298 » return errors.SingleError(d.GetMulti([]interface{}{dst}))
299 }
300
301 func (d *datastoreImpl) Put(src interface{}) (err error) {
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 { 306 if err != nil {
318 return err 307 return err
319 } 308 }
320 309
321 lme := errors.NewLazyMultiError(len(keys))
322 i := 0 310 i := 0
311 var et errorTracker
312 it := mma.iterator(et.init(mma))
323 meta := NewMultiMetaGetter(pms) 313 meta := NewMultiMetaGetter(pms)
324 err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap , err error) error { 314 err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap , err error) error {
325 » » if !lme.Assign(i, err) { 315 » » it.next(func(mat *multiArgType, slot reflect.Value) error {
326 » » » lme.Assign(i, mat.setPM(slice.Index(i), pm)) 316 » » » if err != nil {
327 » » } 317 » » » » return err
318 » » » }
319 » » » return mat.setPM(slot, pm)
320 » » })
321
328 i++ 322 i++
329 return nil 323 return nil
330 })) 324 }))
331 325
332 if err == nil { 326 if err == nil {
333 » » err = lme.Get() 327 » » err = et.error()
328
329 » » if err != nil && len(dst) == 1 {
330 » » » // Single-argument Get will return a single error.
331 » » » err = errors.SingleError(err)
332 » » }
333 » }
334 » return err
335 }
336
337 func (d *datastoreImpl) GetMulti(dst interface{}) error {
338 » if err := checkMultiSliceType(dst); err != nil {
339 » » panic(err)
340 » }
341 » return d.Get(dst)
342 }
343
344 func (d *datastoreImpl) Put(src ...interface{}) (err error) {
345 » mma, err := makeMetaMultiArg(src, false)
346 » if err != nil {
347 » » panic(err)
348 » }
349
350 » keys, vals, err := mma.getKeysPMs(d.aid, d.ns, false)
351 » if err != nil {
352 » » return err
353 » }
354
355 » i := 0
356 » var et errorTracker
357 » it := mma.iterator(et.init(mma))
358 » err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) error {
359 » » it.next(func(mat *multiArgType, slot reflect.Value) error {
360 » » » if err != nil {
361 » » » » return err
362 » » » }
363 » » » if key != keys[i] {
364 » » » » mat.setKey(slot, key)
365 » » » }
366 » » » return nil
367 » » })
368
369 » » i++
370 » » return nil
371 » }))
372
373 » if err == nil {
374 » » err = et.error()
375
376 » » if err != nil && len(src) == 1 {
377 » » » // Single-argument Put will return a single error.
378 » » » err = errors.SingleError(err)
379 » » }
334 } 380 }
335 return err 381 return err
336 } 382 }
337 383
338 func (d *datastoreImpl) PutMulti(src interface{}) error { 384 func (d *datastoreImpl) PutMulti(src interface{}) error {
339 » slice := reflect.ValueOf(src) 385 » if err := checkMultiSliceType(src); err != nil {
340 » mat := parseMultiArg(slice.Type()) 386 » » panic(err)
387 » }
388 » return d.Put(src)
389 }
341 390
342 » keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice, false) 391 func (d *datastoreImpl) Delete(ent ...interface{}) error {
392 » mma, err := makeMetaMultiArg(ent, true)
393 » if err != nil {
394 » » panic(err)
395 » }
396
397 » keys, _, err := mma.getKeysPMs(d.aid, d.ns, false)
343 if err != nil { 398 if err != nil {
344 return err 399 return err
345 } 400 }
346 401
347 lme := errors.NewLazyMultiError(len(keys))
348 i := 0 402 i := 0
349 » err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) error { 403 » var et errorTracker
350 » » if !lme.Assign(i, err) && key != keys[i] { 404 » it := mma.iterator(et.init(mma))
351 » » » mat.setKey(slice.Index(i), key) 405 » err = filterStop(d.RawInterface.DeleteMulti(keys, func(err error) error {
352 » » } 406 » » it.next(func(*multiArgType, reflect.Value) error {
407 » » » return err
408 » » })
353 i++ 409 i++
410
354 return nil 411 return nil
355 })) 412 }))
413 if err == nil {
414 err = et.error()
356 415
357 » if err == nil { 416 » » if err != nil && len(ent) == 1 {
358 » » err = lme.Get() 417 » » » // Single-argument Delete will return a single error.
418 » » » err = errors.SingleError(err)
419 » » }
359 } 420 }
360 return err 421 return err
361 } 422 }
362 423
363 func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) { 424 func (d *datastoreImpl) DeleteMulti(keys []*Key) error {
364 » lme := errors.NewLazyMultiError(len(keys)) 425 » return d.Delete(keys)
365 » i := 0
366 » extErr := filterStop(d.RawInterface.DeleteMulti(keys, func(internalErr e rror) error {
367 » » lme.Assign(i, internalErr)
368 » » i++
369 » » return nil
370 » }))
371 » err = lme.Get()
372 » if err == nil {
373 » » err = extErr
374 » }
375 » return
376 } 426 }
377 427
378 func (d *datastoreImpl) Raw() RawInterface { 428 func (d *datastoreImpl) Raw() RawInterface {
379 return d.RawInterface 429 return d.RawInterface
380 } 430 }
381 431
382 // ParseIndexYAML parses the contents of a index YAML file into a list of 432 // ParseIndexYAML parses the contents of a index YAML file into a list of
383 // IndexDefinitions. 433 // IndexDefinitions.
384 func ParseIndexYAML(content io.Reader) ([]*IndexDefinition, error) { 434 func ParseIndexYAML(content io.Reader) ([]*IndexDefinition, error) {
385 serialized, err := ioutil.ReadAll(content) 435 serialized, err := ioutil.ReadAll(content)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 currentDir = filepath.Dir(currentDir) 511 currentDir = filepath.Dir(currentDir)
462 } 512 }
463 } 513 }
464 514
465 func filterStop(err error) error { 515 func filterStop(err error) error {
466 if err == Stop { 516 if err == Stop {
467 err = nil 517 err = nil
468 } 518 }
469 return err 519 return err
470 } 520 }
OLDNEW
« no previous file with comments | « no previous file | service/datastore/datastore_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698