OLD | NEW |
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 12 matching lines...) Expand all Loading... |
23 // See README.md for head schema. | 23 // See README.md for head schema. |
24 head *memStore | 24 head *memStore |
25 snap *memStore | 25 snap *memStore |
26 // For testing, see SetTransactionRetryCount. | 26 // For testing, see SetTransactionRetryCount. |
27 txnFakeRetry int | 27 txnFakeRetry int |
28 // true means that head always == snap | 28 // true means that head always == snap |
29 consistent bool | 29 consistent bool |
30 // true means that queries with insufficent indexes will pause to add th
em | 30 // true means that queries with insufficent indexes will pause to add th
em |
31 // and then continue instead of failing. | 31 // and then continue instead of failing. |
32 autoIndex bool | 32 autoIndex bool |
| 33 // true means that all of the __...__ keys which are normally automatica
lly |
| 34 // maintained will be omitted. This also means that Put with an incomple
te |
| 35 // key will become an error. |
| 36 disableSpecialEntities bool |
33 } | 37 } |
34 | 38 |
35 var ( | 39 var ( |
36 _ = memContextObj((*dataStoreData)(nil)) | 40 _ = memContextObj((*dataStoreData)(nil)) |
37 _ = sync.Locker((*dataStoreData)(nil)) | 41 _ = sync.Locker((*dataStoreData)(nil)) |
38 ) | 42 ) |
39 | 43 |
40 func newDataStoreData() *dataStoreData { | 44 func newDataStoreData() *dataStoreData { |
41 head := newMemStore() | 45 head := newMemStore() |
42 return &dataStoreData{ | 46 return &dataStoreData{ |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 d.rwlock.RUnlock() | 99 d.rwlock.RUnlock() |
96 | 100 |
97 if !ai { | 101 if !ai { |
98 return false | 102 return false |
99 } | 103 } |
100 | 104 |
101 d.addIndexes(mi.ns, []*ds.IndexDefinition{mi.Missing}) | 105 d.addIndexes(mi.ns, []*ds.IndexDefinition{mi.Missing}) |
102 return true | 106 return true |
103 } | 107 } |
104 | 108 |
| 109 func (d *dataStoreData) setDisableSpecialEntities(enabled bool) { |
| 110 d.Lock() |
| 111 defer d.Unlock() |
| 112 d.disableSpecialEntities = true |
| 113 } |
| 114 |
| 115 func (d *dataStoreData) getDisableSpecialEntities() bool { |
| 116 d.rwlock.RLock() |
| 117 defer d.rwlock.RUnlock() |
| 118 return d.disableSpecialEntities |
| 119 } |
| 120 |
105 func (d *dataStoreData) getQuerySnaps(consistent bool) (idx, head *memStore) { | 121 func (d *dataStoreData) getQuerySnaps(consistent bool) (idx, head *memStore) { |
106 d.rwlock.RLock() | 122 d.rwlock.RLock() |
107 defer d.rwlock.RUnlock() | 123 defer d.rwlock.RUnlock() |
108 if d.consistent { | 124 if d.consistent { |
109 // snap is already a consistent snapshot of head | 125 // snap is already a consistent snapshot of head |
110 return d.snap, d.snap | 126 return d.snap, d.snap |
111 } | 127 } |
112 | 128 |
113 head = d.head.Snapshot() | 129 head = d.head.Snapshot() |
114 if consistent { | 130 if consistent { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 defer d.Unlock() | 209 defer d.Unlock() |
194 | 210 |
195 coll := "ents:" + ns | 211 coll := "ents:" + ns |
196 ents := d.head.GetCollection(coll) | 212 ents := d.head.GetCollection(coll) |
197 if ents == nil { | 213 if ents == nil { |
198 ents = d.head.SetCollection(coll, nil) | 214 ents = d.head.SetCollection(coll, nil) |
199 } | 215 } |
200 return ents | 216 return ents |
201 } | 217 } |
202 | 218 |
203 func (d *dataStoreData) allocateIDs(incomplete *ds.Key, n int) int64 { | 219 func (d *dataStoreData) allocateIDs(incomplete *ds.Key, n int) (int64, error) { |
204 ents := d.mutableEnts(incomplete.Namespace()) | 220 ents := d.mutableEnts(incomplete.Namespace()) |
205 | 221 |
206 d.Lock() | 222 d.Lock() |
207 defer d.Unlock() | 223 defer d.Unlock() |
208 return d.allocateIDsLocked(ents, incomplete, n) | 224 return d.allocateIDsLocked(ents, incomplete, n) |
209 } | 225 } |
210 | 226 |
211 func (d *dataStoreData) allocateIDsLocked(ents *memCollection, incomplete *ds.Ke
y, n int) int64 { | 227 func (d *dataStoreData) allocateIDsLocked(ents *memCollection, incomplete *ds.Ke
y, n int) (int64, error) { |
| 228 » if d.disableSpecialEntities { |
| 229 » » return 0, errors.New("disableSpecialEntities is true so allocate
IDs is disabled") |
| 230 » } |
| 231 |
212 idKey := []byte(nil) | 232 idKey := []byte(nil) |
213 if incomplete.Parent() == nil { | 233 if incomplete.Parent() == nil { |
214 idKey = rootIDsKey(incomplete.Kind()) | 234 idKey = rootIDsKey(incomplete.Kind()) |
215 } else { | 235 } else { |
216 idKey = groupIDsKey(incomplete) | 236 idKey = groupIDsKey(incomplete) |
217 } | 237 } |
218 » return incrementLocked(ents, idKey, n) | 238 » return incrementLocked(ents, idKey, n), nil |
219 } | 239 } |
220 | 240 |
221 func (d *dataStoreData) fixKeyLocked(ents *memCollection, key *ds.Key) *ds.Key { | 241 func (d *dataStoreData) fixKeyLocked(ents *memCollection, key *ds.Key) (*ds.Key,
error) { |
222 if key.Incomplete() { | 242 if key.Incomplete() { |
223 » » id := d.allocateIDsLocked(ents, key, 1) | 243 » » id, err := d.allocateIDsLocked(ents, key, 1) |
| 244 » » if err != nil { |
| 245 » » » return key, err |
| 246 » » } |
224 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()) |
225 } | 248 } |
226 » return key | 249 » return key, nil |
227 } | 250 } |
228 | 251 |
229 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) { |
230 ns := keys[0].Namespace() | 253 ns := keys[0].Namespace() |
231 ents := d.mutableEnts(ns) | 254 ents := d.mutableEnts(ns) |
232 | 255 |
233 for i, k := range keys { | 256 for i, k := range keys { |
234 pmap, _ := vals[i].Save(false) | 257 pmap, _ := vals[i].Save(false) |
235 dataBytes := serialize.ToBytes(pmap) | 258 dataBytes := serialize.ToBytes(pmap) |
236 | 259 |
237 k, err := func() (ret *ds.Key, err error) { | 260 k, err := func() (ret *ds.Key, err error) { |
238 d.Lock() | 261 d.Lock() |
239 defer d.Unlock() | 262 defer d.Unlock() |
240 | 263 |
241 » » » ret = d.fixKeyLocked(ents, k) | 264 » » » ret, err = d.fixKeyLocked(ents, k) |
242 » » » incrementLocked(ents, groupMetaKey(ret), 1) | 265 » » » if err != nil { |
| 266 » » » » return |
| 267 » » » } |
| 268 » » » if !d.disableSpecialEntities { |
| 269 » » » » incrementLocked(ents, groupMetaKey(ret), 1) |
| 270 » » » } |
243 | 271 |
244 old := ents.Get(keyBytes(ret)) | 272 old := ents.Get(keyBytes(ret)) |
245 oldPM := ds.PropertyMap(nil) | 273 oldPM := ds.PropertyMap(nil) |
246 if old != nil { | 274 if old != nil { |
247 if oldPM, err = rpmWoCtx(old, ns); err != nil { | 275 if oldPM, err = rpmWoCtx(old, ns); err != nil { |
248 return | 276 return |
249 } | 277 } |
250 } | 278 } |
251 updateIndexes(d.head, ret, oldPM, pmap) | 279 updateIndexes(d.head, ret, oldPM, pmap) |
252 ents.Set(keyBytes(ret), dataBytes) | 280 ents.Set(keyBytes(ret), dataBytes) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 ents := d.mutableEnts(ns) | 325 ents := d.mutableEnts(ns) |
298 | 326 |
299 if ents != nil { | 327 if ents != nil { |
300 for _, k := range keys { | 328 for _, k := range keys { |
301 err := func() error { | 329 err := func() error { |
302 kb := keyBytes(k) | 330 kb := keyBytes(k) |
303 | 331 |
304 d.Lock() | 332 d.Lock() |
305 defer d.Unlock() | 333 defer d.Unlock() |
306 | 334 |
307 » » » » incrementLocked(ents, groupMetaKey(k), 1) | 335 » » » » if !d.disableSpecialEntities { |
| 336 » » » » » incrementLocked(ents, groupMetaKey(k), 1
) |
| 337 » » » » } |
308 if old := ents.Get(kb); old != nil { | 338 if old := ents.Get(kb); old != nil { |
309 oldPM, err := rpmWoCtx(old, ns) | 339 oldPM, err := rpmWoCtx(old, ns) |
310 if err != nil { | 340 if err != nil { |
311 return err | 341 return err |
312 } | 342 } |
313 updateIndexes(d.head, k, oldPM, nil) | 343 updateIndexes(d.head, k, oldPM, nil) |
314 ents.Delete(kb) | 344 ents.Delete(kb) |
315 if d.consistent { | 345 if d.consistent { |
316 d.snap = d.head.Snapshot() | 346 d.snap = d.head.Snapshot() |
317 } | 347 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 td.muts[rk] = append(td.muts[rk], txnMutation{key, data}) | 507 td.muts[rk] = append(td.muts[rk], txnMutation{key, data}) |
478 } | 508 } |
479 | 509 |
480 return nil | 510 return nil |
481 } | 511 } |
482 | 512 |
483 func (td *txnDataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb d
s.PutMultiCB) { | 513 func (td *txnDataStoreData) putMulti(keys []*ds.Key, vals []ds.PropertyMap, cb d
s.PutMultiCB) { |
484 ents := td.parent.mutableEnts(keys[0].Namespace()) | 514 ents := td.parent.mutableEnts(keys[0].Namespace()) |
485 | 515 |
486 for i, k := range keys { | 516 for i, k := range keys { |
487 » » func() { | 517 » » err := func() (err error) { |
488 td.parent.Lock() | 518 td.parent.Lock() |
489 defer td.parent.Unlock() | 519 defer td.parent.Unlock() |
490 » » » k = td.parent.fixKeyLocked(ents, k) | 520 » » » k, err = td.parent.fixKeyLocked(ents, k) |
| 521 » » » return |
491 }() | 522 }() |
492 » » err := td.writeMutation(false, k, vals[i]) | 523 » » if err == nil { |
| 524 » » » err = td.writeMutation(false, k, vals[i]) |
| 525 » » } |
493 if cb != nil { | 526 if cb != nil { |
494 cb(k, err) | 527 cb(k, err) |
495 } | 528 } |
496 } | 529 } |
497 } | 530 } |
498 | 531 |
499 func (td *txnDataStoreData) getMulti(keys []*ds.Key, cb ds.GetMultiCB) error { | 532 func (td *txnDataStoreData) getMulti(keys []*ds.Key, cb ds.GetMultiCB) error { |
500 return getMultiInner(keys, cb, func() (*memCollection, error) { | 533 return getMultiInner(keys, cb, func() (*memCollection, error) { |
501 err := error(nil) | 534 err := error(nil) |
502 for _, key := range keys { | 535 for _, key := range keys { |
(...skipping 22 matching lines...) Expand all Loading... |
525 | 558 |
526 func rpmWoCtx(data []byte, ns string) (ds.PropertyMap, error) { | 559 func rpmWoCtx(data []byte, ns string) (ds.PropertyMap, error) { |
527 return serialize.ReadPropertyMap(bytes.NewBuffer(data), | 560 return serialize.ReadPropertyMap(bytes.NewBuffer(data), |
528 serialize.WithoutContext, globalAppID, ns) | 561 serialize.WithoutContext, globalAppID, ns) |
529 } | 562 } |
530 | 563 |
531 func rpm(data []byte) (ds.PropertyMap, error) { | 564 func rpm(data []byte) (ds.PropertyMap, error) { |
532 return serialize.ReadPropertyMap(bytes.NewBuffer(data), | 565 return serialize.ReadPropertyMap(bytes.NewBuffer(data), |
533 serialize.WithContext, "", "") | 566 serialize.WithContext, "", "") |
534 } | 567 } |
OLD | NEW |