OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package dscache | 5 package dscache |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "math/rand" | 9 "math/rand" |
10 "time" | 10 "time" |
11 | 11 |
12 ds "github.com/luci/gae/service/datastore" | 12 ds "github.com/luci/gae/service/datastore" |
13 » "github.com/luci/gae/service/memcache" | 13 » mc "github.com/luci/gae/service/memcache" |
14 "github.com/luci/luci-go/common/errors" | 14 "github.com/luci/luci-go/common/errors" |
15 log "github.com/luci/luci-go/common/logging" | 15 log "github.com/luci/luci-go/common/logging" |
16 "golang.org/x/net/context" | 16 "golang.org/x/net/context" |
17 ) | 17 ) |
18 | 18 |
19 type supportContext struct { | 19 type supportContext struct { |
20 aid string | 20 aid string |
21 ns string | 21 ns string |
22 | 22 |
23 c context.Context | 23 c context.Context |
24 mc memcache.Interface | |
25 mr *rand.Rand | 24 mr *rand.Rand |
26 shardsForKey func(*ds.Key) int | 25 shardsForKey func(*ds.Key) int |
27 } | 26 } |
28 | 27 |
29 func (s *supportContext) numShards(k *ds.Key) int { | 28 func (s *supportContext) numShards(k *ds.Key) int { |
30 ret := DefaultShards | 29 ret := DefaultShards |
31 if s.shardsForKey != nil { | 30 if s.shardsForKey != nil { |
32 ret = s.shardsForKey(k) | 31 ret = s.shardsForKey(k) |
33 } | 32 } |
34 if ret < 1 { | 33 if ret < 1 { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 } | 101 } |
103 } | 102 } |
104 return ret | 103 return ret |
105 } | 104 } |
106 | 105 |
107 func (s *supportContext) mutation(keys []*ds.Key, f func() error) error { | 106 func (s *supportContext) mutation(keys []*ds.Key, f func() error) error { |
108 lockItems, lockKeys := s.mkAllLockItems(keys) | 107 lockItems, lockKeys := s.mkAllLockItems(keys) |
109 if lockItems == nil { | 108 if lockItems == nil { |
110 return f() | 109 return f() |
111 } | 110 } |
112 » if err := s.mc.SetMulti(lockItems); err != nil { | 111 » if err := mc.Set(s.c, lockItems...); err != nil { |
113 // this is a hard failure. No mutation can occur if we're unable
to set | 112 // this is a hard failure. No mutation can occur if we're unable
to set |
114 // locks out. See "DANGER ZONE" in the docs. | 113 // locks out. See "DANGER ZONE" in the docs. |
115 (log.Fields{log.ErrorKey: err}).Errorf( | 114 (log.Fields{log.ErrorKey: err}).Errorf( |
116 s.c, "dscache: HARD FAILURE: supportContext.mutation():
mc.SetMulti") | 115 s.c, "dscache: HARD FAILURE: supportContext.mutation():
mc.SetMulti") |
117 return err | 116 return err |
118 } | 117 } |
119 err := f() | 118 err := f() |
120 if err == nil { | 119 if err == nil { |
121 » » if err := errors.Filter(s.mc.DeleteMulti(lockKeys), memcache.Err
CacheMiss); err != nil { | 120 » » if err := errors.Filter(mc.Delete(s.c, lockKeys...), mc.ErrCache
Miss); err != nil { |
122 (log.Fields{log.ErrorKey: err}).Debugf( | 121 (log.Fields{log.ErrorKey: err}).Debugf( |
123 » » » » s.c, "dscache: mc.DeleteMulti") | 122 » » » » s.c, "dscache: mc.Delete") |
124 } | 123 } |
125 } | 124 } |
126 return err | 125 return err |
127 } | 126 } |
128 | 127 |
129 func (s *supportContext) mkRandLockItems(keys []*ds.Key, metas ds.MultiMetaGette
r) ([]memcache.Item, []byte) { | 128 func (s *supportContext) mkRandLockItems(keys []*ds.Key, metas ds.MultiMetaGette
r) ([]mc.Item, []byte) { |
130 mcKeys := s.mkRandKeys(keys, metas) | 129 mcKeys := s.mkRandKeys(keys, metas) |
131 if len(mcKeys) == 0 { | 130 if len(mcKeys) == 0 { |
132 return nil, nil | 131 return nil, nil |
133 } | 132 } |
134 nonce := s.crappyNonce() | 133 nonce := s.crappyNonce() |
135 » ret := make([]memcache.Item, len(mcKeys)) | 134 » ret := make([]mc.Item, len(mcKeys)) |
136 for i, k := range mcKeys { | 135 for i, k := range mcKeys { |
137 if k == "" { | 136 if k == "" { |
138 continue | 137 continue |
139 } | 138 } |
140 » » ret[i] = (s.mc.NewItem(k). | 139 » » ret[i] = (mc.NewItem(s.c, k). |
141 SetFlags(uint32(ItemHasLock)). | 140 SetFlags(uint32(ItemHasLock)). |
142 SetExpiration(time.Second * time.Duration(LockTimeSecond
s)). | 141 SetExpiration(time.Second * time.Duration(LockTimeSecond
s)). |
143 SetValue(nonce)) | 142 SetValue(nonce)) |
144 } | 143 } |
145 return ret, nonce | 144 return ret, nonce |
146 } | 145 } |
147 | 146 |
148 func (s *supportContext) mkAllLockItems(keys []*ds.Key) ([]memcache.Item, []stri
ng) { | 147 func (s *supportContext) mkAllLockItems(keys []*ds.Key) ([]mc.Item, []string) { |
149 mcKeys := s.mkAllKeys(keys) | 148 mcKeys := s.mkAllKeys(keys) |
150 if mcKeys == nil { | 149 if mcKeys == nil { |
151 return nil, nil | 150 return nil, nil |
152 } | 151 } |
153 » ret := make([]memcache.Item, len(mcKeys)) | 152 » ret := make([]mc.Item, len(mcKeys)) |
154 for i := range ret { | 153 for i := range ret { |
155 » » ret[i] = (s.mc.NewItem(mcKeys[i]). | 154 » » ret[i] = (mc.NewItem(s.c, mcKeys[i]). |
156 SetFlags(uint32(ItemHasLock)). | 155 SetFlags(uint32(ItemHasLock)). |
157 SetExpiration(time.Second * time.Duration(LockTimeSecond
s))) | 156 SetExpiration(time.Second * time.Duration(LockTimeSecond
s))) |
158 } | 157 } |
159 return ret, mcKeys | 158 return ret, mcKeys |
160 } | 159 } |
OLD | NEW |