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

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

Issue 1243323002: Refactor a bit. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix golint Created 5 years, 5 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
« no previous file with comments | « impl/memory/globalinfo.go ('k') | impl/memory/memcache_test.go » ('j') | no next file with comments »
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 "sync" 8 "sync"
9 "time" 9 "time"
10 10
11 "golang.org/x/net/context" 11 "golang.org/x/net/context"
12 12
13 » "github.com/luci/gae" 13 » "github.com/luci/gae/impl/dummy"
14 » "github.com/luci/gae/dummy" 14 » mc "github.com/luci/gae/service/memcache"
15
16 "github.com/luci/luci-go/common/clock" 15 "github.com/luci/luci-go/common/clock"
17 ) 16 )
18 17
19 type mcItem struct { 18 type mcItem struct {
20 key string 19 key string
21 value []byte 20 value []byte
22 object interface{} 21 object interface{}
23 flags uint32 22 flags uint32
24 expiration time.Duration 23 expiration time.Duration
25 24
26 CasID uint64 25 CasID uint64
27 } 26 }
28 27
29 var _ gae.MCItem = (*mcItem)(nil) 28 var _ mc.Item = (*mcItem)(nil)
30 29
31 func (m *mcItem) Key() string { return m.key } 30 func (m *mcItem) Key() string { return m.key }
32 func (m *mcItem) Value() []byte { return m.value } 31 func (m *mcItem) Value() []byte { return m.value }
33 func (m *mcItem) Object() interface{} { return m.object } 32 func (m *mcItem) Object() interface{} { return m.object }
34 func (m *mcItem) Flags() uint32 { return m.flags } 33 func (m *mcItem) Flags() uint32 { return m.flags }
35 func (m *mcItem) Expiration() time.Duration { return m.expiration } 34 func (m *mcItem) Expiration() time.Duration { return m.expiration }
36 35
37 func (m *mcItem) SetKey(key string) gae.MCItem { 36 func (m *mcItem) SetKey(key string) mc.Item {
38 m.key = key 37 m.key = key
39 return m 38 return m
40 } 39 }
41 func (m *mcItem) SetValue(val []byte) gae.MCItem { 40 func (m *mcItem) SetValue(val []byte) mc.Item {
42 m.value = val 41 m.value = val
43 return m 42 return m
44 } 43 }
45 func (m *mcItem) SetObject(obj interface{}) gae.MCItem { 44 func (m *mcItem) SetObject(obj interface{}) mc.Item {
46 m.object = obj 45 m.object = obj
47 return m 46 return m
48 } 47 }
49 func (m *mcItem) SetFlags(flg uint32) gae.MCItem { 48 func (m *mcItem) SetFlags(flg uint32) mc.Item {
50 m.flags = flg 49 m.flags = flg
51 return m 50 return m
52 } 51 }
53 func (m *mcItem) SetExpiration(exp time.Duration) gae.MCItem { 52 func (m *mcItem) SetExpiration(exp time.Duration) mc.Item {
54 m.expiration = exp 53 m.expiration = exp
55 return m 54 return m
56 } 55 }
57 56
58 func (m *mcItem) duplicate() *mcItem { 57 func (m *mcItem) duplicate() *mcItem {
59 ret := mcItem{} 58 ret := mcItem{}
60 ret = *m 59 ret = *m
61 ret.value = make([]byte, len(m.value)) 60 ret.value = make([]byte, len(m.value))
62 copy(ret.value, m.value) 61 copy(ret.value, m.value)
63 return &ret 62 return &ret
64 } 63 }
65 64
66 type memcacheData struct { 65 type memcacheData struct {
67 lock sync.Mutex 66 lock sync.Mutex
68 items map[string]*mcItem 67 items map[string]*mcItem
69 casID uint64 68 casID uint64
70 } 69 }
71 70
72 // memcacheImpl binds the current connection's memcache data to an 71 // memcacheImpl binds the current connection's memcache data to an
73 // implementation of {gae.Memcache, gae.Testable}. 72 // implementation of {gae.Memcache, gae.Testable}.
74 type memcacheImpl struct { 73 type memcacheImpl struct {
75 » gae.Memcache 74 » mc.Interface
76 75
77 data *memcacheData 76 data *memcacheData
78 ctx context.Context 77 ctx context.Context
79 } 78 }
80 79
81 var _ gae.Memcache = (*memcacheImpl)(nil) 80 var _ mc.Interface = (*memcacheImpl)(nil)
82 81
83 // useMC adds a gae.Memcache implementation to context, accessible 82 // useMC adds a gae.Memcache implementation to context, accessible
84 // by gae.GetMC(c) 83 // by gae.GetMC(c)
85 func useMC(c context.Context) context.Context { 84 func useMC(c context.Context) context.Context {
86 lck := sync.Mutex{} 85 lck := sync.Mutex{}
87 mcdMap := map[string]*memcacheData{} 86 mcdMap := map[string]*memcacheData{}
88 87
89 » return gae.SetMCFactory(c, func(ic context.Context) gae.Memcache { 88 » return mc.SetFactory(c, func(ic context.Context) mc.Interface {
90 lck.Lock() 89 lck.Lock()
91 defer lck.Unlock() 90 defer lck.Unlock()
92 91
93 ns := curGID(ic).namespace 92 ns := curGID(ic).namespace
94 mcd, ok := mcdMap[ns] 93 mcd, ok := mcdMap[ns]
95 if !ok { 94 if !ok {
96 mcd = &memcacheData{items: map[string]*mcItem{}} 95 mcd = &memcacheData{items: map[string]*mcItem{}}
97 mcdMap[ns] = mcd 96 mcdMap[ns] = mcd
98 } 97 }
99 98
100 return &memcacheImpl{ 99 return &memcacheImpl{
101 » » » dummy.MC(), 100 » » » dummy.Memcache(),
102 mcd, 101 mcd,
103 ic, 102 ic,
104 } 103 }
105 }) 104 })
106 } 105 }
107 106
108 func (m *memcacheImpl) mkItemLocked(i gae.MCItem) (ret *mcItem) { 107 func (m *memcacheImpl) mkItemLocked(i mc.Item) (ret *mcItem) {
109 m.data.casID++ 108 m.data.casID++
110 109
111 var exp time.Duration 110 var exp time.Duration
112 if i.Expiration() != 0 { 111 if i.Expiration() != 0 {
113 exp = time.Duration(clock.Now(m.ctx).Add(i.Expiration()).UnixNan o()) 112 exp = time.Duration(clock.Now(m.ctx).Add(i.Expiration()).UnixNan o())
114 } 113 }
115 newItem := mcItem{ 114 newItem := mcItem{
116 key: i.Key(), 115 key: i.Key(),
117 flags: i.Flags(), 116 flags: i.Flags(),
118 expiration: exp, 117 expiration: exp,
119 value: i.Value(), 118 value: i.Value(),
120 CasID: m.data.casID, 119 CasID: m.data.casID,
121 } 120 }
122 return newItem.duplicate() 121 return newItem.duplicate()
123 } 122 }
124 123
125 func (m *memcacheImpl) NewItem(key string) gae.MCItem { 124 func (m *memcacheImpl) NewItem(key string) mc.Item {
126 return &mcItem{key: key} 125 return &mcItem{key: key}
127 } 126 }
128 127
129 // Add implements context.MCSingleReadWriter.Add. 128 // Add implements context.MCSingleReadWriter.Add.
130 func (m *memcacheImpl) Add(i gae.MCItem) error { 129 func (m *memcacheImpl) Add(i mc.Item) error {
131 m.data.lock.Lock() 130 m.data.lock.Lock()
132 defer m.data.lock.Unlock() 131 defer m.data.lock.Unlock()
133 132
134 if _, ok := m.retrieveLocked(i.Key()); !ok { 133 if _, ok := m.retrieveLocked(i.Key()); !ok {
135 m.data.items[i.Key()] = m.mkItemLocked(i) 134 m.data.items[i.Key()] = m.mkItemLocked(i)
136 return nil 135 return nil
137 } 136 }
138 » return gae.ErrMCNotStored 137 » return mc.ErrNotStored
139 } 138 }
140 139
141 // CompareAndSwap implements context.MCSingleReadWriter.CompareAndSwap. 140 // CompareAndSwap implements context.MCSingleReadWriter.CompareAndSwap.
142 func (m *memcacheImpl) CompareAndSwap(item gae.MCItem) error { 141 func (m *memcacheImpl) CompareAndSwap(item mc.Item) error {
143 m.data.lock.Lock() 142 m.data.lock.Lock()
144 defer m.data.lock.Unlock() 143 defer m.data.lock.Unlock()
145 144
146 if cur, ok := m.retrieveLocked(item.Key()); ok { 145 if cur, ok := m.retrieveLocked(item.Key()); ok {
147 casid := uint64(0) 146 casid := uint64(0)
148 if mi, ok := item.(*mcItem); ok && mi != nil { 147 if mi, ok := item.(*mcItem); ok && mi != nil {
149 casid = mi.CasID 148 casid = mi.CasID
150 } 149 }
151 150
152 if cur.CasID == casid { 151 if cur.CasID == casid {
153 m.data.items[item.Key()] = m.mkItemLocked(item) 152 m.data.items[item.Key()] = m.mkItemLocked(item)
154 } else { 153 } else {
155 » » » return gae.ErrMCCASConflict 154 » » » return mc.ErrCASConflict
156 } 155 }
157 } else { 156 } else {
158 » » return gae.ErrMCNotStored 157 » » return mc.ErrNotStored
159 } 158 }
160 return nil 159 return nil
161 } 160 }
162 161
163 // Set implements context.MCSingleReadWriter.Set. 162 // Set implements context.MCSingleReadWriter.Set.
164 func (m *memcacheImpl) Set(i gae.MCItem) error { 163 func (m *memcacheImpl) Set(i mc.Item) error {
165 m.data.lock.Lock() 164 m.data.lock.Lock()
166 defer m.data.lock.Unlock() 165 defer m.data.lock.Unlock()
167 m.data.items[i.Key()] = m.mkItemLocked(i) 166 m.data.items[i.Key()] = m.mkItemLocked(i)
168 return nil 167 return nil
169 } 168 }
170 169
171 // Get implements context.MCSingleReadWriter.Get. 170 // Get implements context.MCSingleReadWriter.Get.
172 func (m *memcacheImpl) Get(key string) (itm gae.MCItem, err error) { 171 func (m *memcacheImpl) Get(key string) (itm mc.Item, err error) {
173 m.data.lock.Lock() 172 m.data.lock.Lock()
174 defer m.data.lock.Unlock() 173 defer m.data.lock.Unlock()
175 if val, ok := m.retrieveLocked(key); ok { 174 if val, ok := m.retrieveLocked(key); ok {
176 itm = val.duplicate().SetExpiration(0) 175 itm = val.duplicate().SetExpiration(0)
177 } else { 176 } else {
178 » » err = gae.ErrMCCacheMiss 177 » » err = mc.ErrCacheMiss
179 } 178 }
180 return 179 return
181 } 180 }
182 181
183 // Delete implements context.MCSingleReadWriter.Delete. 182 // Delete implements context.MCSingleReadWriter.Delete.
184 func (m *memcacheImpl) Delete(key string) error { 183 func (m *memcacheImpl) Delete(key string) error {
185 m.data.lock.Lock() 184 m.data.lock.Lock()
186 defer m.data.lock.Unlock() 185 defer m.data.lock.Unlock()
187 186
188 if _, ok := m.retrieveLocked(key); ok { 187 if _, ok := m.retrieveLocked(key); ok {
189 delete(m.data.items, key) 188 delete(m.data.items, key)
190 return nil 189 return nil
191 } 190 }
192 » return gae.ErrMCCacheMiss 191 » return mc.ErrCacheMiss
193 } 192 }
194 193
195 func (m *memcacheImpl) retrieveLocked(key string) (*mcItem, bool) { 194 func (m *memcacheImpl) retrieveLocked(key string) (*mcItem, bool) {
196 ret, ok := m.data.items[key] 195 ret, ok := m.data.items[key]
197 if ok && ret.Expiration() != 0 && ret.Expiration() < time.Duration(clock .Now(m.ctx).UnixNano()) { 196 if ok && ret.Expiration() != 0 && ret.Expiration() < time.Duration(clock .Now(m.ctx).UnixNano()) {
198 ret = nil 197 ret = nil
199 ok = false 198 ok = false
200 delete(m.data.items, key) 199 delete(m.data.items, key)
201 } 200 }
202 return ret, ok 201 return ret, ok
203 } 202 }
OLDNEW
« no previous file with comments | « impl/memory/globalinfo.go ('k') | impl/memory/memcache_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698