| 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 |