github.com/m3db/m3@v1.5.0/src/cluster/kv/util/lock.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package util 22 23 import ( 24 "sync" 25 "time" 26 27 "github.com/m3db/m3/src/cluster/kv" 28 ) 29 30 func lockedUpdate(fn updateFn, lock sync.Locker) updateFn { 31 return func(i interface{}) { 32 if lock != nil { 33 lock.Lock() 34 } 35 36 fn(i) 37 38 if lock != nil { 39 lock.Unlock() 40 } 41 } 42 } 43 44 // WatchAndUpdateBool sets up a watch with validation for a bool property. Any 45 // malformed or invalid updates are not applied. The default value is applied 46 // when the key does not exist in KV. The watch on the value is returned. 47 func WatchAndUpdateBool( 48 store kv.Store, 49 key string, 50 property *bool, 51 lock sync.Locker, 52 defaultValue bool, 53 opts Options, 54 ) (kv.ValueWatch, error) { 55 if opts == nil { 56 opts = NewOptions() 57 } 58 updateFn := lockedUpdate(func(i interface{}) { *property = i.(bool) }, lock) 59 60 return watchAndUpdate( 61 store, key, getBool, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 62 ) 63 } 64 65 // WatchAndUpdateFloat64 sets up a watch with validation for a float64 property. 66 // Any malformed or invalid updates are not applied. The default value is applied 67 // when the key does not exist in KV. The watch on the value is returned. 68 func WatchAndUpdateFloat64( 69 store kv.Store, 70 key string, 71 property *float64, 72 lock sync.Locker, 73 defaultValue float64, 74 opts Options, 75 ) (kv.ValueWatch, error) { 76 if opts == nil { 77 opts = NewOptions() 78 } 79 updateFn := lockedUpdate(func(i interface{}) { *property = i.(float64) }, lock) 80 81 return watchAndUpdate( 82 store, key, getFloat64, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 83 ) 84 } 85 86 // WatchAndUpdateInt64 sets up a watch with validation for an int64 property. Any 87 // malformed or invalid updates are not applied. The default value is applied when 88 // the key does not exist in KV. The watch on the value is returned. 89 func WatchAndUpdateInt64( 90 store kv.Store, 91 key string, 92 property *int64, 93 lock sync.Locker, 94 defaultValue int64, 95 opts Options, 96 ) (kv.ValueWatch, error) { 97 if opts == nil { 98 opts = NewOptions() 99 } 100 updateFn := lockedUpdate(func(i interface{}) { *property = i.(int64) }, lock) 101 102 return watchAndUpdate( 103 store, key, getInt64, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 104 ) 105 } 106 107 // WatchAndUpdateString sets up a watch with validation for a string property. Any 108 // malformed or invalid updates are not applied. The default value is applied when 109 // the key does not exist in KV. The watch on the value is returned. 110 func WatchAndUpdateString( 111 store kv.Store, 112 key string, 113 property *string, 114 lock sync.Locker, 115 defaultValue string, 116 opts Options, 117 ) (kv.ValueWatch, error) { 118 if opts == nil { 119 opts = NewOptions() 120 } 121 updateFn := lockedUpdate(func(i interface{}) { *property = i.(string) }, lock) 122 123 return watchAndUpdate( 124 store, key, getString, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 125 ) 126 } 127 128 // WatchAndUpdateStringArray sets up a watch with validation for a string array 129 // property. Any malformed, or invalid updates are not applied. The default value 130 // is applied when the key does not exist in KV. The watch on the value is returned. 131 func WatchAndUpdateStringArray( 132 store kv.Store, 133 key string, 134 property *[]string, 135 lock sync.Locker, 136 defaultValue []string, 137 opts Options, 138 ) (kv.ValueWatch, error) { 139 if opts == nil { 140 opts = NewOptions() 141 } 142 updateFn := lockedUpdate(func(i interface{}) { *property = i.([]string) }, lock) 143 144 return watchAndUpdate( 145 store, key, getStringArray, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 146 ) 147 } 148 149 // WatchAndUpdateStringArrayPointer sets up a watch with validation for a string array pointer 150 // property. Any malformed, or invalid updates are not applied. The default value 151 // is applied when the key does not exist in KV. The watch on the value is returned. 152 func WatchAndUpdateStringArrayPointer( 153 store kv.Store, 154 key string, 155 property **[]string, 156 lock sync.Locker, 157 defaultValue *[]string, 158 opts Options, 159 ) (kv.ValueWatch, error) { 160 if opts == nil { 161 opts = NewOptions() 162 } 163 updateFn := lockedUpdate(func(i interface{}) { *property = i.(*[]string) }, lock) 164 165 return watchAndUpdate( 166 store, key, getStringArrayPointer, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 167 ) 168 } 169 170 // WatchAndUpdateTime sets up a watch with validation for a time property. Any 171 // malformed, or invalid updates are not applied. The default value is applied 172 // when the key does not exist in KV. The watch on the value is returned. 173 func WatchAndUpdateTime( 174 store kv.Store, 175 key string, 176 property *time.Time, 177 lock sync.Locker, 178 defaultValue time.Time, 179 opts Options, 180 ) (kv.ValueWatch, error) { 181 if opts == nil { 182 opts = NewOptions() 183 } 184 updateFn := lockedUpdate(func(i interface{}) { *property = i.(time.Time) }, lock) 185 186 return watchAndUpdate( 187 store, key, getTime, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 188 ) 189 } 190 191 // WatchAndUpdateDuration sets up a watch with validation for a time property. Any 192 // malformed, or invalid updates are not applied. The default value is applied 193 // when the key does not exist in KV. The watch on the value is returned. 194 func WatchAndUpdateDuration( 195 store kv.Store, 196 key string, 197 property *time.Duration, 198 lock sync.Locker, 199 defaultValue time.Duration, 200 opts Options, 201 ) (kv.ValueWatch, error) { 202 if opts == nil { 203 opts = NewOptions() 204 } 205 updateFn := lockedUpdate(func(i interface{}) { *property = i.(time.Duration) }, lock) 206 207 return watchAndUpdate( 208 store, key, getDuration, updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 209 ) 210 } 211 212 // WatchAndUpdateGeneric sets up a watch with validation for a generic property. 213 // Any malformed, or invalid updates are not applied. The default value is 214 // applied when the key does not exist in KV. The watch on the value is returned. 215 func WatchAndUpdateGeneric( 216 store kv.Store, 217 key string, 218 genericGetFn GenericGetValueFn, 219 genericUpdateFn GenericUpdateFn, 220 lock sync.Locker, 221 defaultValue interface{}, 222 opts Options, 223 ) (kv.ValueWatch, error) { 224 if opts == nil { 225 opts = NewOptions() 226 } 227 228 updateFn := lockedUpdate(updateFn(genericUpdateFn), lock) 229 return watchAndUpdate( 230 store, key, getValueFn(genericGetFn), updateFn, opts.ValidateFn(), defaultValue, opts.Logger(), 231 ) 232 }