github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/gossip/util/misc.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package util
     8  
     9  import (
    10  	"fmt"
    11  	"math/rand"
    12  	"reflect"
    13  	"runtime"
    14  	"sync"
    15  	"time"
    16  
    17  	"github.com/spf13/viper"
    18  )
    19  
    20  func init() { // do we really need this?
    21  	rand.Seed(time.Now().UnixNano())
    22  }
    23  
    24  // Equals returns whether a and b are the same
    25  type Equals func(a interface{}, b interface{}) bool
    26  
    27  var viperLock sync.RWMutex
    28  
    29  // Contains returns whether a given slice a contains a string s
    30  func Contains(s string, a []string) bool {
    31  	for _, e := range a {
    32  		if e == s {
    33  			return true
    34  		}
    35  	}
    36  	return false
    37  }
    38  
    39  // IndexInSlice returns the index of given object o in array, and -1 if it is not in array.
    40  func IndexInSlice(array interface{}, o interface{}, equals Equals) int {
    41  	arr := reflect.ValueOf(array)
    42  	for i := 0; i < arr.Len(); i++ {
    43  		if equals(arr.Index(i).Interface(), o) {
    44  			return i
    45  		}
    46  	}
    47  	return -1
    48  }
    49  
    50  // GetRandomIndices returns indiceCount random indices
    51  // from 0 to highestIndex.
    52  func GetRandomIndices(indiceCount, highestIndex int) []int {
    53  	// More choices needed than possible to choose.
    54  	if highestIndex+1 < indiceCount {
    55  		return nil
    56  	}
    57  
    58  	return rand.Perm(highestIndex + 1)[:indiceCount]
    59  }
    60  
    61  // Set is a generic and thread-safe
    62  // set container
    63  type Set struct {
    64  	items map[interface{}]struct{}
    65  	lock  *sync.RWMutex
    66  }
    67  
    68  // NewSet returns a new set
    69  func NewSet() *Set {
    70  	return &Set{lock: &sync.RWMutex{}, items: make(map[interface{}]struct{})}
    71  }
    72  
    73  // Add adds given item to the set
    74  func (s *Set) Add(item interface{}) {
    75  	s.lock.Lock()
    76  	defer s.lock.Unlock()
    77  	s.items[item] = struct{}{}
    78  }
    79  
    80  // Exists returns true whether given item is in the set
    81  func (s *Set) Exists(item interface{}) bool {
    82  	s.lock.RLock()
    83  	defer s.lock.RUnlock()
    84  	_, exists := s.items[item]
    85  	return exists
    86  }
    87  
    88  // Size returns the size of the set
    89  func (s *Set) Size() int {
    90  	s.lock.RLock()
    91  	defer s.lock.RUnlock()
    92  	return len(s.items)
    93  }
    94  
    95  // ToArray returns a slice with items
    96  // at the point in time the method was invoked
    97  func (s *Set) ToArray() []interface{} {
    98  	s.lock.RLock()
    99  	defer s.lock.RUnlock()
   100  	a := make([]interface{}, len(s.items))
   101  	i := 0
   102  	for item := range s.items {
   103  		a[i] = item
   104  		i++
   105  	}
   106  	return a
   107  }
   108  
   109  // Clear removes all elements from set
   110  func (s *Set) Clear() {
   111  	s.lock.Lock()
   112  	defer s.lock.Unlock()
   113  	s.items = make(map[interface{}]struct{})
   114  }
   115  
   116  // Remove removes a given item from the set
   117  func (s *Set) Remove(item interface{}) {
   118  	s.lock.Lock()
   119  	defer s.lock.Unlock()
   120  	delete(s.items, item)
   121  }
   122  
   123  // PrintStackTrace prints to stdout
   124  // all goroutines
   125  func PrintStackTrace() {
   126  	buf := make([]byte, 1<<16)
   127  	l := runtime.Stack(buf, true)
   128  	fmt.Printf("%s", buf[:l])
   129  }
   130  
   131  // GetIntOrDefault returns the int value from config if present otherwise default value
   132  func GetIntOrDefault(key string, defVal int) int {
   133  	viperLock.RLock()
   134  	defer viperLock.RUnlock()
   135  
   136  	if val := viper.GetInt(key); val != 0 {
   137  		return val
   138  	}
   139  
   140  	return defVal
   141  }
   142  
   143  // GetFloat64OrDefault returns the float64 value from config if present otherwise default value
   144  func GetFloat64OrDefault(key string, defVal float64) float64 {
   145  	viperLock.RLock()
   146  	defer viperLock.RUnlock()
   147  
   148  	if val := viper.GetFloat64(key); val != 0 {
   149  		return val
   150  	}
   151  
   152  	return defVal
   153  }
   154  
   155  // GetDurationOrDefault returns the Duration value from config if present otherwise default value
   156  func GetDurationOrDefault(key string, defVal time.Duration) time.Duration {
   157  	viperLock.RLock()
   158  	defer viperLock.RUnlock()
   159  
   160  	if val := viper.GetDuration(key); val != 0 {
   161  		return val
   162  	}
   163  
   164  	return defVal
   165  }
   166  
   167  // SetVal stores key value to viper
   168  func SetVal(key string, val interface{}) {
   169  	viperLock.Lock()
   170  	defer viperLock.Unlock()
   171  	viper.Set(key, val)
   172  }
   173  
   174  // RandomInt returns, as an int, a non-negative pseudo-random integer in [0,n)
   175  // It panics if n <= 0
   176  func RandomInt(n int) int {
   177  	return rand.Intn(n)
   178  }
   179  
   180  // RandomUInt64 returns a random uint64
   181  //
   182  // If we want a rand that's non-global and specific to gossip, we can
   183  // establish one. Otherwise this uses the process-global locking RNG.
   184  func RandomUInt64() uint64 {
   185  	return rand.Uint64()
   186  }
   187  
   188  func BytesToStrings(bytes [][]byte) []string {
   189  	strings := make([]string, len(bytes))
   190  	for i, b := range bytes {
   191  		strings[i] = string(b)
   192  	}
   193  	return strings
   194  }
   195  
   196  func StringsToBytes(strings []string) [][]byte {
   197  	bytes := make([][]byte, len(strings))
   198  	for i, str := range strings {
   199  		bytes[i] = []byte(str)
   200  	}
   201  	return bytes
   202  }