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  }