| 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 |