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

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: add go-slab dependency 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 var _ = memContextObj((memContext)(nil))
29
30 func newMemContext() memContext {
31 return memContext{
32 newTaskQueueData(),
33 newDataStoreData(),
34 }
35 }
36
37 type memContextIdx int
38
39 const (
40 memContextTQIdx memContextIdx = iota
41 memContextDSIdx
42 )
43
44 func (m memContext) Get(itm memContextIdx) memContextObj {
45 return m[itm]
46 }
47
48 func (m memContext) Lock() {
49 for _, itm := range m {
50 itm.Lock()
51 }
52 }
53
54 func (m memContext) Unlock() {
55 for i := len(m) - 1; i >= 0; i-- {
56 m[i].Unlock()
57 }
58 }
59
60 func (m memContext) endTxn() {
61 for _, itm := range m {
62 itm.endTxn()
63 }
64 }
65
66 func (m memContext) mkTxn(o *datastore.TransactionOptions) (memContextObj, error ) {
67 ret := make(memContext, len(m))
68 for i, itm := range m {
69 newItm, err := itm.mkTxn(o)
70 if err != nil {
71 return nil, err
72 }
73 ret[i] = newItm
74 }
75 return ret, nil
76 }
77
78 func (m memContext) canApplyTxn(txnCtxObj memContextObj) bool {
79 txnCtx := txnCtxObj.(memContext)
80 for i := range m {
81 if !m[i].canApplyTxn(txnCtx[i]) {
82 return false
83 }
84 }
85 return true
86 }
87
88 func (m memContext) applyTxn(rnd *rand.Rand, txnCtxObj memContextObj) {
89 txnCtx := txnCtxObj.(memContext)
90 for i := range m {
91 m[i].applyTxn(rnd, txnCtx[i])
92 }
93 }
94
95 // Enable adds a new memory context to c. This new memory context will have
96 // a zeroed state.
97 func Enable(c context.Context) context.Context {
98 return context.WithValue(
99 context.WithValue(c, memContextKey, newMemContext()),
100 giContextKey, &globalInfoData{})
101 }
102
103 // Use calls ALL of this packages Use* methods on c. This enables all
104 // gae/wrapper Get* api's.
105 func Use(c context.Context) context.Context {
106 return UseTQ(UseDS(UseMC(UseGI(c))))
107 }
108
109 func cur(c context.Context) (p memContext) {
110 p, _ = c.Value(memContextKey).(memContext)
111 return
112 }
113
114 type memContextKeyType int
115
116 var memContextKey memContextKeyType
117
118 // weird stuff
119
120 // RunInTransaction is here because it's really a service-wide transaction, not
121 // just in the datastore. TaskQueue behaves differently in a transaction in
122 // a couple ways, for example.
123 //
124 // It really should have been appengine.Context.RunInTransaction(func(tc...)),
125 // but because it's not, this method is on dsImpl instead to mirror the official
126 // API.
127 //
128 // The fake implementation also differs from the real implementation because the
129 // fake TaskQueue is NOT backed by the fake Datastore. This is done to make the
130 // test-access API for TaskQueue better (instead of trying to reconstitute the
131 // state of the task queue from a bunch of datastore accesses).
132 func (d *dsImpl) RunInTransaction(f func(context.Context) error, o *datastore.Tr ansactionOptions) error {
133 curMC := cur(d.c)
134
135 txnMC, err := curMC.mkTxn(o)
136 if err != nil {
137 return err
138 }
139
140 defer func() {
141 txnMC.Lock()
142 defer txnMC.Unlock()
143
144 txnMC.endTxn()
145 }()
146
147 if err = f(context.WithValue(d.c, memContextKey, txnMC)); err != nil {
148 return err
149 }
150
151 txnMC.Lock()
152 defer txnMC.Unlock()
153
154 if curMC.canApplyTxn(txnMC) {
155 curMC.applyTxn(wrapper.GetMathRand(d.c), txnMC)
156 } else {
157 return datastore.ErrConcurrentTransaction
158 }
159 return nil
160 }
OLDNEW
« no previous file with comments | « go/src/infra/gae/libs/wrapper/memory/binutils_test.go ('k') | go/src/infra/gae/libs/wrapper/memory/datastore.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698