| 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 |