| OLD | NEW |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be 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 30 matching lines...) Expand all Loading... |
| 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 |
| 51 func (d *datastoreImpl) NewIncompleteKeys(count int, kind string, parent *Key) (
keys []*Key) { |
| 52 if count > 0 { |
| 53 keys = make([]*Key, count) |
| 54 for i := range keys { |
| 55 keys[i] = d.NewKey(kind, "", 0, parent) |
| 56 } |
| 57 } |
| 58 return |
| 59 } |
| 60 |
| 51 func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key { | 61 func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key { |
| 52 return NewKeyToks(d.aid, d.ns, toks) | 62 return NewKeyToks(d.aid, d.ns, toks) |
| 53 } | 63 } |
| 54 | 64 |
| 55 // PopulateKey loads key into obj. | 65 // PopulateKey loads key into obj. |
| 56 // | 66 // |
| 57 // obj is any object that Interface.Get is able to accept. | 67 // obj is any object that Interface.Get is able to accept. |
| 58 // | 68 // |
| 69 // Upon successful application, this method will return true. If the key could |
| 70 // not be applied to the object, this method will return false. It will panic if |
| 71 // obj is an invalid datastore model. |
| 72 // |
| 59 // This method will panic if obj is an invalid datastore model. If the key could | 73 // This method will panic if obj is an invalid datastore model. If the key could |
| 60 // not be applied to the object, nothing will happen. | 74 // not be applied to the object, nothing will happen. |
| 61 func PopulateKey(obj interface{}, key *Key) { | 75 func PopulateKey(obj interface{}, key *Key) bool { |
| 62 » populateKeyMGS(getMGS(obj), key) | 76 » return populateKeyMGS(getMGS(obj), key) |
| 63 } | 77 } |
| 64 | 78 |
| 65 func populateKeyMGS(mgs MetaGetterSetter, key *Key) { | 79 func populateKeyMGS(mgs MetaGetterSetter, key *Key) bool { |
| 66 » if !mgs.SetMeta("key", key) { | 80 » if mgs.SetMeta("key", key) { |
| 67 » » lst := key.LastTok() | 81 » » return true |
| 68 » » if lst.StringID != "" { | 82 » } |
| 69 » » » mgs.SetMeta("id", lst.StringID) | 83 |
| 70 » » } else { | 84 » lst := key.LastTok() |
| 71 » » » mgs.SetMeta("id", lst.IntID) | 85 » if lst.StringID != "" { |
| 86 » » if !mgs.SetMeta("id", lst.StringID) { |
| 87 » » » return false |
| 72 } | 88 } |
| 73 » » mgs.SetMeta("kind", lst.Kind) | 89 » } else { |
| 74 » » mgs.SetMeta("parent", key.Parent()) | 90 » » if !mgs.SetMeta("id", lst.IntID) { |
| 91 » » » return false |
| 92 » » } |
| 75 } | 93 } |
| 94 |
| 95 mgs.SetMeta("kind", lst.Kind) |
| 96 mgs.SetMeta("parent", key.Parent()) |
| 97 return true |
| 76 } | 98 } |
| 77 | 99 |
| 78 func checkMultiSliceType(v interface{}) error { | 100 func checkMultiSliceType(v interface{}) error { |
| 79 if reflect.TypeOf(v).Kind() == reflect.Slice { | 101 if reflect.TypeOf(v).Kind() == reflect.Slice { |
| 80 return nil | 102 return nil |
| 81 } | 103 } |
| 82 return fmt.Errorf("argument must be a slice, not %T", v) | 104 return fmt.Errorf("argument must be a slice, not %T", v) |
| 83 | 105 |
| 84 } | 106 } |
| 85 | 107 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 104 | 126 |
| 105 numIn := cbTyp.NumIn() | 127 numIn := cbTyp.NumIn() |
| 106 if numIn != 1 && numIn != 2 { | 128 if numIn != 1 && numIn != 2 { |
| 107 badSig() | 129 badSig() |
| 108 } | 130 } |
| 109 | 131 |
| 110 firstArg := cbTyp.In(0) | 132 firstArg := cbTyp.In(0) |
| 111 if firstArg == typeOfKey { | 133 if firstArg == typeOfKey { |
| 112 isKey = true | 134 isKey = true |
| 113 } else { | 135 } else { |
| 114 » » mat = mustParseArg(firstArg) | 136 » » mat = mustParseArg(firstArg, false) |
| 115 if mat.newElem == nil { | 137 if mat.newElem == nil { |
| 116 badSig() | 138 badSig() |
| 117 } | 139 } |
| 118 } | 140 } |
| 119 | 141 |
| 120 hasCursorCB = numIn == 2 | 142 hasCursorCB = numIn == 2 |
| 121 if hasCursorCB && cbTyp.In(1) != typeOfCursorCB { | 143 if hasCursorCB && cbTyp.In(1) != typeOfCursorCB { |
| 122 badSig() | 144 badSig() |
| 123 } | 145 } |
| 124 | 146 |
| 125 if cbTyp.NumOut() > 1 { | 147 if cbTyp.NumOut() > 1 { |
| 126 badSig() | 148 badSig() |
| 127 } else if cbTyp.NumOut() == 1 && cbTyp.Out(0) != typeOfError { | 149 } else if cbTyp.NumOut() == 1 && cbTyp.Out(0) != typeOfError { |
| 128 badSig() | 150 badSig() |
| 129 } | 151 } |
| 130 hasErr = cbTyp.NumOut() == 1 | 152 hasErr = cbTyp.NumOut() == 1 |
| 131 | 153 |
| 132 return | 154 return |
| 133 } | 155 } |
| 134 | 156 |
| 157 func (d *datastoreImpl) AllocateIDs(ent ...interface{}) error { |
| 158 if len(ent) == 0 { |
| 159 return nil |
| 160 } |
| 161 |
| 162 mma, err := makeMetaMultiArg(ent, mmaWriteKeys) |
| 163 if err != nil { |
| 164 panic(err) |
| 165 } |
| 166 |
| 167 keys, _, err := mma.getKeysPMs(d.aid, d.ns, false) |
| 168 if err != nil { |
| 169 return err |
| 170 } |
| 171 if len(keys) == 0 { |
| 172 return nil |
| 173 } |
| 174 |
| 175 // Convert each key to be partial valid, assigning an integer ID of 0. C
onfirm |
| 176 // that each object can be populated with such a key. |
| 177 for i, key := range keys { |
| 178 keys[i] = key.Incomplete() |
| 179 } |
| 180 |
| 181 var et errorTracker |
| 182 it := mma.iterator(et.init(mma)) |
| 183 err = filterStop(d.RawInterface.AllocateIDs(keys, func(key *Key, err err
or) error { |
| 184 it.next(func(mat *multiArgType, v reflect.Value) error { |
| 185 if err != nil { |
| 186 return err |
| 187 } |
| 188 |
| 189 if !mat.setKey(v, key) { |
| 190 return ErrInvalidKey |
| 191 } |
| 192 return nil |
| 193 }) |
| 194 |
| 195 return nil |
| 196 })) |
| 197 if err == nil { |
| 198 err = et.error() |
| 199 |
| 200 if err != nil && len(ent) == 1 { |
| 201 // Single-argument Exists will return a single error. |
| 202 err = errors.SingleError(err) |
| 203 } |
| 204 } |
| 205 return err |
| 206 } |
| 207 |
| 135 func (d *datastoreImpl) Run(q *Query, cbIface interface{}) error { | 208 func (d *datastoreImpl) Run(q *Query, cbIface interface{}) error { |
| 136 isKey, hasErr, hasCursorCB, mat := runParseCallback(cbIface) | 209 isKey, hasErr, hasCursorCB, mat := runParseCallback(cbIface) |
| 137 | 210 |
| 138 if isKey { | 211 if isKey { |
| 139 q = q.KeysOnly(true) | 212 q = q.KeysOnly(true) |
| 140 } | 213 } |
| 141 fq, err := q.Finalize() | 214 fq, err := q.Finalize() |
| 142 if err != nil { | 215 if err != nil { |
| 143 return err | 216 return err |
| 144 } | 217 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 for i, e := range errs { | 326 for i, e := range errs { |
| 254 me[i] = e | 327 me[i] = e |
| 255 } | 328 } |
| 256 err = me | 329 err = me |
| 257 } | 330 } |
| 258 } | 331 } |
| 259 return err | 332 return err |
| 260 } | 333 } |
| 261 | 334 |
| 262 func (d *datastoreImpl) Exists(ent ...interface{}) (*ExistsResult, error) { | 335 func (d *datastoreImpl) Exists(ent ...interface{}) (*ExistsResult, error) { |
| 263 » mma, err := makeMetaMultiArg(ent, true) | 336 » if len(ent) == 0 { |
| 337 » » return nil, nil |
| 338 » } |
| 339 |
| 340 » mma, err := makeMetaMultiArg(ent, mmaKeysOnly) |
| 264 if err != nil { | 341 if err != nil { |
| 265 panic(err) | 342 panic(err) |
| 266 } | 343 } |
| 267 | 344 |
| 268 keys, _, err := mma.getKeysPMs(d.aid, d.ns, false) | 345 keys, _, err := mma.getKeysPMs(d.aid, d.ns, false) |
| 269 if err != nil { | 346 if err != nil { |
| 270 return nil, err | 347 return nil, err |
| 271 } | 348 } |
| 349 if len(keys) == 0 { |
| 350 return nil, nil |
| 351 } |
| 272 | 352 |
| 273 i := 0 | |
| 274 var bt boolTracker | 353 var bt boolTracker |
| 275 it := mma.iterator(bt.init(mma)) | 354 it := mma.iterator(bt.init(mma)) |
| 276 err = filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap,
err error) error { | 355 err = filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap,
err error) error { |
| 277 it.next(func(*multiArgType, reflect.Value) error { | 356 it.next(func(*multiArgType, reflect.Value) error { |
| 278 return err | 357 return err |
| 279 }) | 358 }) |
| 280 i++ | |
| 281 return nil | 359 return nil |
| 282 })) | 360 })) |
| 283 if err == nil { | 361 if err == nil { |
| 284 err = bt.error() | 362 err = bt.error() |
| 285 | 363 |
| 286 if err != nil && len(ent) == 1 { | 364 if err != nil && len(ent) == 1 { |
| 287 // Single-argument Exists will return a single error. | 365 // Single-argument Exists will return a single error. |
| 288 err = errors.SingleError(err) | 366 err = errors.SingleError(err) |
| 289 } | 367 } |
| 290 } | 368 } |
| 291 return bt.result(), err | 369 return bt.result(), err |
| 292 } | 370 } |
| 293 | 371 |
| 294 func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) { | 372 func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) { |
| 295 v, err := d.Exists(keys) | 373 v, err := d.Exists(keys) |
| 296 if err != nil { | 374 if err != nil { |
| 297 return nil, err | 375 return nil, err |
| 298 } | 376 } |
| 299 return v.List(0), nil | 377 return v.List(0), nil |
| 300 } | 378 } |
| 301 | 379 |
| 302 func (d *datastoreImpl) Get(dst ...interface{}) (err error) { | 380 func (d *datastoreImpl) Get(dst ...interface{}) (err error) { |
| 303 » mma, err := makeMetaMultiArg(dst, false) | 381 » if len(dst) == 0 { |
| 382 » » return nil |
| 383 » } |
| 384 |
| 385 » mma, err := makeMetaMultiArg(dst, mmaReadWrite) |
| 304 if err != nil { | 386 if err != nil { |
| 305 panic(err) | 387 panic(err) |
| 306 } | 388 } |
| 307 | 389 |
| 308 keys, pms, err := mma.getKeysPMs(d.aid, d.ns, true) | 390 keys, pms, err := mma.getKeysPMs(d.aid, d.ns, true) |
| 309 if err != nil { | 391 if err != nil { |
| 310 return err | 392 return err |
| 311 } | 393 } |
| 394 if len(keys) == 0 { |
| 395 return nil |
| 396 } |
| 312 | 397 |
| 313 i := 0 | |
| 314 var et errorTracker | 398 var et errorTracker |
| 315 it := mma.iterator(et.init(mma)) | 399 it := mma.iterator(et.init(mma)) |
| 316 meta := NewMultiMetaGetter(pms) | 400 meta := NewMultiMetaGetter(pms) |
| 317 err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap
, err error) error { | 401 err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap
, err error) error { |
| 318 it.next(func(mat *multiArgType, slot reflect.Value) error { | 402 it.next(func(mat *multiArgType, slot reflect.Value) error { |
| 319 if err != nil { | 403 if err != nil { |
| 320 return err | 404 return err |
| 321 } | 405 } |
| 322 return mat.setPM(slot, pm) | 406 return mat.setPM(slot, pm) |
| 323 }) | 407 }) |
| 324 | |
| 325 i++ | |
| 326 return nil | 408 return nil |
| 327 })) | 409 })) |
| 328 | 410 |
| 329 if err == nil { | 411 if err == nil { |
| 330 err = et.error() | 412 err = et.error() |
| 331 | 413 |
| 332 if err != nil && len(dst) == 1 { | 414 if err != nil && len(dst) == 1 { |
| 333 // Single-argument Get will return a single error. | 415 // Single-argument Get will return a single error. |
| 334 err = errors.SingleError(err) | 416 err = errors.SingleError(err) |
| 335 } | 417 } |
| 336 } | 418 } |
| 337 return err | 419 return err |
| 338 } | 420 } |
| 339 | 421 |
| 340 func (d *datastoreImpl) GetMulti(dst interface{}) error { | 422 func (d *datastoreImpl) GetMulti(dst interface{}) error { |
| 341 if err := checkMultiSliceType(dst); err != nil { | 423 if err := checkMultiSliceType(dst); err != nil { |
| 342 panic(err) | 424 panic(err) |
| 343 } | 425 } |
| 344 return d.Get(dst) | 426 return d.Get(dst) |
| 345 } | 427 } |
| 346 | 428 |
| 347 func (d *datastoreImpl) Put(src ...interface{}) (err error) { | 429 func (d *datastoreImpl) Put(src ...interface{}) (err error) { |
| 348 » mma, err := makeMetaMultiArg(src, false) | 430 » if len(src) == 0 { |
| 431 » » return nil |
| 432 » } |
| 433 |
| 434 » mma, err := makeMetaMultiArg(src, mmaReadWrite) |
| 349 if err != nil { | 435 if err != nil { |
| 350 panic(err) | 436 panic(err) |
| 351 } | 437 } |
| 352 | 438 |
| 353 keys, vals, err := mma.getKeysPMs(d.aid, d.ns, false) | 439 keys, vals, err := mma.getKeysPMs(d.aid, d.ns, false) |
| 354 if err != nil { | 440 if err != nil { |
| 355 return err | 441 return err |
| 356 } | 442 } |
| 443 if len(keys) == 0 { |
| 444 return nil |
| 445 } |
| 357 | 446 |
| 358 i := 0 | 447 i := 0 |
| 359 var et errorTracker | 448 var et errorTracker |
| 360 it := mma.iterator(et.init(mma)) | 449 it := mma.iterator(et.init(mma)) |
| 361 err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err
error) error { | 450 err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err
error) error { |
| 362 it.next(func(mat *multiArgType, slot reflect.Value) error { | 451 it.next(func(mat *multiArgType, slot reflect.Value) error { |
| 363 if err != nil { | 452 if err != nil { |
| 364 return err | 453 return err |
| 365 } | 454 } |
| 366 if key != keys[i] { | 455 if key != keys[i] { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 385 } | 474 } |
| 386 | 475 |
| 387 func (d *datastoreImpl) PutMulti(src interface{}) error { | 476 func (d *datastoreImpl) PutMulti(src interface{}) error { |
| 388 if err := checkMultiSliceType(src); err != nil { | 477 if err := checkMultiSliceType(src); err != nil { |
| 389 panic(err) | 478 panic(err) |
| 390 } | 479 } |
| 391 return d.Put(src) | 480 return d.Put(src) |
| 392 } | 481 } |
| 393 | 482 |
| 394 func (d *datastoreImpl) Delete(ent ...interface{}) error { | 483 func (d *datastoreImpl) Delete(ent ...interface{}) error { |
| 395 » mma, err := makeMetaMultiArg(ent, true) | 484 » if len(ent) == 0 { |
| 485 » » return nil |
| 486 » } |
| 487 |
| 488 » mma, err := makeMetaMultiArg(ent, mmaKeysOnly) |
| 396 if err != nil { | 489 if err != nil { |
| 397 panic(err) | 490 panic(err) |
| 398 } | 491 } |
| 399 | 492 |
| 400 keys, _, err := mma.getKeysPMs(d.aid, d.ns, false) | 493 keys, _, err := mma.getKeysPMs(d.aid, d.ns, false) |
| 401 if err != nil { | 494 if err != nil { |
| 402 return err | 495 return err |
| 403 } | 496 } |
| 497 if len(keys) == 0 { |
| 498 return nil |
| 499 } |
| 404 | 500 |
| 405 i := 0 | |
| 406 var et errorTracker | 501 var et errorTracker |
| 407 it := mma.iterator(et.init(mma)) | 502 it := mma.iterator(et.init(mma)) |
| 408 err = filterStop(d.RawInterface.DeleteMulti(keys, func(err error) error
{ | 503 err = filterStop(d.RawInterface.DeleteMulti(keys, func(err error) error
{ |
| 409 it.next(func(*multiArgType, reflect.Value) error { | 504 it.next(func(*multiArgType, reflect.Value) error { |
| 410 return err | 505 return err |
| 411 }) | 506 }) |
| 412 i++ | |
| 413 | 507 |
| 414 return nil | 508 return nil |
| 415 })) | 509 })) |
| 416 if err == nil { | 510 if err == nil { |
| 417 err = et.error() | 511 err = et.error() |
| 418 | 512 |
| 419 if err != nil && len(ent) == 1 { | 513 if err != nil && len(ent) == 1 { |
| 420 // Single-argument Delete will return a single error. | 514 // Single-argument Delete will return a single error. |
| 421 err = errors.SingleError(err) | 515 err = errors.SingleError(err) |
| 422 } | 516 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 currentDir = filepath.Dir(currentDir) | 608 currentDir = filepath.Dir(currentDir) |
| 515 } | 609 } |
| 516 } | 610 } |
| 517 | 611 |
| 518 func filterStop(err error) error { | 612 func filterStop(err error) error { |
| 519 if err == Stop { | 613 if err == Stop { |
| 520 err = nil | 614 err = nil |
| 521 } | 615 } |
| 522 return err | 616 return err |
| 523 } | 617 } |
| OLD | NEW |