-
Notifications
You must be signed in to change notification settings - Fork 315
/
common.go
129 lines (112 loc) · 3.48 KB
/
common.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
Copyright 2022 The Koordinator Authors.
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 system
import (
"io"
"os"
"path"
"runtime"
"strings"
"syscall"
"k8s.io/klog/v2"
)
var (
CommonRootDir = "" // for uni-test
PageSize = int64(syscall.Getpagesize())
)
func CommonFileRead(file string) (string, error) {
file = path.Join(CommonRootDir, file)
klog.V(5).Infof("read %s", file)
data, err := os.ReadFile(file)
return strings.Trim(string(data), "\n"), err
}
func CommonFileWriteIfDifferent(file string, value string) (bool, error) {
currentValue, err := CommonFileRead(file)
if err != nil {
return false, err
}
if value == currentValue {
klog.Infof("resource currentValue equal newValue, skip update resource! file:%s, value %s", file, value)
return false, nil
}
if err := CommonFileWrite(file, value); err != nil {
return false, err
}
return true, nil
}
func CommonFileWrite(file string, data string) error {
file = path.Join(CommonRootDir, file)
klog.V(5).Infof("write %s [%s]", file, data)
return os.WriteFile(file, []byte(data), 0644)
}
// ReadFileNoStat uses io.ReadAll to read contents of entire file.
// This is similar to io.ReadFile but without the call to os.Stat, because
// many files in /proc and /sys report incorrect file sizes (either 0 or 4096).
// Reads a max file size of 512kB. For files larger than this, a scanner
// should be used.
func ReadFileNoStat(filename string) ([]byte, error) {
const maxBufferSize = 1024 * 512
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
reader := io.LimitReader(f, maxBufferSize)
return io.ReadAll(reader)
}
func FileExists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// ParseKVMap parses a file content into a KV map.
// e.g. `user 100\nsystem 20` -> `{"user": "100", "system": "20"}`
func ParseKVMap(content string) map[string]string {
m := map[string]string{}
lines := strings.Split(content, "\n")
for _, line := range lines {
lineItems := strings.Fields(line)
if len(lineItems) < 2 {
klog.V(6).Infof("parse key-value map failed, got invalid number of items, line %s, content %s",
line, content)
continue
}
m[lineItems[0]] = lineItems[1]
}
return m
}
// GoWithNewThread synchronously runs the function in a new goroutine bound to a new OS thread.
func GoWithNewThread(f func() interface{}) interface{} {
// Lock the thread of the caller goroutine to ensure the thread does not change outside the new goroutine.
runtime.LockOSThread()
defer runtime.UnlockOSThread()
retCh := make(chan interface{})
go func() {
// When the calling goroutine exits without unlocking the thread, the thread will be terminated.
// It helps the function to lock with an individual thread so not to affect the caller goroutine.
runtime.LockOSThread()
ret := f()
retCh <- ret
}()
ret := <-retCh
return ret
}