OLD | NEW |
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 prod | 5 package prod |
6 | 6 |
7 import ( | 7 import ( |
8 "time" | 8 "time" |
9 | 9 |
10 mc "github.com/luci/gae/service/memcache" | 10 mc "github.com/luci/gae/service/memcache" |
11 "github.com/luci/luci-go/common/errors" | |
12 "golang.org/x/net/context" | 11 "golang.org/x/net/context" |
| 12 "google.golang.org/appengine" |
13 "google.golang.org/appengine/memcache" | 13 "google.golang.org/appengine/memcache" |
14 ) | 14 ) |
15 | 15 |
16 // useMC adds a gae.Memcache implementation to context, accessible | 16 // useMC adds a gae.Memcache implementation to context, accessible |
17 // by gae.GetMC(c) | 17 // by gae.GetMC(c) |
18 func useMC(c context.Context) context.Context { | 18 func useMC(c context.Context) context.Context { |
19 » return mc.SetFactory(c, func(ci context.Context) mc.Interface { | 19 » return mc.SetRawFactory(c, func(ci context.Context) mc.RawInterface { |
20 return mcImpl{ci} | 20 return mcImpl{ci} |
21 }) | 21 }) |
22 } | 22 } |
23 | 23 |
24 type mcImpl struct{ context.Context } | 24 type mcImpl struct{ context.Context } |
25 | 25 |
26 type mcItem struct { | 26 type mcItem struct { |
27 i *memcache.Item | 27 i *memcache.Item |
28 } | 28 } |
29 | 29 |
30 var _ mc.Item = mcItem{} | 30 var _ mc.Item = mcItem{} |
31 | 31 |
32 func (i mcItem) Key() string { return i.i.Key } | 32 func (i mcItem) Key() string { return i.i.Key } |
33 func (i mcItem) Value() []byte { return i.i.Value } | 33 func (i mcItem) Value() []byte { return i.i.Value } |
34 func (i mcItem) Object() interface{} { return i.i.Object } | |
35 func (i mcItem) Flags() uint32 { return i.i.Flags } | 34 func (i mcItem) Flags() uint32 { return i.i.Flags } |
36 func (i mcItem) Expiration() time.Duration { return i.i.Expiration } | 35 func (i mcItem) Expiration() time.Duration { return i.i.Expiration } |
37 | 36 |
38 func (i mcItem) SetKey(k string) mc.Item { | 37 func (i mcItem) SetKey(k string) mc.Item { |
39 i.i.Key = k | 38 i.i.Key = k |
40 return i | 39 return i |
41 } | 40 } |
42 func (i mcItem) SetValue(v []byte) mc.Item { | 41 func (i mcItem) SetValue(v []byte) mc.Item { |
43 i.i.Value = v | 42 i.i.Value = v |
44 return i | 43 return i |
45 } | 44 } |
46 func (i mcItem) SetObject(o interface{}) mc.Item { | |
47 i.i.Object = o | |
48 return i | |
49 } | |
50 func (i mcItem) SetFlags(f uint32) mc.Item { | 45 func (i mcItem) SetFlags(f uint32) mc.Item { |
51 i.i.Flags = f | 46 i.i.Flags = f |
52 return i | 47 return i |
53 } | 48 } |
54 func (i mcItem) SetExpiration(d time.Duration) mc.Item { | 49 func (i mcItem) SetExpiration(d time.Duration) mc.Item { |
55 i.i.Expiration = d | 50 i.i.Expiration = d |
56 return i | 51 return i |
57 } | 52 } |
58 | 53 |
| 54 func (i mcItem) SetAll(other mc.Item) { |
| 55 o := other.(mcItem) |
| 56 *i.i = *o.i |
| 57 val := i.i.Value |
| 58 i.i.Value = make([]byte, len(val)) |
| 59 copy(i.i.Value, val) |
| 60 } |
| 61 |
59 // mcR2FErr (MC real-to-fake w/ error) converts a *memcache.Item to a mc.Item, | 62 // mcR2FErr (MC real-to-fake w/ error) converts a *memcache.Item to a mc.Item, |
60 // and passes along an error. | 63 // and passes along an error. |
61 func mcR2FErr(i *memcache.Item, err error) (mc.Item, error) { | 64 func mcR2FErr(i *memcache.Item, err error) (mc.Item, error) { |
62 if err != nil { | 65 if err != nil { |
63 return nil, err | 66 return nil, err |
64 } | 67 } |
65 return mcItem{i}, nil | 68 return mcItem{i}, nil |
66 } | 69 } |
67 | 70 |
68 // mcF2R (MC fake-to-real) converts a mc.Item. i must originate from inside | 71 // mcF2R (MC fake-to-real) converts a mc.Item. i must originate from inside |
(...skipping 15 matching lines...) Expand all Loading... |
84 for i, itm := range items { | 87 for i, itm := range items { |
85 realItems[i] = mcF2R(itm) | 88 realItems[i] = mcF2R(itm) |
86 } | 89 } |
87 return realItems | 90 return realItems |
88 } | 91 } |
89 | 92 |
90 func (m mcImpl) NewItem(key string) mc.Item { | 93 func (m mcImpl) NewItem(key string) mc.Item { |
91 return mcItem{&memcache.Item{Key: key}} | 94 return mcItem{&memcache.Item{Key: key}} |
92 } | 95 } |
93 | 96 |
94 //////// MCSingleReadWriter | 97 func doCB(err error, cb mc.RawCB) error { |
95 func (m mcImpl) Add(item mc.Item) error { | 98 » if me, ok := err.(appengine.MultiError); ok { |
96 » return memcache.Add(m.Context, mcF2R(item)) | 99 » » for _, err := range me { |
97 } | 100 » » » cb(err) |
98 func (m mcImpl) Set(item mc.Item) error { | 101 » » } |
99 » return memcache.Set(m.Context, mcF2R(item)) | 102 » » err = nil |
100 } | 103 » } |
101 func (m mcImpl) Delete(key string) error { | 104 » return err |
102 » return memcache.Delete(m.Context, key) | |
103 } | |
104 func (m mcImpl) Get(key string) (mc.Item, error) { | |
105 » return mcR2FErr(memcache.Get(m.Context, key)) | |
106 } | |
107 func (m mcImpl) CompareAndSwap(item mc.Item) error { | |
108 » return memcache.CompareAndSwap(m.Context, mcF2R(item)) | |
109 } | 105 } |
110 | 106 |
111 //////// MCMultiReadWriter | 107 func (m mcImpl) DeleteMulti(keys []string, cb mc.RawCB) error { |
112 func (m mcImpl) DeleteMulti(keys []string) error { | 108 » return doCB(memcache.DeleteMulti(m.Context, keys), cb) |
113 » return errors.Fix(memcache.DeleteMulti(m.Context, keys)) | |
114 } | 109 } |
115 func (m mcImpl) AddMulti(items []mc.Item) error { | 110 |
116 » return errors.Fix(memcache.AddMulti(m.Context, mcMF2R(items))) | 111 func (m mcImpl) AddMulti(items []mc.Item, cb mc.RawCB) error { |
| 112 » return doCB(memcache.AddMulti(m.Context, mcMF2R(items)), cb) |
117 } | 113 } |
118 func (m mcImpl) SetMulti(items []mc.Item) error { | 114 |
119 » return errors.Fix(memcache.SetMulti(m.Context, mcMF2R(items))) | 115 func (m mcImpl) SetMulti(items []mc.Item, cb mc.RawCB) error { |
| 116 » return doCB(memcache.SetMulti(m.Context, mcMF2R(items)), cb) |
120 } | 117 } |
121 func (m mcImpl) GetMulti(keys []string) (map[string]mc.Item, error) { | 118 |
| 119 func (m mcImpl) GetMulti(keys []string, cb mc.RawItemCB) error { |
122 realItems, err := memcache.GetMulti(m.Context, keys) | 120 realItems, err := memcache.GetMulti(m.Context, keys) |
123 if err != nil { | 121 if err != nil { |
124 » » return nil, errors.Fix(err) | 122 » » return err |
125 } | 123 } |
126 » items := make(map[string]mc.Item, len(realItems)) | 124 » for _, k := range keys { |
127 » for k, itm := range realItems { | 125 » » itm := realItems[k] |
128 » » items[k] = mcItem{itm} | 126 » » if itm == nil { |
| 127 » » » cb(nil, memcache.ErrCacheMiss) |
| 128 » » } else { |
| 129 » » » cb(mcItem{itm}, nil) |
| 130 » » } |
129 } | 131 } |
130 » return items, err | 132 » return nil |
131 } | |
132 func (m mcImpl) CompareAndSwapMulti(items []mc.Item) error { | |
133 » return errors.Fix(memcache.CompareAndSwapMulti(m.Context, mcMF2R(items))
) | |
134 } | 133 } |
135 | 134 |
136 //////// MCIncrementer | 135 func (m mcImpl) CompareAndSwapMulti(items []mc.Item, cb mc.RawCB) error { |
137 func (m mcImpl) Increment(key string, delta int64, initialValue uint64) (uint64,
error) { | 136 » return doCB(memcache.CompareAndSwapMulti(m.Context, mcMF2R(items)), cb) |
138 » return memcache.Increment(m.Context, key, delta, initialValue) | |
139 } | |
140 func (m mcImpl) IncrementExisting(key string, delta int64) (uint64, error) { | |
141 » return memcache.IncrementExisting(m.Context, key, delta) | |
142 } | 137 } |
143 | 138 |
144 //////// MCFlusher | 139 func (m mcImpl) Increment(key string, delta int64, initialValue *uint64) (uint64
, error) { |
| 140 » if initialValue == nil { |
| 141 » » return memcache.IncrementExisting(m.Context, key, delta) |
| 142 » } else { |
| 143 » » return memcache.Increment(m.Context, key, delta, *initialValue) |
| 144 » } |
| 145 } |
| 146 |
145 func (m mcImpl) Flush() error { | 147 func (m mcImpl) Flush() error { |
146 return memcache.Flush(m.Context) | 148 return memcache.Flush(m.Context) |
147 } | 149 } |
148 | 150 |
149 //////// MCStatter | |
150 func (m mcImpl) Stats() (*mc.Statistics, error) { | 151 func (m mcImpl) Stats() (*mc.Statistics, error) { |
151 stats, err := memcache.Stats(m.Context) | 152 stats, err := memcache.Stats(m.Context) |
152 if err != nil { | 153 if err != nil { |
153 return nil, err | 154 return nil, err |
154 } | 155 } |
155 return (*mc.Statistics)(stats), nil | 156 return (*mc.Statistics)(stats), nil |
156 } | 157 } |
OLD | NEW |