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

Side by Side Diff: impl/memory/context.go

Issue 1494223002: Add API to allow you to get the non-transactional datastore or taskqueue. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: Created 5 years 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
« no previous file with comments | « no previous file | impl/memory/datastore.go » ('j') | impl/memory/datastore.go » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "errors" 8 "errors"
9 "sync" 9 "sync"
10 10
11 ds "github.com/luci/gae/service/datastore" 11 ds "github.com/luci/gae/service/datastore"
12 "golang.org/x/net/context" 12 "golang.org/x/net/context"
13 ) 13 )
14 14
15 var serializationDeterministic = false 15 var serializationDeterministic = false
16 16
17 type memContextObj interface { 17 type memContextObj interface {
18 sync.Locker 18 sync.Locker
19 canApplyTxn(m memContextObj) bool 19 canApplyTxn(m memContextObj) bool
20 applyTxn(c context.Context, m memContextObj) 20 applyTxn(c context.Context, m memContextObj)
21 21
22 endTxn() 22 endTxn()
23 mkTxn(*ds.TransactionOptions) memContextObj 23 mkTxn(*ds.TransactionOptions) memContextObj
24 } 24 }
25 25
26 type memContext []memContextObj 26 type memContext []memContextObj
27 27
28 var _ = memContextObj((memContext)(nil)) 28 var _ memContextObj = (*memContext)(nil)
iannucci 2015/12/04 03:35:10 changed to a pointer to be == comparable
29 29
30 func newMemContext(aid string) memContext { 30 func newMemContext(aid string) *memContext {
31 » return memContext{ 31 » return &memContext{
32 newTaskQueueData(), 32 newTaskQueueData(),
33 newDataStoreData(aid), 33 newDataStoreData(aid),
34 } 34 }
35 } 35 }
36 36
37 type memContextIdx int 37 type memContextIdx int
38 38
39 const ( 39 const (
40 memContextTQIdx memContextIdx = iota 40 memContextTQIdx memContextIdx = iota
41 memContextDSIdx 41 memContextDSIdx
42 ) 42 )
43 43
44 func (m memContext) Get(itm memContextIdx) memContextObj { 44 func (m *memContext) Get(itm memContextIdx) memContextObj {
45 » return m[itm] 45 » return (*m)[itm]
46 } 46 }
47 47
48 func (m memContext) Lock() { 48 func (m *memContext) Lock() {
49 » for _, itm := range m { 49 » for _, itm := range *m {
50 itm.Lock() 50 itm.Lock()
51 } 51 }
52 } 52 }
53 53
54 func (m memContext) Unlock() { 54 func (m *memContext) Unlock() {
55 » for i := len(m) - 1; i >= 0; i-- { 55 » for i := len(*m) - 1; i >= 0; i-- {
56 » » m[i].Unlock() 56 » » (*m)[i].Unlock()
57 } 57 }
58 } 58 }
59 59
60 func (m memContext) endTxn() { 60 func (m *memContext) endTxn() {
61 » for _, itm := range m { 61 » for _, itm := range *m {
62 itm.endTxn() 62 itm.endTxn()
63 } 63 }
64 } 64 }
65 65
66 func (m memContext) mkTxn(o *ds.TransactionOptions) memContextObj { 66 func (m *memContext) mkTxn(o *ds.TransactionOptions) memContextObj {
67 » ret := make(memContext, len(m)) 67 » ret := make(memContext, len(*m))
68 » for i, itm := range m { 68 » for i, itm := range *m {
69 ret[i] = itm.mkTxn(o) 69 ret[i] = itm.mkTxn(o)
70 } 70 }
71 » return ret 71 » return &ret
72 } 72 }
73 73
74 func (m memContext) canApplyTxn(txnCtxObj memContextObj) bool { 74 func (m *memContext) canApplyTxn(txnCtxObj memContextObj) bool {
75 » txnCtx := txnCtxObj.(memContext) 75 » txnCtx := *txnCtxObj.(*memContext)
76 » for i := range m { 76 » for i := range *m {
77 » » if !m[i].canApplyTxn(txnCtx[i]) { 77 » » if !(*m)[i].canApplyTxn(txnCtx[i]) {
78 return false 78 return false
79 } 79 }
80 } 80 }
81 return true 81 return true
82 } 82 }
83 83
84 func (m memContext) applyTxn(c context.Context, txnCtxObj memContextObj) { 84 func (m *memContext) applyTxn(c context.Context, txnCtxObj memContextObj) {
85 » txnCtx := txnCtxObj.(memContext) 85 » txnCtx := *txnCtxObj.(*memContext)
86 » for i := range m { 86 » for i := range *m {
87 » » m[i].applyTxn(c, txnCtx[i]) 87 » » (*m)[i].applyTxn(c, txnCtx[i])
88 } 88 }
89 } 89 }
90 90
91 // Use calls UseWithAppID with the appid of "dev~app" 91 // Use calls UseWithAppID with the appid of "dev~app"
92 func Use(c context.Context) context.Context { 92 func Use(c context.Context) context.Context {
93 return UseWithAppID(c, "dev~app") 93 return UseWithAppID(c, "dev~app")
94 } 94 }
95 95
96 // UseWithAppID adds implementations for the following gae interfaces to the 96 // UseWithAppID adds implementations for the following gae interfaces to the
97 // context: 97 // context:
98 // * gae.Datastore 98 // * gae.Datastore
99 // * gae.TaskQueue 99 // * gae.TaskQueue
100 // * gae.Memcache 100 // * gae.Memcache
101 // * gae.GlobalInfo 101 // * gae.GlobalInfo
102 // 102 //
103 // The application id wil be set to 'aid', and will not be modifiable in this 103 // The application id wil be set to 'aid', and will not be modifiable in this
104 // context. 104 // context.
105 // 105 //
106 // These can be retrieved with the gae.Get functions. 106 // These can be retrieved with the gae.Get functions.
107 // 107 //
108 // The implementations are all backed by an in-memory implementation, and start 108 // The implementations are all backed by an in-memory implementation, and start
109 // with an empty state. 109 // with an empty state.
110 // 110 //
111 // Using this more than once per context.Context will cause a panic. 111 // Using this more than once per context.Context will cause a panic.
112 func UseWithAppID(c context.Context, aid string) context.Context { 112 func UseWithAppID(c context.Context, aid string) context.Context {
113 if c.Value(memContextKey) != nil { 113 if c.Value(memContextKey) != nil {
114 panic(errors.New("memory.Use: called twice on the same Context") ) 114 panic(errors.New("memory.Use: called twice on the same Context") )
115 } 115 }
116 » c = context.WithValue( 116 » memctx := newMemContext(aid)
117 » » context.WithValue(c, memContextKey, newMemContext(aid)), 117 » c = context.WithValue(c, memContextKey, memctx)
118 » » giContextKey, &globalInfoData{appid: aid}) 118 » c = context.WithValue(c, memContextNoTxnKey, memctx)
119 » c = context.WithValue(c, giContextKey, &globalInfoData{appid: aid})
120
119 return useTQ(useRDS(useMC(useGI(c, aid)))) 121 return useTQ(useRDS(useMC(useGI(c, aid))))
120 } 122 }
121 123
122 func cur(c context.Context) (p memContext) { 124 func cur(c context.Context) (p *memContext) {
123 » p, _ = c.Value(memContextKey).(memContext) 125 » p, _ = c.Value(memContextKey).(*memContext)
126 » return
127 }
128
129 func curNoTxn(c context.Context) (p *memContext) {
130 » p, _ = c.Value(memContextNoTxnKey).(*memContext)
124 return 131 return
125 } 132 }
126 133
127 type memContextKeyType int 134 type memContextKeyType int
128 135
129 var memContextKey memContextKeyType 136 var (
137 » memContextKey memContextKeyType
138 » memContextNoTxnKey memContextKeyType = 1
139 )
130 140
131 // weird stuff 141 // weird stuff
132 142
133 // RunInTransaction is here because it's really a service-wide transaction, not 143 // RunInTransaction is here because it's really a service-wide transaction, not
134 // just in the datastore. TaskQueue behaves differently in a transaction in 144 // just in the datastore. TaskQueue behaves differently in a transaction in
135 // a couple ways, for example. 145 // a couple ways, for example.
136 // 146 //
137 // It really should have been appengine.Context.RunInTransaction(func(tc...)), 147 // It really should have been appengine.Context.RunInTransaction(func(tc...)),
138 // but because it's not, this method is on dsImpl instead to mirror the official 148 // but because it's not, this method is on dsImpl instead to mirror the official
139 // API. 149 // API.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 if o != nil && o.Attempts != 0 { 190 if o != nil && o.Attempts != 0 {
181 attempts = o.Attempts 191 attempts = o.Attempts
182 } 192 }
183 for attempt := 0; attempt < attempts; attempt++ { 193 for attempt := 0; attempt < attempts; attempt++ {
184 if err := loopBody(attempt >= d.data.txnFakeRetry); err != ds.Er rConcurrentTransaction { 194 if err := loopBody(attempt >= d.data.txnFakeRetry); err != ds.Er rConcurrentTransaction {
185 return err 195 return err
186 } 196 }
187 } 197 }
188 return ds.ErrConcurrentTransaction 198 return ds.ErrConcurrentTransaction
189 } 199 }
OLDNEW
« no previous file with comments | « no previous file | impl/memory/datastore.go » ('j') | impl/memory/datastore.go » ('J')

Powered by Google App Engine
This is Rietveld 408576698