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