Chromium Code Reviews| Index: impl/memory/context.go | 
| diff --git a/impl/memory/context.go b/impl/memory/context.go | 
| index 7a0deec8a36a310962cf670d47d92b517d1b0be9..0845a207e4d18d09930c7f9a8384489932938895 100644 | 
| --- a/impl/memory/context.go | 
| +++ b/impl/memory/context.go | 
| @@ -11,6 +11,7 @@ import ( | 
| ds "github.com/luci/gae/service/datastore" | 
| "github.com/luci/luci-go/common/logging/memlogger" | 
| + | 
| "golang.org/x/net/context" | 
| ) | 
| @@ -128,7 +129,6 @@ func UseWithAppID(c context.Context, aid string) context.Context { | 
| memctx := newMemContext(fqAppID) | 
| c = context.WithValue(c, memContextKey, memctx) | 
| - c = context.WithValue(c, memContextNoTxnKey, memctx) | 
| c = useGID(c, func(mod *globalInfoData) { | 
| mod.appID = aid | 
| mod.fqAppID = fqAppID | 
| @@ -136,21 +136,24 @@ func UseWithAppID(c context.Context, aid string) context.Context { | 
| return useMod(useMail(useUser(useTQ(useRDS(useMC(useGI(c))))))) | 
| } | 
| -func cur(c context.Context) (p *memContext) { | 
| - p, _ = c.Value(memContextKey).(*memContext) | 
| - return | 
| +func cur(c context.Context) (*memContext, bool) { | 
| + if txn := c.Value(currentTxnKey); txn != nil { | 
| + // We are in a Transaction. | 
| + return txn.(*memContext), true | 
| + } | 
| + return c.Value(memContextKey).(*memContext), false | 
| } | 
| -func curNoTxn(c context.Context) (p *memContext) { | 
| - p, _ = c.Value(memContextNoTxnKey).(*memContext) | 
| - return | 
| +func inTxn(c context.Context) bool { | 
| 
 
dnj
2016/09/01 15:25:39
Ended up not needing this, will delete in next pat
 
iannucci
2016/09/16 01:01:13
sgtm
 
dnj
2016/09/16 05:44:42
Done.
 
 | 
| + _, inTxn := cur(c) | 
| + return inTxn | 
| } | 
| type memContextKeyType int | 
| var ( | 
| - memContextKey memContextKeyType | 
| - memContextNoTxnKey memContextKeyType = 1 | 
| + memContextKey memContextKeyType | 
| + currentTxnKey = 1 | 
| ) | 
| // weird stuff | 
| @@ -174,7 +177,10 @@ func (d *dsImpl) RunInTransaction(f func(context.Context) error, o *ds.Transacti | 
| // Keep in separate function for defers. | 
| loopBody := func(applyForReal bool) error { | 
| - curMC := cur(d.c) | 
| + curMC, inTxn := cur(d) | 
| + if inTxn { | 
| + return errors.New("datastore: nested transactions are not supported") | 
| + } | 
| txnMC := curMC.mkTxn(o) | 
| @@ -185,7 +191,7 @@ func (d *dsImpl) RunInTransaction(f func(context.Context) error, o *ds.Transacti | 
| txnMC.endTxn() | 
| }() | 
| - if err := f(context.WithValue(d.c, memContextKey, txnMC)); err != nil { | 
| + if err := f(context.WithValue(d, currentTxnKey, txnMC)); err != nil { | 
| return err | 
| } | 
| @@ -193,7 +199,7 @@ func (d *dsImpl) RunInTransaction(f func(context.Context) error, o *ds.Transacti | 
| defer txnMC.Unlock() | 
| if applyForReal && curMC.canApplyTxn(txnMC) { | 
| - curMC.applyTxn(d.c, txnMC) | 
| + curMC.applyTxn(d, txnMC) | 
| } else { | 
| return ds.ErrConcurrentTransaction | 
| } |