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