OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |