| Index: impl/prod/raw_datastore.go
|
| diff --git a/impl/prod/raw_datastore.go b/impl/prod/raw_datastore.go
|
| index 0eee913e1e9e239c64f54dbce67038da5a0d1678..de70c43f491dcbd430afc49be1806c22f1be5a83 100644
|
| --- a/impl/prod/raw_datastore.go
|
| +++ b/impl/prod/raw_datastore.go
|
| @@ -14,17 +14,13 @@ import (
|
| // useRDS adds a gae.RawDatastore implementation to context, accessible
|
| // by gae.GetDS(c)
|
| func useRDS(c context.Context) context.Context {
|
| - return ds.SetRawFactory(c, func(ci context.Context, wantTxn bool) ds.RawInterface {
|
| - maybeTxnCtx := AEContext(ci)
|
| -
|
| - if wantTxn {
|
| - return rdsImpl{ci, maybeTxnCtx}
|
| - }
|
| - aeCtx := AEContextNoTxn(ci)
|
| - if maybeTxnCtx != aeCtx {
|
| - ci = context.WithValue(ci, prodContextKey, aeCtx)
|
| + return ds.SetRawFactory(c, func(ci context.Context) ds.RawInterface {
|
| + rds := rdsImpl{
|
| + userCtx: ci,
|
| + ps: getProdState(ci),
|
| }
|
| - return rdsImpl{ci, aeCtx}
|
| + rds.aeCtx = rds.ps.context(ci)
|
| + return &rds
|
| })
|
| }
|
|
|
| @@ -35,8 +31,12 @@ type rdsImpl struct {
|
| // it.
|
| userCtx context.Context
|
|
|
| - // aeCtx is the context with the appengine connection information in it.
|
| + // aeCtx is the AppEngine Context that will be used in method calls. This is
|
| + // derived from ps.
|
| aeCtx context.Context
|
| +
|
| + // ps is the current production state.
|
| + ps prodState
|
| }
|
|
|
| func idxCallbacker(err error, amt int, cb func(idx int, err error) error) error {
|
| @@ -61,7 +61,7 @@ func idxCallbacker(err error, amt int, cb func(idx int, err error) error) error
|
| return err
|
| }
|
|
|
| -func (d rdsImpl) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error {
|
| +func (d *rdsImpl) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error {
|
| // Map keys by entity type.
|
| entityMap := make(map[string][]int)
|
| for i, key := range keys {
|
| @@ -106,7 +106,7 @@ func (d rdsImpl) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error {
|
| return nil
|
| }
|
|
|
| -func (d rdsImpl) DeleteMulti(ks []*ds.Key, cb ds.DeleteMultiCB) error {
|
| +func (d *rdsImpl) DeleteMulti(ks []*ds.Key, cb ds.DeleteMultiCB) error {
|
| keys, err := dsMF2R(d.aeCtx, ks)
|
| if err == nil {
|
| err = datastore.DeleteMulti(d.aeCtx, keys)
|
| @@ -116,7 +116,7 @@ func (d rdsImpl) DeleteMulti(ks []*ds.Key, cb ds.DeleteMultiCB) error {
|
| })
|
| }
|
|
|
| -func (d rdsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMultiCB) error {
|
| +func (d *rdsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMultiCB) error {
|
| vals := make([]datastore.PropertyLoadSaver, len(keys))
|
| rkeys, err := dsMF2R(d.aeCtx, keys)
|
| if err == nil {
|
| @@ -133,7 +133,7 @@ func (d rdsImpl) GetMulti(keys []*ds.Key, _meta ds.MultiMetaGetter, cb ds.GetMul
|
| })
|
| }
|
|
|
| -func (d rdsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKeyCB) error {
|
| +func (d *rdsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKeyCB) error {
|
| rkeys, err := dsMF2R(d.aeCtx, keys)
|
| if err == nil {
|
| rvals := make([]datastore.PropertyLoadSaver, len(vals))
|
| @@ -151,7 +151,7 @@ func (d rdsImpl) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKeyCB)
|
| })
|
| }
|
|
|
| -func (d rdsImpl) fixQuery(fq *ds.FinalizedQuery) (*datastore.Query, error) {
|
| +func (d *rdsImpl) fixQuery(fq *ds.FinalizedQuery) (*datastore.Query, error) {
|
| ret := datastore.NewQuery(fq.Kind())
|
|
|
| start, end := fq.Bounds()
|
| @@ -226,11 +226,11 @@ func (d rdsImpl) fixQuery(fq *ds.FinalizedQuery) (*datastore.Query, error) {
|
| return ret, nil
|
| }
|
|
|
| -func (d rdsImpl) DecodeCursor(s string) (ds.Cursor, error) {
|
| +func (d *rdsImpl) DecodeCursor(s string) (ds.Cursor, error) {
|
| return datastore.DecodeCursor(s)
|
| }
|
|
|
| -func (d rdsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error {
|
| +func (d *rdsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error {
|
| q, err := d.fixQuery(fq)
|
| if err != nil {
|
| return err
|
| @@ -256,7 +256,7 @@ func (d rdsImpl) Run(fq *ds.FinalizedQuery, cb ds.RawRunCB) error {
|
| }
|
| }
|
|
|
| -func (d rdsImpl) Count(fq *ds.FinalizedQuery) (int64, error) {
|
| +func (d *rdsImpl) Count(fq *ds.FinalizedQuery) (int64, error) {
|
| q, err := d.fixQuery(fq)
|
| if err != nil {
|
| return 0, err
|
| @@ -265,13 +265,40 @@ func (d rdsImpl) Count(fq *ds.FinalizedQuery) (int64, error) {
|
| return int64(ret), err
|
| }
|
|
|
| -func (d rdsImpl) RunInTransaction(f func(c context.Context) error, opts *ds.TransactionOptions) error {
|
| +func (d *rdsImpl) RunInTransaction(f func(c context.Context) error, opts *ds.TransactionOptions) error {
|
| ropts := (*datastore.TransactionOptions)(opts)
|
| return datastore.RunInTransaction(d.aeCtx, func(c context.Context) error {
|
| - return f(context.WithValue(d.userCtx, prodContextKey, c))
|
| + // Derive a prodState with this transaction Context.
|
| + ps := d.ps
|
| + ps.ctx = c
|
| + ps.inTxn = true
|
| +
|
| + c = withProdState(d.userCtx, ps)
|
| + return f(c)
|
| }, ropts)
|
| }
|
|
|
| -func (d rdsImpl) Testable() ds.Testable {
|
| +func (d *rdsImpl) WithoutTransaction() context.Context {
|
| + c := d.userCtx
|
| + if d.ps.inTxn {
|
| + // We're in a transaction. Reset to non-transactional state.
|
| + ps := d.ps
|
| + ps.ctx = ps.noTxnCtx
|
| + ps.inTxn = false
|
| + c = withProdState(c, ps)
|
| + }
|
| + return c
|
| +}
|
| +
|
| +func (d *rdsImpl) CurrentTransaction() ds.Transaction {
|
| + if d.ps.inTxn {
|
| + // Since we don't distinguish between transactions (yet), we just need this
|
| + // to be non-nil.
|
| + return struct{}{}
|
| + }
|
| + return nil
|
| +}
|
| +
|
| +func (d *rdsImpl) GetTestable() ds.Testable {
|
| return nil
|
| }
|
|
|