Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: impl/memory/datastore_data.go

Issue 1411573014: Fix race in impl/memory. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | impl/memory/gkvlite_utils.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package memory 5 package memory
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "fmt" 9 "fmt"
10 "sync" 10 "sync"
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 if amt <= 0 { 200 if amt <= 0 {
201 panic(fmt.Errorf("incrementLocked called with bad `amt`: %d", am t)) 201 panic(fmt.Errorf("incrementLocked called with bad `amt`: %d", am t))
202 } 202 }
203 ret := curVersion(ents, key) + 1 203 ret := curVersion(ents, key) + 1
204 ents.Set(key, serialize.ToBytes(ds.PropertyMap{ 204 ents.Set(key, serialize.ToBytes(ds.PropertyMap{
205 "__version__": {ds.MkPropertyNI(ret + int64(amt-1))}, 205 "__version__": {ds.MkPropertyNI(ret + int64(amt-1))},
206 })) 206 }))
207 return ret 207 return ret
208 } 208 }
209 209
210 func (d *dataStoreData) mutableEnts(ns string) *memCollection { 210 func (d *dataStoreData) mutableEntsLocked(ns string) *memCollection {
211 » d.Lock()
212 » defer d.Unlock()
213
214 coll := "ents:" + ns 211 coll := "ents:" + ns
215 ents := d.head.GetCollection(coll) 212 ents := d.head.GetCollection(coll)
216 if ents == nil { 213 if ents == nil {
217 ents = d.head.SetCollection(coll, nil) 214 ents = d.head.SetCollection(coll, nil)
218 } 215 }
219 return ents 216 return ents
220 } 217 }
221 218
222 func (d *dataStoreData) allocateIDs(incomplete *ds.Key, n int) (int64, error) { 219 func (d *dataStoreData) allocateIDs(incomplete *ds.Key, n int) (int64, error) {
223 ents := d.mutableEnts(incomplete.Namespace())
iannucci 2015/11/06 23:25:03 apparently getting a collection locked, releasing
224
225 d.Lock() 220 d.Lock()
226 defer d.Unlock() 221 defer d.Unlock()
222
223 ents := d.mutableEntsLocked(incomplete.Namespace())
227 return d.allocateIDsLocked(ents, incomplete, n) 224 return d.allocateIDsLocked(ents, incomplete, n)
228 } 225 }
229 226
230 func (d *dataStoreData) allocateIDsLocked(ents *memCollection, incomplete *ds.Ke y, n int) (int64, error) { 227 func (d *dataStoreData) allocateIDsLocked(ents *memCollection, incomplete *ds.Ke y, n int) (int64, error) {
231 if d.disableSpecialEntities { 228 if d.disableSpecialEntities {
232 return 0, errors.New("disableSpecialEntities is true so allocate IDs is disabled") 229 return 0, errors.New("disableSpecialEntities is true so allocate IDs is disabled")
233 } 230 }
234 231
235 idKey := []byte(nil) 232 idKey := []byte(nil)
236 if incomplete.Parent() == nil { 233 if incomplete.Parent() == nil {
(...skipping 10 matching lines...) Expand all
247 if err != nil { 244 if err != nil {
248 return key, err 245 return key, err
249 } 246 }
250 key = ds.NewKey(key.AppID(), key.Namespace(), key.Kind(), "", id , key.Parent()) 247 key = ds.NewKey(key.AppID(), key.Namespace(), key.Kind(), "", id , key.Parent())
251 } 248 }
252 return key, nil 249 return key, nil
253 } 250 }
254 251
255 func (d *dataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.Pu tMultiCB) { 252 func (d *dataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.Pu tMultiCB) {
256 ns := keys[0].Namespace() 253 ns := keys[0].Namespace()
257 ents := d.mutableEnts(ns)
258 254
259 for i, k := range keys { 255 for i, k := range keys {
260 pmap, _ := vals[i].Save(false) 256 pmap, _ := vals[i].Save(false)
261 dataBytes := serialize.ToBytes(pmap) 257 dataBytes := serialize.ToBytes(pmap)
262 258
263 k, err := func() (ret *ds.Key, err error) { 259 k, err := func() (ret *ds.Key, err error) {
264 d.Lock() 260 d.Lock()
265 defer d.Unlock() 261 defer d.Unlock()
266 262
263 ents := d.mutableEntsLocked(ns)
264
267 ret, err = d.fixKeyLocked(ents, k) 265 ret, err = d.fixKeyLocked(ents, k)
268 if err != nil { 266 if err != nil {
269 return 267 return
270 } 268 }
271 if !d.disableSpecialEntities { 269 if !d.disableSpecialEntities {
272 incrementLocked(ents, groupMetaKey(ret), 1) 270 incrementLocked(ents, groupMetaKey(ret), 1)
273 } 271 }
274 272
275 old := ents.Get(keyBytes(ret)) 273 old := ents.Get(keyBytes(ret))
276 oldPM := ds.PropertyMap(nil) 274 oldPM := ds.PropertyMap(nil)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 func (d *dataStoreData) getMulti(keys []*ds.Key, cb ds.GetMultiCB) error { 313 func (d *dataStoreData) getMulti(keys []*ds.Key, cb ds.GetMultiCB) error {
316 return getMultiInner(keys, cb, func() (*memCollection, error) { 314 return getMultiInner(keys, cb, func() (*memCollection, error) {
317 s := d.takeSnapshot() 315 s := d.takeSnapshot()
318 316
319 return s.GetCollection("ents:" + keys[0].Namespace()), nil 317 return s.GetCollection("ents:" + keys[0].Namespace()), nil
320 }) 318 })
321 } 319 }
322 320
323 func (d *dataStoreData) delMulti(keys []*ds.Key, cb ds.DeleteMultiCB) { 321 func (d *dataStoreData) delMulti(keys []*ds.Key, cb ds.DeleteMultiCB) {
324 ns := keys[0].Namespace() 322 ns := keys[0].Namespace()
325 ents := d.mutableEnts(ns)
326 323
327 » if ents != nil { 324 » hasEntsInNS := func() bool {
325 » » d.Lock()
326 » » defer d.Unlock()
327 » » return d.mutableEntsLocked(ns) != nil
328 » }()
329
330 » if hasEntsInNS {
328 for _, k := range keys { 331 for _, k := range keys {
329 err := func() error { 332 err := func() error {
330 kb := keyBytes(k) 333 kb := keyBytes(k)
331 334
332 d.Lock() 335 d.Lock()
333 defer d.Unlock() 336 defer d.Unlock()
334 337
338 ents := d.mutableEntsLocked(ns)
339
335 if !d.disableSpecialEntities { 340 if !d.disableSpecialEntities {
336 incrementLocked(ents, groupMetaKey(k), 1 ) 341 incrementLocked(ents, groupMetaKey(k), 1 )
337 } 342 }
338 if old := ents.Get(kb); old != nil { 343 if old := ents.Get(kb); old != nil {
339 oldPM, err := rpm(old) 344 oldPM, err := rpm(old)
340 if err != nil { 345 if err != nil {
341 return err 346 return err
342 } 347 }
343 updateIndexes(d.head, k, oldPM, nil) 348 updateIndexes(d.head, k, oldPM, nil)
344 ents.Delete(kb) 349 ents.Delete(kb)
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 td.muts[rk] = []txnMutation{} 506 td.muts[rk] = []txnMutation{}
502 } 507 }
503 if !getOnly { 508 if !getOnly {
504 td.muts[rk] = append(td.muts[rk], txnMutation{key, data}) 509 td.muts[rk] = append(td.muts[rk], txnMutation{key, data})
505 } 510 }
506 511
507 return nil 512 return nil
508 } 513 }
509 514
510 func (td *txnDataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb d s.PutMultiCB) { 515 func (td *txnDataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb d s.PutMultiCB) {
511 » ents := td.parent.mutableEnts(keys[0].Namespace()) 516 » ns := keys[0].Namespace()
512 517
513 for i, k := range keys { 518 for i, k := range keys {
514 err := func() (err error) { 519 err := func() (err error) {
515 td.parent.Lock() 520 td.parent.Lock()
516 defer td.parent.Unlock() 521 defer td.parent.Unlock()
522 ents := td.parent.mutableEntsLocked(ns)
523
517 k, err = td.parent.fixKeyLocked(ents, k) 524 k, err = td.parent.fixKeyLocked(ents, k)
518 return 525 return
519 }() 526 }()
520 if err == nil { 527 if err == nil {
521 err = td.writeMutation(false, k, vals[i]) 528 err = td.writeMutation(false, k, vals[i])
522 } 529 }
523 if cb != nil { 530 if cb != nil {
524 cb(k, err) 531 cb(k, err)
525 } 532 }
526 } 533 }
(...skipping 23 matching lines...) Expand all
550 } 557 }
551 558
552 func keyBytes(key *ds.Key) []byte { 559 func keyBytes(key *ds.Key) []byte {
553 return serialize.ToBytes(ds.MkProperty(key)) 560 return serialize.ToBytes(ds.MkProperty(key))
554 } 561 }
555 562
556 func rpm(data []byte) (ds.PropertyMap, error) { 563 func rpm(data []byte) (ds.PropertyMap, error) {
557 return serialize.ReadPropertyMap(bytes.NewBuffer(data), 564 return serialize.ReadPropertyMap(bytes.NewBuffer(data),
558 serialize.WithContext, "", "") 565 serialize.WithContext, "", "")
559 } 566 }
OLDNEW
« no previous file with comments | « no previous file | impl/memory/gkvlite_utils.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698