203 lines
4.2 KiB
Go
203 lines
4.2 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package util
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"reflect"
|
|
"runtime"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
func init() { // do we really need this?
|
|
rand.Seed(time.Now().UnixNano())
|
|
}
|
|
|
|
// Equals returns whether a and b are the same
|
|
type Equals func(a interface{}, b interface{}) bool
|
|
|
|
var viperLock sync.RWMutex
|
|
|
|
// Contains returns whether a given slice a contains a string s
|
|
func Contains(s string, a []string) bool {
|
|
for _, e := range a {
|
|
if e == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IndexInSlice returns the index of given object o in array, and -1 if it is not in array.
|
|
func IndexInSlice(array interface{}, o interface{}, equals Equals) int {
|
|
arr := reflect.ValueOf(array)
|
|
for i := 0; i < arr.Len(); i++ {
|
|
if equals(arr.Index(i).Interface(), o) {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// GetRandomIndices returns indiceCount random indices
|
|
// from 0 to highestIndex.
|
|
func GetRandomIndices(indiceCount, highestIndex int) []int {
|
|
// More choices needed than possible to choose.
|
|
if highestIndex+1 < indiceCount {
|
|
return nil
|
|
}
|
|
|
|
return rand.Perm(highestIndex + 1)[:indiceCount]
|
|
}
|
|
|
|
// Set is a generic and thread-safe
|
|
// set container
|
|
type Set struct {
|
|
items map[interface{}]struct{}
|
|
lock *sync.RWMutex
|
|
}
|
|
|
|
// NewSet returns a new set
|
|
func NewSet() *Set {
|
|
return &Set{lock: &sync.RWMutex{}, items: make(map[interface{}]struct{})}
|
|
}
|
|
|
|
// Add adds given item to the set
|
|
func (s *Set) Add(item interface{}) {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
s.items[item] = struct{}{}
|
|
}
|
|
|
|
// Exists returns true whether given item is in the set
|
|
func (s *Set) Exists(item interface{}) bool {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
_, exists := s.items[item]
|
|
return exists
|
|
}
|
|
|
|
// Size returns the size of the set
|
|
func (s *Set) Size() int {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
return len(s.items)
|
|
}
|
|
|
|
// ToArray returns a slice with items
|
|
// at the point in time the method was invoked
|
|
func (s *Set) ToArray() []interface{} {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
a := make([]interface{}, len(s.items))
|
|
i := 0
|
|
for item := range s.items {
|
|
a[i] = item
|
|
i++
|
|
}
|
|
return a
|
|
}
|
|
|
|
// Clear removes all elements from set
|
|
func (s *Set) Clear() {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
s.items = make(map[interface{}]struct{})
|
|
}
|
|
|
|
// Remove removes a given item from the set
|
|
func (s *Set) Remove(item interface{}) {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
delete(s.items, item)
|
|
}
|
|
|
|
// PrintStackTrace prints to stdout
|
|
// all goroutines
|
|
func PrintStackTrace() {
|
|
buf := make([]byte, 1<<16)
|
|
l := runtime.Stack(buf, true)
|
|
fmt.Printf("%s", buf[:l])
|
|
}
|
|
|
|
// GetIntOrDefault returns the int value from config if present otherwise default value
|
|
func GetIntOrDefault(key string, defVal int) int {
|
|
viperLock.RLock()
|
|
defer viperLock.RUnlock()
|
|
|
|
if val := viper.GetInt(key); val != 0 {
|
|
return val
|
|
}
|
|
|
|
return defVal
|
|
}
|
|
|
|
// GetFloat64OrDefault returns the float64 value from config if present otherwise default value
|
|
func GetFloat64OrDefault(key string, defVal float64) float64 {
|
|
viperLock.RLock()
|
|
defer viperLock.RUnlock()
|
|
|
|
if val := viper.GetFloat64(key); val != 0 {
|
|
return val
|
|
}
|
|
|
|
return defVal
|
|
}
|
|
|
|
// GetDurationOrDefault returns the Duration value from config if present otherwise default value
|
|
func GetDurationOrDefault(key string, defVal time.Duration) time.Duration {
|
|
viperLock.RLock()
|
|
defer viperLock.RUnlock()
|
|
|
|
if val := viper.GetDuration(key); val != 0 {
|
|
return val
|
|
}
|
|
|
|
return defVal
|
|
}
|
|
|
|
// SetVal stores key value to viper
|
|
func SetVal(key string, val interface{}) {
|
|
viperLock.Lock()
|
|
defer viperLock.Unlock()
|
|
viper.Set(key, val)
|
|
}
|
|
|
|
// RandomInt returns, as an int, a non-negative pseudo-random integer in [0,n)
|
|
// It panics if n <= 0
|
|
func RandomInt(n int) int {
|
|
return rand.Intn(n)
|
|
}
|
|
|
|
// RandomUInt64 returns a random uint64
|
|
//
|
|
// If we want a rand that's non-global and specific to gossip, we can
|
|
// establish one. Otherwise this uses the process-global locking RNG.
|
|
func RandomUInt64() uint64 {
|
|
return rand.Uint64()
|
|
}
|
|
|
|
func BytesToStrings(bytes [][]byte) []string {
|
|
strings := make([]string, len(bytes))
|
|
for i, b := range bytes {
|
|
strings[i] = string(b)
|
|
}
|
|
return strings
|
|
}
|
|
|
|
func StringsToBytes(strings []string) [][]byte {
|
|
bytes := make([][]byte, len(strings))
|
|
for i, str := range strings {
|
|
bytes[i] = []byte(str)
|
|
}
|
|
return bytes
|
|
}
|