internal/utils/misc.go (120 lines of code) (raw):
/*
* Copyright (c) 2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package utils
import (
"fmt"
"math"
"math/rand"
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/shirou/gopsutil/v4/disk"
atom "go.uber.org/atomic"
"github.com/alibaba/schedulerx-worker-go/internal/constants"
)
var (
seed = atom.NewInt32(1000)
uid uint64 = 0
deliveryId = atom.NewInt64(0)
)
const (
manifestSplitter = "$"
pathTplPrefix = "$"
base64Chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+~"
)
func SyncMapLen(m *sync.Map) int {
length := 0
m.Range(func(_, _ interface{}) bool {
length++
return true
})
return length
}
func GetMsgType(manifest string) (string, error) {
if len(manifest) > 0 && strings.Contains(manifest, manifestSplitter) {
parts := strings.Split(manifest, manifestSplitter)
if len(parts) == 2 {
return parts[1], nil
}
}
return "", fmt.Errorf("Invalid manifest: %s ", manifest)
}
func ShuffleStringSlice(nums []string) []string {
rand.Seed(time.Now().UnixNano())
for i := len(nums) - 1; i > 0; i-- {
j := rand.Intn(i + 1)
nums[i], nums[j] = nums[j], nums[i]
}
return nums
}
func GenPathTpl() string {
if seed.Load() == math.MaxInt32 {
seed.Store(0)
}
return base64Func(seed.Inc(), pathTplPrefix)
}
func base64Func(l int32, sb string) string {
sb += string(base64Chars[l&63])
next := l >> 6
if next == 0 {
return sb
}
return base64Func(next, sb)
}
func GetHandshakeUid() uint64 {
if uid != 0 {
return uid
}
rand.Seed(time.Now().UnixNano())
uid = rand.Uint64()
return uid
}
func GetDeliveryId() int64 {
return deliveryId.Inc()
}
func RemoveSliceElem(s []string, elem string) []string {
result := []string{}
for _, value := range s {
if value != elem {
result = append(result, value)
}
}
return result
}
func Int64SliceToStringSlice(intSlice []int64) []string {
strSlice := make([]string, len(intSlice))
for i, v := range intSlice {
strSlice[i] = strconv.FormatInt(v, 10)
}
return strSlice
}
func GetUserDiskSpacePercent() (float64, error) {
path := "/"
if runtime.GOOS == "windows" {
path = "C:"
}
info, err := disk.Usage(path)
if err != nil {
return 0, err
}
return info.UsedPercent, nil
}
func IsRootTask(taskName string) bool {
return taskName == constants.MapTaskRootName
}
// PrintCallStack print the latest 5-level call stack for troubleshooting
func PrintCallStack() {
const size = 5
var pc [size]uintptr // Stores the program counter value for each level in the call stack
n := runtime.Callers(2, pc[:]) // Skip runtime.Callers and PrintStack itself
if n == 0 {
// The call stack information is empty and returns directly
return
}
frames := runtime.CallersFrames(pc[:n])
for i := 0; i < size; i++ {
frame, more := frames.Next()
fmt.Printf("%s\n\t%s:%d\n", frame.Function, frame.File, frame.Line)
if !more {
break
}
}
}