 Chromium Code Reviews
 Chromium Code Reviews Issue 1411573014:
  Fix race in impl/memory.  (Closed) 
  Base URL: https://github.com/luci/gae.git@master
    
  
    Issue 1411573014:
  Fix race in impl/memory.  (Closed) 
  Base URL: https://github.com/luci/gae.git@master| Index: impl/memory/datastore_data.go | 
| diff --git a/impl/memory/datastore_data.go b/impl/memory/datastore_data.go | 
| index f0dcc416b9f14ed55711304ee82a1a4dcf6cd6a3..b5a40819286012a7f4b653c1e5b063e3eb33c776 100644 | 
| --- a/impl/memory/datastore_data.go | 
| +++ b/impl/memory/datastore_data.go | 
| @@ -207,10 +207,7 @@ func incrementLocked(ents *memCollection, key []byte, amt int) int64 { | 
| return ret | 
| } | 
| -func (d *dataStoreData) mutableEnts(ns string) *memCollection { | 
| - d.Lock() | 
| - defer d.Unlock() | 
| - | 
| +func (d *dataStoreData) mutableEntsLocked(ns string) *memCollection { | 
| coll := "ents:" + ns | 
| ents := d.head.GetCollection(coll) | 
| if ents == nil { | 
| @@ -220,10 +217,10 @@ func (d *dataStoreData) mutableEnts(ns string) *memCollection { | 
| } | 
| func (d *dataStoreData) allocateIDs(incomplete *ds.Key, n int) (int64, error) { | 
| - ents := d.mutableEnts(incomplete.Namespace()) | 
| 
iannucci
2015/11/06 23:25:03
apparently getting a collection locked, releasing
 | 
| - | 
| d.Lock() | 
| defer d.Unlock() | 
| + | 
| + ents := d.mutableEntsLocked(incomplete.Namespace()) | 
| return d.allocateIDsLocked(ents, incomplete, n) | 
| } | 
| @@ -254,7 +251,6 @@ func (d *dataStoreData) fixKeyLocked(ents *memCollection, key *ds.Key) (*ds.Key, | 
| func (d *dataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.PutMultiCB) { | 
| ns := keys[0].Namespace() | 
| - ents := d.mutableEnts(ns) | 
| for i, k := range keys { | 
| pmap, _ := vals[i].Save(false) | 
| @@ -264,6 +260,8 @@ func (d *dataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.Pu | 
| d.Lock() | 
| defer d.Unlock() | 
| + ents := d.mutableEntsLocked(ns) | 
| + | 
| ret, err = d.fixKeyLocked(ents, k) | 
| if err != nil { | 
| return | 
| @@ -322,9 +320,14 @@ func (d *dataStoreData) getMulti(keys []*ds.Key, cb ds.GetMultiCB) error { | 
| func (d *dataStoreData) delMulti(keys []*ds.Key, cb ds.DeleteMultiCB) { | 
| ns := keys[0].Namespace() | 
| - ents := d.mutableEnts(ns) | 
| - if ents != nil { | 
| + hasEntsInNS := func() bool { | 
| + d.Lock() | 
| + defer d.Unlock() | 
| + return d.mutableEntsLocked(ns) != nil | 
| + }() | 
| + | 
| + if hasEntsInNS { | 
| for _, k := range keys { | 
| err := func() error { | 
| kb := keyBytes(k) | 
| @@ -332,6 +335,8 @@ func (d *dataStoreData) delMulti(keys []*ds.Key, cb ds.DeleteMultiCB) { | 
| d.Lock() | 
| defer d.Unlock() | 
| + ents := d.mutableEntsLocked(ns) | 
| + | 
| if !d.disableSpecialEntities { | 
| incrementLocked(ents, groupMetaKey(k), 1) | 
| } | 
| @@ -508,12 +513,14 @@ 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()) | 
| + ns := keys[0].Namespace() | 
| for i, k := range keys { | 
| err := func() (err error) { | 
| td.parent.Lock() | 
| defer td.parent.Unlock() | 
| + ents := td.parent.mutableEntsLocked(ns) | 
| + | 
| k, err = td.parent.fixKeyLocked(ents, k) | 
| return | 
| }() |