github.com/google/cloudprober@v0.11.3/metrics/int.go (about)

     1  // Copyright 2017 The Cloudprober Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package metrics
    16  
    17  import (
    18  	"errors"
    19  	"strconv"
    20  	"sync/atomic"
    21  )
    22  
    23  // Int implements NumValue with int64 storage. Note that Int is not concurrency
    24  // safe, if you want a concurrency safe integer NumValue, use AtomicInt.
    25  type Int struct {
    26  	i int64
    27  	// If Str is defined, this is method used to convert Int into a string.
    28  	Str func(int64) string
    29  }
    30  
    31  // NewInt returns a new Int
    32  func NewInt(i int64) *Int {
    33  	return &Int{i: i}
    34  }
    35  
    36  // Clone returns a copy the receiver Int
    37  func (i *Int) Clone() Value {
    38  	return &Int{
    39  		i:   i.i,
    40  		Str: i.Str,
    41  	}
    42  }
    43  
    44  // Int64 returns the stored int64
    45  func (i *Int) Int64() int64 {
    46  	return i.i
    47  }
    48  
    49  // Float64 returns the stored int64 as a float64
    50  func (i *Int) Float64() float64 {
    51  	return float64(i.i)
    52  }
    53  
    54  // Inc increments the receiver Int by one.
    55  // It's part of the NumValue interface.
    56  func (i *Int) Inc() {
    57  	i.i++
    58  }
    59  
    60  // IncBy increments the receiver Int by "delta" NumValue.
    61  // It's part of the NumValue interface.
    62  func (i *Int) IncBy(delta NumValue) {
    63  	i.i += delta.Int64()
    64  }
    65  
    66  // Add adds a Value to the receiver Int. If Value is not Int, an error is returned.
    67  // It's part of the Value interface.
    68  func (i *Int) Add(val Value) error {
    69  	delta, ok := val.(*Int)
    70  	if !ok {
    71  		return errors.New("incompatible value to add")
    72  	}
    73  	i.i += delta.i
    74  	return nil
    75  }
    76  
    77  // SubtractCounter subtracts the provided "lastVal", assuming that value
    78  // represents a counter, i.e. if "value" is less than "lastVal", we assume that
    79  // counter has been reset and don't subtract.
    80  func (i *Int) SubtractCounter(lastVal Value) (bool, error) {
    81  	lv, ok := lastVal.(*Int)
    82  	if !ok {
    83  		return false, errors.New("incompatible value to subtract")
    84  	}
    85  
    86  	if i.i < lv.i {
    87  		return true, nil
    88  	}
    89  
    90  	i.i -= lv.i
    91  	return false, nil
    92  }
    93  
    94  // AddInt64 adds an int64 to the receiver Int.
    95  func (i *Int) AddInt64(ii int64) {
    96  	i.i += ii
    97  }
    98  
    99  // AddFloat64 adds a float64 to the receiver Int.
   100  func (i *Int) AddFloat64(f float64) {
   101  	i.i += int64(f)
   102  }
   103  
   104  // String returns the string representation of Int.
   105  // It's part of the Value interface.
   106  func (i *Int) String() string {
   107  	if i.Str != nil {
   108  		return i.Str(i.Int64())
   109  	}
   110  	return strconv.FormatInt(i.Int64(), 10)
   111  }
   112  
   113  // AtomicInt implements NumValue with int64 storage and atomic operations. If
   114  // concurrency-safety is not a requirement, e.g. for use in already mutex
   115  // protected map, you could use Int.
   116  type AtomicInt struct {
   117  	i int64
   118  	// If Str is defined, this is method used to convert AtomicInt into a string.
   119  	Str func(int64) string
   120  }
   121  
   122  // NewAtomicInt returns a new AtomicInt
   123  func NewAtomicInt(i int64) *AtomicInt {
   124  	return &AtomicInt{i: i}
   125  }
   126  
   127  // Clone returns a copy the receiver AtomicInt
   128  func (i *AtomicInt) Clone() Value {
   129  	return &AtomicInt{
   130  		i:   i.Int64(),
   131  		Str: i.Str,
   132  	}
   133  }
   134  
   135  // Int64 returns the stored int64
   136  func (i *AtomicInt) Int64() int64 {
   137  	return atomic.LoadInt64(&i.i)
   138  }
   139  
   140  // Float64 returns the stored int64 as a float64
   141  func (i *AtomicInt) Float64() float64 {
   142  	return float64(atomic.LoadInt64(&i.i))
   143  }
   144  
   145  // Inc increments the receiver AtomicInt by one.
   146  // It's part of the NumValue interface.
   147  func (i *AtomicInt) Inc() {
   148  	atomic.AddInt64(&i.i, 1)
   149  }
   150  
   151  // IncBy increments the receiver AtomicInt by "delta" NumValue.
   152  // It's part of the NumValue interface.
   153  func (i *AtomicInt) IncBy(delta NumValue) {
   154  	atomic.AddInt64(&i.i, delta.Int64())
   155  }
   156  
   157  // Add adds a Value to the receiver AtomicInt. If Value is not AtomicInt, an error is returned.
   158  // It's part of the Value interface.
   159  func (i *AtomicInt) Add(val Value) error {
   160  	delta, ok := val.(NumValue)
   161  	if !ok {
   162  		return errors.New("incompatible value to add")
   163  	}
   164  	atomic.AddInt64(&i.i, delta.Int64())
   165  	return nil
   166  }
   167  
   168  // SubtractCounter subtracts the provided "lastVal". Note that this function
   169  // is not fully atomic: we first load the values, compare them, and then update
   170  // the receiver if required. There is a possibility that either receiver, or
   171  // lastVal may change between loading of the values and updating them. We
   172  // should still not get negative values though, as we use the snapshots to
   173  // finally update the value.
   174  func (i *AtomicInt) SubtractCounter(lastVal Value) (bool, error) {
   175  	lv, ok := lastVal.(NumValue)
   176  	if !ok {
   177  		return false, errors.New("incompatible value to subtract")
   178  	}
   179  
   180  	valS := i.Int64()
   181  	lvS := lv.Int64()
   182  
   183  	if valS < lvS {
   184  		return true, nil
   185  	}
   186  	atomic.StoreInt64(&i.i, valS-lvS)
   187  	return false, nil
   188  }
   189  
   190  // AddInt64 adds an int64 to the receiver Int.
   191  func (i *AtomicInt) AddInt64(ii int64) {
   192  	atomic.AddInt64(&i.i, ii)
   193  }
   194  
   195  // AddFloat64 adds a float64 to the receiver Int.
   196  func (i *AtomicInt) AddFloat64(f float64) {
   197  	atomic.AddInt64(&i.i, int64(f))
   198  }
   199  
   200  // String returns the string representation of AtomicInt.
   201  // It's part of the Value interface.
   202  func (i *AtomicInt) String() string {
   203  	if i.Str != nil {
   204  		return i.Str(i.Int64())
   205  	}
   206  	return strconv.FormatInt(i.Int64(), 10)
   207  }