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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 } else { | 100 } else { |
101 idKey = groupIDsKey(key) | 101 idKey = groupIDsKey(key) |
102 } | 102 } |
103 id := incrementLocked(ents, idKey) | 103 id := incrementLocked(ents, idKey) |
104 key = rds.NewKey(key.AppID(), key.Namespace(), key.Kind(), "", i
d, key.Parent()) | 104 key = rds.NewKey(key.AppID(), key.Namespace(), key.Kind(), "", i
d, key.Parent()) |
105 } | 105 } |
106 | 106 |
107 return ents, key | 107 return ents, key |
108 } | 108 } |
109 | 109 |
110 func (d *dataStoreData) put(ns string, key rds.Key, pls rds.PropertyLoadSaver) (
rds.Key, error) { | 110 func (d *dataStoreData) putMulti(keys []rds.Key, vals []rds.PropertyLoadSaver, c
b rds.PutMultiCB) { |
111 » keys, errs := d.putMulti(ns, []rds.Key{key}, []rds.PropertyLoadSaver{pls
}) | |
112 » if errs == nil { | |
113 » » return keys[0], nil | |
114 » } | |
115 » return nil, errors.SingleError(errs) | |
116 } | |
117 | |
118 func (d *dataStoreData) putMulti(ns string, keys []rds.Key, plss []rds.PropertyL
oadSaver) ([]rds.Key, error) { | |
119 » pmaps, err := putMultiPrelim(ns, keys, plss) | |
120 » if err != nil { | |
121 » » return nil, err | |
122 » } | |
123 » return d.putMultiInner(keys, pmaps) | |
124 } | |
125 | |
126 func putMultiPrelim(ns string, keys []rds.Key, plss []rds.PropertyLoadSaver) ([]
rds.PropertyMap, error) { | |
127 » err := multiValid(keys, plss, ns, true, false) | |
128 » if err != nil { | |
129 » » return nil, err | |
130 » } | |
131 » pmaps := make([]rds.PropertyMap, len(keys)) | |
132 » lme := errors.LazyMultiError{Size: len(keys)} | |
133 » for i, pls := range plss { | |
134 » » pm, err := pls.Save(false) | |
135 » » lme.Assign(i, err) | |
136 » » pmaps[i] = pm | |
137 » } | |
138 » return pmaps, lme.Get() | |
139 } | |
140 | |
141 func (d *dataStoreData) putMultiInner(keys []rds.Key, data []rds.PropertyMap) ([
]rds.Key, error) { | |
142 » retKeys := make([]rds.Key, len(keys)) | |
143 » lme := errors.LazyMultiError{Size: len(keys)} | |
144 for i, k := range keys { | 111 for i, k := range keys { |
145 buf := &bytes.Buffer{} | 112 buf := &bytes.Buffer{} |
146 » » data[i].Write(buf, rds.WithoutContext) | 113 » » pmap := vals[i].(rds.PropertyMap) |
| 114 » » pmap.Write(buf, rds.WithoutContext) |
147 dataBytes := buf.Bytes() | 115 dataBytes := buf.Bytes() |
148 | 116 |
149 » » rKey, err := func() (ret rds.Key, err error) { | 117 » » k, err := func() (ret rds.Key, err error) { |
150 d.rwlock.Lock() | 118 d.rwlock.Lock() |
151 defer d.rwlock.Unlock() | 119 defer d.rwlock.Unlock() |
152 | 120 |
153 ents, ret := d.entsKeyLocked(k) | 121 ents, ret := d.entsKeyLocked(k) |
154 incrementLocked(ents, groupMetaKey(ret)) | 122 incrementLocked(ents, groupMetaKey(ret)) |
155 | 123 |
156 old := ents.Get(keyBytes(rds.WithoutContext, ret)) | 124 old := ents.Get(keyBytes(rds.WithoutContext, ret)) |
157 oldPM := rds.PropertyMap(nil) | 125 oldPM := rds.PropertyMap(nil) |
158 if old != nil { | 126 if old != nil { |
159 if oldPM, err = rpmWoCtx(old, ret.Namespace());
err != nil { | 127 if oldPM, err = rpmWoCtx(old, ret.Namespace());
err != nil { |
160 return | 128 return |
161 } | 129 } |
162 } | 130 } |
163 » » » updateIndicies(d.store, ret, oldPM, data[i]) | 131 » » » updateIndicies(d.store, ret, oldPM, pmap) |
164 ents.Set(keyBytes(rds.WithoutContext, ret), dataBytes) | 132 ents.Set(keyBytes(rds.WithoutContext, ret), dataBytes) |
165 return | 133 return |
166 }() | 134 }() |
167 » » lme.Assign(i, err) | 135 » » if cb != nil { |
168 » » retKeys[i] = rKey | 136 » » » cb(k, err) |
| 137 » » } |
169 } | 138 } |
170 return retKeys, lme.Get() | |
171 } | 139 } |
172 | 140 |
173 func getMultiInner(ns string, keys []rds.Key, plss []rds.PropertyLoadSaver, getC
oll func() (*memCollection, error)) error { | 141 func getMultiInner(keys []rds.Key, cb rds.GetMultiCB, getColl func() (*memCollec
tion, error)) error { |
174 » if err := multiValid(keys, plss, ns, false, true); err != nil { | |
175 » » return err | |
176 » } | |
177 | |
178 » lme := errors.LazyMultiError{Size: len(keys)} | |
179 | |
180 ents, err := getColl() | 142 ents, err := getColl() |
181 if err != nil { | 143 if err != nil { |
182 return err | 144 return err |
183 } | 145 } |
184 if ents == nil { | 146 if ents == nil { |
185 » » for i := range keys { | 147 » » for range keys { |
186 » » » lme.Assign(i, rds.ErrNoSuchEntity) | 148 » » » cb(nil, rds.ErrNoSuchEntity) |
187 } | 149 } |
188 » » return lme.Get() | 150 » » return nil |
189 } | 151 } |
190 | 152 |
191 » for i, k := range keys { | 153 » for _, k := range keys { |
192 pdata := ents.Get(keyBytes(rds.WithoutContext, k)) | 154 pdata := ents.Get(keyBytes(rds.WithoutContext, k)) |
193 if pdata == nil { | 155 if pdata == nil { |
194 » » » lme.Assign(i, rds.ErrNoSuchEntity) | 156 » » » cb(nil, rds.ErrNoSuchEntity) |
195 continue | 157 continue |
196 } | 158 } |
197 | 159 » » cb(rpmWoCtx(pdata, k.Namespace())) |
198 » » got, err := rpmWoCtx(pdata, ns) | |
199 » » if err != nil { | |
200 » » » lme.Assign(i, err) | |
201 » » » continue | |
202 » » } | |
203 | |
204 » » lme.Assign(i, plss[i].Load(got)) | |
205 } | 160 } |
206 » return lme.Get() | 161 » return nil |
207 } | 162 } |
208 | 163 |
209 func (d *dataStoreData) get(ns string, key rds.Key, pls rds.PropertyLoadSaver) e
rror { | 164 func (d *dataStoreData) getMulti(keys []rds.Key, cb rds.GetMultiCB) error { |
210 » return errors.SingleError(d.getMulti(ns, []rds.Key{key}, []rds.PropertyL
oadSaver{pls})) | 165 » getMultiInner(keys, cb, func() (*memCollection, error) { |
211 } | |
212 | |
213 func (d *dataStoreData) getMulti(ns string, keys []rds.Key, plss []rds.PropertyL
oadSaver) error { | |
214 » return getMultiInner(ns, keys, plss, func() (*memCollection, error) { | |
215 d.rwlock.RLock() | 166 d.rwlock.RLock() |
216 s := d.store.Snapshot() | 167 s := d.store.Snapshot() |
217 d.rwlock.RUnlock() | 168 d.rwlock.RUnlock() |
218 | 169 |
219 » » return s.GetCollection("ents:" + ns), nil | 170 » » return s.GetCollection("ents:" + keys[0].Namespace()), nil |
220 }) | 171 }) |
| 172 return nil |
221 } | 173 } |
222 | 174 |
223 func (d *dataStoreData) del(ns string, key rds.Key) (err error) { | 175 func (d *dataStoreData) delMulti(keys []rds.Key, cb rds.DeleteMultiCB) { |
224 » return errors.SingleError(d.delMulti(ns, []rds.Key{key})) | |
225 } | |
226 | |
227 func (d *dataStoreData) delMulti(ns string, keys []rds.Key) error { | |
228 » lme := errors.LazyMultiError{Size: len(keys)} | |
229 toDel := make([][]byte, 0, len(keys)) | 176 toDel := make([][]byte, 0, len(keys)) |
230 » for i, k := range keys { | 177 » for _, k := range keys { |
231 » » if !rds.KeyValid(k, ns, false) { | |
232 » » » lme.Assign(i, rds.ErrInvalidKey) | |
233 » » » continue | |
234 » » } | |
235 toDel = append(toDel, keyBytes(rds.WithoutContext, k)) | 178 toDel = append(toDel, keyBytes(rds.WithoutContext, k)) |
236 } | 179 } |
237 » err := lme.Get() | 180 » ns := keys[0].Namespace() |
238 » if err != nil { | |
239 » » return err | |
240 » } | |
241 | 181 |
242 d.rwlock.Lock() | 182 d.rwlock.Lock() |
243 defer d.rwlock.Unlock() | 183 defer d.rwlock.Unlock() |
244 | 184 |
245 ents := d.store.GetCollection("ents:" + ns) | 185 ents := d.store.GetCollection("ents:" + ns) |
246 if ents == nil { | |
247 return nil | |
248 } | |
249 | 186 |
250 for i, k := range keys { | 187 for i, k := range keys { |
251 » » incrementLocked(ents, groupMetaKey(k)) | 188 » » if ents != nil { |
252 » » kb := toDel[i] | 189 » » » incrementLocked(ents, groupMetaKey(k)) |
253 » » old := ents.Get(kb) | 190 » » » kb := toDel[i] |
254 » » oldPM := rds.PropertyMap(nil) | 191 » » » if old := ents.Get(kb); old != nil { |
255 » » if old != nil { | 192 » » » » oldPM, err := rpmWoCtx(old, ns) |
256 » » » if oldPM, err = rpmWoCtx(old, ns); err != nil { | 193 » » » » if err != nil { |
257 » » » » lme.Assign(i, err) | 194 » » » » » if cb != nil { |
258 » » » » continue | 195 » » » » » » cb(err) |
| 196 » » » » » } |
| 197 » » » » » continue |
| 198 » » » » } |
| 199 » » » » updateIndicies(d.store, k, oldPM, nil) |
| 200 » » » » ents.Delete(kb) |
259 } | 201 } |
260 } | 202 } |
261 » » updateIndicies(d.store, k, oldPM, nil) | 203 » » if cb != nil { |
262 » » ents.Delete(kb) | 204 » » » cb(nil) |
| 205 » » } |
263 } | 206 } |
264 return lme.Get() | |
265 } | 207 } |
266 | 208 |
267 func (d *dataStoreData) canApplyTxn(obj memContextObj) bool { | 209 func (d *dataStoreData) canApplyTxn(obj memContextObj) bool { |
268 // TODO(riannucci): implement with Flush/FlushRevert for persistance. | 210 // TODO(riannucci): implement with Flush/FlushRevert for persistance. |
269 | 211 |
270 txn := obj.(*txnDataStoreData) | 212 txn := obj.(*txnDataStoreData) |
271 for rk, muts := range txn.muts { | 213 for rk, muts := range txn.muts { |
272 if len(muts) == 0 { // read-only | 214 if len(muts) == 0 { // read-only |
273 continue | 215 continue |
274 } | 216 } |
(...skipping 14 matching lines...) Expand all Loading... |
289 } | 231 } |
290 return true | 232 return true |
291 } | 233 } |
292 | 234 |
293 func (d *dataStoreData) applyTxn(c context.Context, obj memContextObj) { | 235 func (d *dataStoreData) applyTxn(c context.Context, obj memContextObj) { |
294 txn := obj.(*txnDataStoreData) | 236 txn := obj.(*txnDataStoreData) |
295 for _, muts := range txn.muts { | 237 for _, muts := range txn.muts { |
296 if len(muts) == 0 { // read-only | 238 if len(muts) == 0 { // read-only |
297 continue | 239 continue |
298 } | 240 } |
| 241 // TODO(riannucci): refactor to do just 1 putMulti, and 1 delMul
ti |
299 for _, m := range muts { | 242 for _, m := range muts { |
300 err := error(nil) | 243 err := error(nil) |
| 244 k := m.key |
301 if m.data == nil { | 245 if m.data == nil { |
302 » » » » err = d.del(m.key.Namespace(), m.key) | 246 » » » » d.delMulti([]rds.Key{k}, |
| 247 » » » » » func(e error) { err = e }) |
303 } else { | 248 } else { |
304 » » » » _, err = d.put(m.key.Namespace(), m.key, m.data) | 249 » » » » d.putMulti([]rds.Key{m.key}, []rds.PropertyLoadS
aver{m.data}, |
| 250 » » » » » func(_ rds.Key, e error) { err = e }) |
305 } | 251 } |
| 252 err = errors.SingleError(err) |
306 if err != nil { | 253 if err != nil { |
307 panic(err) | 254 panic(err) |
308 } | 255 } |
309 } | 256 } |
310 } | 257 } |
311 } | 258 } |
312 | 259 |
313 func (d *dataStoreData) mkTxn(o *rds.TransactionOptions) memContextObj { | 260 func (d *dataStoreData) mkTxn(o *rds.TransactionOptions) memContextObj { |
314 return &txnDataStoreData{ | 261 return &txnDataStoreData{ |
315 // alias to the main datastore's so that testing code can have p
rimitive | 262 // alias to the main datastore's so that testing code can have p
rimitive |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 } | 352 } |
406 td.muts[rk] = []txnMutation{} | 353 td.muts[rk] = []txnMutation{} |
407 } | 354 } |
408 if !getOnly { | 355 if !getOnly { |
409 td.muts[rk] = append(td.muts[rk], txnMutation{key, data}) | 356 td.muts[rk] = append(td.muts[rk], txnMutation{key, data}) |
410 } | 357 } |
411 | 358 |
412 return nil | 359 return nil |
413 } | 360 } |
414 | 361 |
415 func (td *txnDataStoreData) put(ns string, key rds.Key, pls rds.PropertyLoadSave
r) (rds.Key, error) { | 362 func (td *txnDataStoreData) putMulti(keys []rds.Key, vals []rds.PropertyLoadSave
r, cb rds.PutMultiCB) { |
416 » keys, errs := td.putMulti(ns, []rds.Key{key}, []rds.PropertyLoadSaver{pl
s}) | |
417 » if errs == nil { | |
418 » » return keys[0], nil | |
419 » } | |
420 » return nil, errors.SingleError(errs) | |
421 } | |
422 | |
423 func (td *txnDataStoreData) putMulti(ns string, keys []rds.Key, plss []rds.Prope
rtyLoadSaver) ([]rds.Key, error) { | |
424 » pmaps, err := putMultiPrelim(ns, keys, plss) | |
425 » if err != nil { | |
426 » » return nil, err | |
427 » } | |
428 | |
429 » retKeys := make([]rds.Key, len(keys)) | |
430 » lme := errors.LazyMultiError{Size: len(keys)} | |
431 for i, k := range keys { | 363 for i, k := range keys { |
432 func() { | 364 func() { |
433 td.parent.Lock() | 365 td.parent.Lock() |
434 defer td.parent.Unlock() | 366 defer td.parent.Unlock() |
435 _, k = td.parent.entsKeyLocked(k) | 367 _, k = td.parent.entsKeyLocked(k) |
436 }() | 368 }() |
437 » » lme.Assign(i, td.writeMutation(false, k, pmaps[i])) | 369 » » err := td.writeMutation(false, k, vals[i].(rds.PropertyMap)) |
438 » » retKeys[i] = k | 370 » » if cb != nil { |
| 371 » » » cb(k, err) |
| 372 » » } |
439 } | 373 } |
440 | |
441 return retKeys, lme.Get() | |
442 } | 374 } |
443 | 375 |
444 func (td *txnDataStoreData) get(ns string, key rds.Key, pls rds.PropertyLoadSave
r) error { | 376 func (td *txnDataStoreData) getMulti(keys []rds.Key, cb rds.GetMultiCB) error { |
445 » return errors.SingleError(td.getMulti(ns, []rds.Key{key}, []rds.Property
LoadSaver{pls})) | 377 » return getMultiInner(keys, cb, func() (*memCollection, error) { |
446 } | 378 » » err := error(nil) |
447 | 379 » » for _, key := range keys { |
448 func (td *txnDataStoreData) getMulti(ns string, keys []rds.Key, plss []rds.Prope
rtyLoadSaver) error { | 380 » » » err = td.writeMutation(true, key, nil) |
449 » return getMultiInner(ns, keys, plss, func() (*memCollection, error) { | 381 » » » if err != nil { |
450 » » lme := errors.LazyMultiError{Size: len(keys)} | 382 » » » » return nil, err |
451 » » for i, k := range keys { | 383 » » » } |
452 » » » lme.Assign(i, td.writeMutation(true, k, nil)) | |
453 } | 384 } |
454 » » return td.snap.GetCollection("ents:" + ns), lme.Get() | 385 » » return td.snap.GetCollection("ents:" + keys[0].Namespace()), nil |
455 }) | 386 }) |
456 } | 387 } |
457 | 388 |
458 func (td *txnDataStoreData) del(ns string, key rds.Key) error { | 389 func (td *txnDataStoreData) delMulti(keys []rds.Key, cb rds.DeleteMultiCB) error
{ |
459 » return errors.SingleError(td.delMulti(ns, []rds.Key{key})) | 390 » for _, k := range keys { |
460 } | 391 » » err := td.writeMutation(false, k, nil) |
461 | 392 » » if cb != nil { |
462 func (td *txnDataStoreData) delMulti(ns string, keys []rds.Key) error { | 393 » » » cb(err) |
463 » lme := errors.LazyMultiError{Size: len(keys)} | |
464 » for i, k := range keys { | |
465 » » if !rds.KeyValid(k, ns, false) { | |
466 » » » lme.Assign(i, rds.ErrInvalidKey) | |
467 » » } else { | |
468 » » » lme.Assign(i, td.writeMutation(false, k, nil)) | |
469 } | 394 } |
470 } | 395 } |
471 » return lme.Get() | 396 » return nil |
472 } | 397 } |
473 | 398 |
474 func keyBytes(ctx rds.KeyContext, key rds.Key) []byte { | 399 func keyBytes(ctx rds.KeyContext, key rds.Key) []byte { |
475 buf := &bytes.Buffer{} | 400 buf := &bytes.Buffer{} |
476 rds.WriteKey(buf, ctx, key) | 401 rds.WriteKey(buf, ctx, key) |
477 return buf.Bytes() | 402 return buf.Bytes() |
478 } | 403 } |
479 | 404 |
480 func rpmWoCtx(data []byte, ns string) (rds.PropertyMap, error) { | 405 func rpmWoCtx(data []byte, ns string) (rds.PropertyMap, error) { |
481 ret := rds.PropertyMap{} | 406 ret := rds.PropertyMap{} |
482 err := ret.Read(bytes.NewBuffer(data), rds.WithoutContext, globalAppID,
ns) | 407 err := ret.Read(bytes.NewBuffer(data), rds.WithoutContext, globalAppID,
ns) |
483 return ret, err | 408 return ret, err |
484 } | 409 } |
485 | 410 |
486 func rpm(data []byte) (rds.PropertyMap, error) { | 411 func rpm(data []byte) (rds.PropertyMap, error) { |
487 ret := rds.PropertyMap{} | 412 ret := rds.PropertyMap{} |
488 err := ret.Read(bytes.NewBuffer(data), rds.WithContext, "", "") | 413 err := ret.Read(bytes.NewBuffer(data), rds.WithContext, "", "") |
489 return ret, err | 414 return ret, err |
490 } | 415 } |
491 | 416 |
492 func multiValid(keys []rds.Key, plss []rds.PropertyLoadSaver, ns string, potenti
alKey, allowSpecial bool) error { | 417 type keyitem interface { |
493 » vfn := func(k rds.Key) bool { | 418 » Key() rds.Key |
494 » » return !rds.KeyIncomplete(k) && rds.KeyValid(k, ns, allowSpecial
) | |
495 » } | |
496 » if potentialKey { | |
497 » » vfn = func(k rds.Key) bool { | |
498 » » » // adds an id to k if it's incomplete. | |
499 » » » if rds.KeyIncomplete(k) { | |
500 » » » » k = rds.NewKey(k.AppID(), k.Namespace(), k.Kind(
), "", 1, k.Parent()) | |
501 » » » } | |
502 » » » return rds.KeyValid(k, ns, allowSpecial) | |
503 » » } | |
504 » } | |
505 | |
506 » if keys == nil || plss == nil { | |
507 » » return errors.New("gae: key or plss slices were nil") | |
508 » } | |
509 » if len(keys) != len(plss) { | |
510 » » return errors.New("gae: key and dst slices have different length
") | |
511 » } | |
512 » lme := errors.LazyMultiError{Size: len(keys)} | |
513 » for i, k := range keys { | |
514 » » if !vfn(k) { | |
515 » » » lme.Assign(i, rds.ErrInvalidKey) | |
516 » » } | |
517 » } | |
518 » return lme.Get() | |
519 } | 419 } |
OLD | NEW |