Index: impl/memory/datastore_data.go |
diff --git a/impl/memory/datastore_data.go b/impl/memory/datastore_data.go |
index 7793ac913730723b868f174dad79a59dbf250ced..96c85f8af98a3ca3eefc7ea20beecf485beb5c03 100644 |
--- a/impl/memory/datastore_data.go |
+++ b/impl/memory/datastore_data.go |
@@ -109,46 +109,68 @@ func curVersion(ents *memCollection, key []byte) int64 { |
return 0 |
} |
-func incrementLocked(ents *memCollection, key []byte) int64 { |
+func incrementLocked(ents *memCollection, key []byte, amt int) int64 { |
+ if amt <= 0 { |
+ panic(fmt.Errorf("incrementLocked called with bad `amt`: %d", amt)) |
+ } |
ret := curVersion(ents, key) + 1 |
ents.Set(key, serialize.ToBytes(ds.PropertyMap{ |
- "__version__": {ds.MkPropertyNI(ret)}, |
+ "__version__": {ds.MkPropertyNI(ret + int64(amt-1))}, |
})) |
return ret |
} |
-func (d *dataStoreData) entsKeyLocked(key *ds.Key) (*memCollection, *ds.Key) { |
- coll := "ents:" + key.Namespace() |
+func (d *dataStoreData) mutableEnts(ns string) *memCollection { |
+ d.Lock() |
+ defer d.Unlock() |
+ |
+ coll := "ents:" + ns |
ents := d.head.GetCollection(coll) |
if ents == nil { |
ents = d.head.SetCollection(coll, nil) |
} |
+ return ents |
+} |
+ |
+func (d *dataStoreData) allocateIDs(incomplete *ds.Key, n int) int64 { |
+ ents := d.mutableEnts(incomplete.Namespace()) |
+ |
+ d.Lock() |
+ defer d.Unlock() |
+ return d.allocateIDsLocked(ents, incomplete, n) |
+} |
+ |
+func (d *dataStoreData) allocateIDsLocked(ents *memCollection, incomplete *ds.Key, n int) int64 { |
+ idKey := []byte(nil) |
+ if incomplete.Parent() == nil { |
+ idKey = rootIDsKey(incomplete.Last().Kind) |
+ } else { |
+ idKey = groupIDsKey(incomplete) |
+ } |
+ return incrementLocked(ents, idKey, n) |
+} |
+func (d *dataStoreData) fixKeyLocked(ents *memCollection, key *ds.Key) *ds.Key { |
if key.Incomplete() { |
- idKey := []byte(nil) |
- if key.Parent() == nil { |
- idKey = rootIDsKey(key.Last().Kind) |
- } else { |
- idKey = groupIDsKey(key) |
- } |
- id := incrementLocked(ents, idKey) |
+ id := d.allocateIDsLocked(ents, key, 1) |
key = ds.NewKey(key.AppID(), key.Namespace(), key.Last().Kind, "", id, key.Parent()) |
} |
- |
- return ents, key |
+ return key |
} |
func (d *dataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMultiCB) { |
+ ents := d.mutableEnts(keys[0].Namespace()) |
+ |
for i, k := range keys { |
pmap, _ := vals[i].Save(false) |
dataBytes := serialize.ToBytes(pmap) |
k, err := func() (ret *ds.Key, err error) { |
- d.rwlock.Lock() |
- defer d.rwlock.Unlock() |
+ d.Lock() |
+ defer d.Unlock() |
- ents, ret := d.entsKeyLocked(k) |
- incrementLocked(ents, groupMetaKey(ret)) |
+ ret = d.fixKeyLocked(ents, k) |
+ incrementLocked(ents, groupMetaKey(ret), 1) |
old := ents.Get(keyBytes(ret)) |
oldPM := ds.PropertyMap(nil) |
@@ -212,7 +234,7 @@ func (d *dataStoreData) delMulti(keys []*ds.Key, cb ds.DeleteMultiCB) { |
for i, k := range keys { |
if ents != nil { |
- incrementLocked(ents, groupMetaKey(k)) |
+ incrementLocked(ents, groupMetaKey(k), 1) |
kb := toDel[i] |
if old := ents.Get(kb); old != nil { |
oldPM, err := rpmWoCtx(old, ns) |
@@ -384,11 +406,13 @@ func (td *txnDataStoreData) writeMutation(getOnly bool, key *ds.Key, data ds.Pro |
} |
func (td *txnDataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMultiCB) { |
+ ents := td.parent.mutableEnts(keys[0].Namespace()) |
+ |
for i, k := range keys { |
func() { |
td.parent.Lock() |
defer td.parent.Unlock() |
- _, k = td.parent.entsKeyLocked(k) |
+ k = td.parent.fixKeyLocked(ents, k) |
}() |
err := td.writeMutation(false, k, vals[i]) |
if cb != nil { |