Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(904)

Side by Side Diff: go/src/infra/gae/libs/wrapper/memory/context.go

Issue 1152383003: Simple memory testing for gae/wrapper (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@better_context_lite
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package memory
6
7 import (
8 "infra/gae/libs/wrapper"
9 "math/rand"
10 "sync"
11
12 "golang.org/x/net/context"
13
14 "appengine/datastore"
15 )
16
17 type memContextObj interface {
18 sync.Locker
19 canApplyTxn(m memContextObj) bool
20 applyTxn(rnd *rand.Rand, m memContextObj)
21
22 endTxn()
23 mkTxn(*datastore.TransactionOptions) (memContextObj, error)
24 }
25
26 type memContext []memContextObj
27
28 func newMemContext() memContext {
29 return memContext{
30 newTaskQueueData(),
31 newDataStoreData(),
32 }
33 }
34
35 type memContextIdx int
36
37 const (
38 memContextTQIdx memContextIdx = iota
39 memContextDSIdx
40 )
41
42 func (m memContext) Get(itm memContextIdx) memContextObj {
43 return m[itm]
44 }
45
46 func (m memContext) Lock() {
47 for _, itm := range m {
48 itm.Lock()
49 }
50 }
51
52 func (m memContext) Unlock() {
53 for i := len(m) - 1; i >= 0; i-- {
54 m[i].Unlock()
55 }
56 }
57
58 func (m memContext) endTxn() {
59 for _, itm := range m {
60 itm.endTxn()
61 }
62 }
63
64 func (m memContext) mkTxn(o *datastore.TransactionOptions) (memContext, error) {
65 ret := make(memContext, len(m))
66 for i, itm := range m {
67 newItm, err := itm.mkTxn(o)
68 if err != nil {
69 return nil, err
70 }
71 ret[i] = newItm
72 }
73 return ret, nil
74 }
75
76 func (m memContext) canApplyTxn(txnCtx memContext) bool {
77 for i := range m {
78 if !m[i].canApplyTxn(txnCtx[i]) {
79 return false
80 }
81 }
82 return true
83 }
84
85 func (m memContext) applyTxn(rnd *rand.Rand, txnCtx memContext) {
86 for i := range m {
87 m[i].applyTxn(rnd, txnCtx[i])
88 }
89 }
90
91 // Enable adds a new memory context to c. This new memory context will have
92 // a zeroed state.
93 func Enable(c context.Context) context.Context {
94 return context.WithValue(
95 context.WithValue(c, memContextKey, newMemContext()),
96 giContextKey, &globalInfoData{})
97 }
98
99 // Use calls ALL of this packages Use* methods on c. This enables all
100 // gae/wrapper Get* api's.
101 func Use(c context.Context) context.Context {
102 return UseTQ(UseDS(UseMC(UseGI(c))))
103 }
104
105 func cur(c context.Context) (p memContext) {
106 p, _ = c.Value(memContextKey).(memContext)
107 return
108 }
109
110 type memContextKeyType int
111
112 var memContextKey memContextKeyType
113
114 // weird stuff
115
116 // RunInTransaction is here because it's really a service-wide transaction, not
117 // just in the datastore. TaskQueue behaves differently in a transaction in
118 // a couple ways, for example.
119 //
120 // It really should have been appengine.Context.RunInTransaction(func(tc...)),
121 // but because it's not, this method is on dsImpl instead to mirror the official
122 // API.
123 //
124 // The fake implementation also differs from the real implementation because the
125 // fake TaskQueue is NOT backed by the fake Datastore. This is done to make the
126 // test-access API for TaskQueue better (instead of trying to reconstitute the
127 // state of the task queue from a bunch of datastore accesses).
128 func (d *dsImpl) RunInTransaction(f func(context.Context) error, o *datastore.Tr ansactionOptions) error {
129 curMC := cur(d.c)
130
131 txnMC, err := curMC.mkTxn(o)
132 if err != nil {
133 return err
134 }
135
136 defer func() {
137 txnMC.Lock()
138 defer txnMC.Unlock()
139
140 txnMC.endTxn()
141 }()
142
143 if err = f(context.WithValue(d.c, memContextKey, txnMC)); err != nil {
144 return err
145 }
146
147 txnMC.Lock()
148 defer txnMC.Unlock()
149
150 if curMC.canApplyTxn(txnMC) {
151 curMC.applyTxn(wrapper.GetMathRand(d.c), txnMC)
152 } else {
153 return datastore.ErrConcurrentTransaction
154 }
155 return nil
156 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698