| 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" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 if !key.IsIncomplete() { | 76 if !key.IsIncomplete() { |
| 77 keySuffix := HashKey(key) | 77 keySuffix := HashKey(key) |
| 78 for shard := 0; shard < nums[i]; shard++ { | 78 for shard := 0; shard < nums[i]; shard++ { |
| 79 ret = append(ret, fmt.Sprintf(KeyFormat, shard,
keySuffix)) | 79 ret = append(ret, fmt.Sprintf(KeyFormat, shard,
keySuffix)) |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 return ret | 83 return ret |
| 84 } | 84 } |
| 85 | 85 |
| 86 // crappyNonce creates a really crappy nonce using math/rand. This is generally | |
| 87 // unacceptable for cryptographic purposes, but since mathrand is the only | |
| 88 // mocked randomness source, we use that. | |
| 89 // | |
| 90 // The random values here are controlled entriely by the application, will never | |
| 91 // be shown to, or provided by, the user, so this should be fine. | |
| 92 // | |
| 93 // Do not use this function for anything other than mkRandLockItems or your hair | |
| 94 // will fall out. You've been warned. | |
| 95 func (s *supportContext) crappyNonce() []byte { | |
| 96 ret := make([]byte, NonceUint32s*4) | |
| 97 for w := uint(0); w < NonceUint32s; w++ { | |
| 98 word := s.mr.Uint32() | |
| 99 for i := uint(0); i < 4; i++ { | |
| 100 ret[(w*4)+i] = byte(word >> (8 * i)) | |
| 101 } | |
| 102 } | |
| 103 return ret | |
| 104 } | |
| 105 | |
| 106 func (s *supportContext) mutation(keys []*ds.Key, f func() error) error { | 86 func (s *supportContext) mutation(keys []*ds.Key, f func() error) error { |
| 107 lockItems, lockKeys := s.mkAllLockItems(keys) | 87 lockItems, lockKeys := s.mkAllLockItems(keys) |
| 108 if lockItems == nil { | 88 if lockItems == nil { |
| 109 return f() | 89 return f() |
| 110 } | 90 } |
| 111 if err := mc.Set(s.c, lockItems...); err != nil { | 91 if err := mc.Set(s.c, lockItems...); err != nil { |
| 112 // this is a hard failure. No mutation can occur if we're unable
to set | 92 // this is a hard failure. No mutation can occur if we're unable
to set |
| 113 // locks out. See "DANGER ZONE" in the docs. | 93 // locks out. See "DANGER ZONE" in the docs. |
| 114 (log.Fields{log.ErrorKey: err}).Errorf( | 94 (log.Fields{log.ErrorKey: err}).Errorf( |
| 115 s.c, "dscache: HARD FAILURE: supportContext.mutation():
mc.SetMulti") | 95 s.c, "dscache: HARD FAILURE: supportContext.mutation():
mc.SetMulti") |
| 116 return err | 96 return err |
| 117 } | 97 } |
| 118 err := f() | 98 err := f() |
| 119 if err == nil { | 99 if err == nil { |
| 120 if err := errors.Filter(mc.Delete(s.c, lockKeys...), mc.ErrCache
Miss); err != nil { | 100 if err := errors.Filter(mc.Delete(s.c, lockKeys...), mc.ErrCache
Miss); err != nil { |
| 121 (log.Fields{log.ErrorKey: err}).Debugf( | 101 (log.Fields{log.ErrorKey: err}).Debugf( |
| 122 s.c, "dscache: mc.Delete") | 102 s.c, "dscache: mc.Delete") |
| 123 } | 103 } |
| 124 } | 104 } |
| 125 return err | 105 return err |
| 126 } | 106 } |
| 127 | 107 |
| 128 func (s *supportContext) mkRandLockItems(keys []*ds.Key, metas ds.MultiMetaGette
r) ([]mc.Item, []byte) { | 108 func (s *supportContext) mkRandLockItems(keys []*ds.Key, metas ds.MultiMetaGette
r) ([]mc.Item, []byte) { |
| 129 mcKeys := s.mkRandKeys(keys, metas) | 109 mcKeys := s.mkRandKeys(keys, metas) |
| 130 if len(mcKeys) == 0 { | 110 if len(mcKeys) == 0 { |
| 131 return nil, nil | 111 return nil, nil |
| 132 } | 112 } |
| 133 » nonce := s.crappyNonce() | 113 » nonce := generateNonce() |
| 134 ret := make([]mc.Item, len(mcKeys)) | 114 ret := make([]mc.Item, len(mcKeys)) |
| 135 for i, k := range mcKeys { | 115 for i, k := range mcKeys { |
| 136 if k == "" { | 116 if k == "" { |
| 137 continue | 117 continue |
| 138 } | 118 } |
| 139 ret[i] = (mc.NewItem(s.c, k). | 119 ret[i] = (mc.NewItem(s.c, k). |
| 140 SetFlags(uint32(ItemHasLock)). | 120 SetFlags(uint32(ItemHasLock)). |
| 141 SetExpiration(time.Second * time.Duration(LockTimeSecond
s)). | 121 SetExpiration(time.Second * time.Duration(LockTimeSecond
s)). |
| 142 SetValue(nonce)) | 122 SetValue(nonce)) |
| 143 } | 123 } |
| 144 return ret, nonce | 124 return ret, nonce |
| 145 } | 125 } |
| 146 | 126 |
| 147 func (s *supportContext) mkAllLockItems(keys []*ds.Key) ([]mc.Item, []string) { | 127 func (s *supportContext) mkAllLockItems(keys []*ds.Key) ([]mc.Item, []string) { |
| 148 mcKeys := s.mkAllKeys(keys) | 128 mcKeys := s.mkAllKeys(keys) |
| 149 if mcKeys == nil { | 129 if mcKeys == nil { |
| 150 return nil, nil | 130 return nil, nil |
| 151 } | 131 } |
| 152 ret := make([]mc.Item, len(mcKeys)) | 132 ret := make([]mc.Item, len(mcKeys)) |
| 153 for i := range ret { | 133 for i := range ret { |
| 154 ret[i] = (mc.NewItem(s.c, mcKeys[i]). | 134 ret[i] = (mc.NewItem(s.c, mcKeys[i]). |
| 155 SetFlags(uint32(ItemHasLock)). | 135 SetFlags(uint32(ItemHasLock)). |
| 156 SetExpiration(time.Second * time.Duration(LockTimeSecond
s))) | 136 SetExpiration(time.Second * time.Duration(LockTimeSecond
s))) |
| 157 } | 137 } |
| 158 return ret, mcKeys | 138 return ret, mcKeys |
| 159 } | 139 } |
| 140 |
| 141 // generateNonce creates a pseudo-random sequence of bytes for use as a nonce |
| 142 // usingthe non-cryptographic PRNG in "math/rand". |
| 143 // |
| 144 // The random values here are controlled entriely by the application, will never |
| 145 // be shown to, or provided by, the user, so this should be fine. |
| 146 func generateNonce() []byte { |
| 147 nonce := make([]byte, NonceBytes) |
| 148 _, _ = rand.Read(nonce) // This Read will always return len(nonce), nil. |
| 149 return nonce |
| 150 } |
| OLD | NEW |