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 |