| Index: filter/txnBuf/state.go
|
| diff --git a/filter/txnBuf/state.go b/filter/txnBuf/state.go
|
| index e76b0e8a7fbd23820b979361b317076dc466a63b..1fefc1b02249dded2793637217a74663d8a395ce 100644
|
| --- a/filter/txnBuf/state.go
|
| +++ b/filter/txnBuf/state.go
|
| @@ -363,33 +363,55 @@ func (t *txnBufState) deleteMulti(keys []*datastore.Key, cb datastore.DeleteMult
|
| }
|
|
|
| func (t *txnBufState) fixKeys(keys []*datastore.Key) ([]*datastore.Key, error) {
|
| - lme := errors.NewLazyMultiError(len(keys))
|
| - realKeys := []*datastore.Key(nil)
|
| - for i, key := range keys {
|
| - if key.Incomplete() {
|
| - // intentionally call AllocateIDs without lock.
|
| - start, err := t.parentDS.AllocateIDs(key, 1)
|
| - if !lme.Assign(i, err) {
|
| - if realKeys == nil {
|
| - realKeys = make([]*datastore.Key, len(keys))
|
| - copy(realKeys, keys)
|
| - }
|
| + // Identify any incomplete keys and allocate IDs for them.
|
| + //
|
| + // In order to facilitate this, we will maintain a mapping of the
|
| + // incompleteKeys index to the key's corresponding index in the keys array.
|
| + // Any errors or allocations on incompleteKeys operations will be propagated
|
| + // to the correct keys index using this map.
|
| + var (
|
| + incompleteKeys []*datastore.Key
|
| + incompleteMap map[int]int
|
| + )
|
|
|
| - aid, ns, toks := key.Split()
|
| - toks[len(toks)-1].IntID = start
|
| - realKeys[i] = datastore.NewKeyToks(aid, ns, toks)
|
| + for i, key := range keys {
|
| + if key.IsIncomplete() {
|
| + if incompleteMap == nil {
|
| + incompleteMap = make(map[int]int)
|
| }
|
| + incompleteMap[len(incompleteKeys)] = i
|
| + incompleteKeys = append(incompleteKeys, key)
|
| }
|
| }
|
| - err := lme.Get()
|
| + if len(incompleteKeys) == 0 {
|
| + return keys, nil
|
| + }
|
| +
|
| + // We're going to update keys, so clone it.
|
| + keys, origKeys := make([]*datastore.Key, len(keys)), keys
|
| + copy(keys, origKeys)
|
| +
|
| + // Intentionally call AllocateIDs without lock.
|
| + i := 0
|
| + outerErr := errors.NewLazyMultiError(len(keys))
|
| + err := t.parentDS.AllocateIDs(incompleteKeys, func(key *datastore.Key, err error) error {
|
| + outerIdx := incompleteMap[i]
|
| + i++
|
|
|
| - if realKeys != nil {
|
| - return realKeys, err
|
| + if err != nil {
|
| + outerErr.Assign(outerIdx, err)
|
| + } else {
|
| + keys[outerIdx] = key
|
| + }
|
| + return nil
|
| + })
|
| + if err != nil {
|
| + return nil, err
|
| }
|
| - return keys, err
|
| + return keys, outerErr.Get()
|
| }
|
|
|
| -func (t *txnBufState) putMulti(keys []*datastore.Key, vals []datastore.PropertyMap, cb datastore.PutMultiCB, haveLock bool) error {
|
| +func (t *txnBufState) putMulti(keys []*datastore.Key, vals []datastore.PropertyMap, cb datastore.NewKeyCB, haveLock bool) error {
|
| keys, err := t.fixKeys(keys)
|
| if err != nil {
|
| for _, e := range err.(errors.MultiError) {
|
|
|