github.com/lzy4123/fabric@v2.1.1+incompatible/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 }