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 txnBuf | 5 package txnBuf |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "sync" | 9 "sync" |
10 | 10 |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 for range keys { | 356 for range keys { |
357 if err := cb(nil); err != nil { | 357 if err := cb(nil); err != nil { |
358 return err | 358 return err |
359 } | 359 } |
360 } | 360 } |
361 | 361 |
362 return nil | 362 return nil |
363 } | 363 } |
364 | 364 |
365 func (t *txnBufState) fixKeys(keys []*datastore.Key) ([]*datastore.Key, error) { | 365 func (t *txnBufState) fixKeys(keys []*datastore.Key) ([]*datastore.Key, error) { |
366 » lme := errors.NewLazyMultiError(len(keys)) | 366 » // Identify any incomplete keys and allocate IDs for them. |
367 » realKeys := []*datastore.Key(nil) | 367 » // |
| 368 » // In order to facilitate this, we will maintain a mapping of the |
| 369 » // incompleteKeys index to the key's corresponding index in the keys arr
ay. |
| 370 » // Any errors or allocations on incompleteKeys operations will be propag
ated |
| 371 » // to the correct keys index using this map. |
| 372 » var ( |
| 373 » » incompleteKeys []*datastore.Key |
| 374 » » incompleteMap map[int]int |
| 375 » ) |
| 376 |
368 for i, key := range keys { | 377 for i, key := range keys { |
369 » » if key.Incomplete() { | 378 » » if key.IsIncomplete() { |
370 » » » // intentionally call AllocateIDs without lock. | 379 » » » if incompleteMap == nil { |
371 » » » start, err := t.parentDS.AllocateIDs(key, 1) | 380 » » » » incompleteMap = make(map[int]int) |
372 » » » if !lme.Assign(i, err) { | |
373 » » » » if realKeys == nil { | |
374 » » » » » realKeys = make([]*datastore.Key, len(ke
ys)) | |
375 » » » » » copy(realKeys, keys) | |
376 » » » » } | |
377 | |
378 » » » » aid, ns, toks := key.Split() | |
379 » » » » toks[len(toks)-1].IntID = start | |
380 » » » » realKeys[i] = datastore.NewKeyToks(aid, ns, toks
) | |
381 } | 381 } |
| 382 incompleteMap[len(incompleteKeys)] = i |
| 383 incompleteKeys = append(incompleteKeys, key) |
382 } | 384 } |
383 } | 385 } |
384 » err := lme.Get() | 386 » if len(incompleteKeys) == 0 { |
| 387 » » return keys, nil |
| 388 » } |
385 | 389 |
386 » if realKeys != nil { | 390 » // We're going to update keys, so clone it. |
387 » » return realKeys, err | 391 » keys, origKeys := make([]*datastore.Key, len(keys)), keys |
| 392 » copy(keys, origKeys) |
| 393 |
| 394 » // Intentionally call AllocateIDs without lock. |
| 395 » i := 0 |
| 396 » outerErr := errors.NewLazyMultiError(len(keys)) |
| 397 » err := t.parentDS.AllocateIDs(incompleteKeys, func(key *datastore.Key, e
rr error) error { |
| 398 » » outerIdx := incompleteMap[i] |
| 399 » » i++ |
| 400 |
| 401 » » if err != nil { |
| 402 » » » outerErr.Assign(outerIdx, err) |
| 403 » » } else { |
| 404 » » » keys[outerIdx] = key |
| 405 » » } |
| 406 » » return nil |
| 407 » }) |
| 408 » if err != nil { |
| 409 » » return nil, err |
388 } | 410 } |
389 » return keys, err | 411 » return keys, outerErr.Get() |
390 } | 412 } |
391 | 413 |
392 func (t *txnBufState) putMulti(keys []*datastore.Key, vals []datastore.PropertyM
ap, cb datastore.PutMultiCB, haveLock bool) error { | 414 func (t *txnBufState) putMulti(keys []*datastore.Key, vals []datastore.PropertyM
ap, cb datastore.NewKeyCB, haveLock bool) error { |
393 keys, err := t.fixKeys(keys) | 415 keys, err := t.fixKeys(keys) |
394 if err != nil { | 416 if err != nil { |
395 for _, e := range err.(errors.MultiError) { | 417 for _, e := range err.(errors.MultiError) { |
396 if err := cb(nil, e); err != nil { | 418 if err := cb(nil, e); err != nil { |
397 return err | 419 return err |
398 } | 420 } |
399 } | 421 } |
400 return nil | 422 return nil |
401 } | 423 } |
402 | 424 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 // plus a stringset of all the encoded root keys that `keys` represents. | 564 // plus a stringset of all the encoded root keys that `keys` represents. |
543 func toEncoded(keys []*datastore.Key) (full []string, roots stringset.Set) { | 565 func toEncoded(keys []*datastore.Key) (full []string, roots stringset.Set) { |
544 roots = stringset.New(len(keys)) | 566 roots = stringset.New(len(keys)) |
545 full = make([]string, len(keys)) | 567 full = make([]string, len(keys)) |
546 for i, k := range keys { | 568 for i, k := range keys { |
547 roots.Add(string(serialize.ToBytes(k.Root()))) | 569 roots.Add(string(serialize.ToBytes(k.Root()))) |
548 full[i] = string(serialize.ToBytes(k)) | 570 full[i] = string(serialize.ToBytes(k)) |
549 } | 571 } |
550 return | 572 return |
551 } | 573 } |
OLD | NEW |