This repository was archived by the owner on Jan 21, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutil.go
136 lines (117 loc) · 3.45 KB
/
util.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
130
131
132
133
134
135
136
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Apache License 2.0.
* See the file "LICENSE" for details.
*/
package util
import (
"hash/fnv"
"strconv"
"sync/atomic"
"unicode"
"unicode/utf8"
"github.com/sirupsen/logrus"
"github.com/elastic/otel-profiling-agent/libpf/hash"
)
// PID represent Unix Process ID (pid_t)
type PID int32
func (p PID) Hash32() uint32 {
return uint32(p)
}
// TID represent a thread ID
type TID int32
// HashString turns a string into a 64-bit hash.
func HashString(s string) uint64 {
h := fnv.New64a()
if _, err := h.Write([]byte(s)); err != nil {
logrus.Fatalf("Failed to write '%v' to hash: %v", s, err)
}
return h.Sum64()
}
// HexToUint64 is a convenience function to extract a hex string to a uint64 and
// not worry about errors. Essentially a "mustConvertHexToUint64".
func HexToUint64(str string) uint64 {
v, err := strconv.ParseUint(str, 16, 64)
if err != nil {
logrus.Fatalf("Failure to hex-convert %s to uint64: %v", str, err)
}
return v
}
// DecToUint64 is a convenience function to extract a decimal string to a uint64
// and not worry about errors. Essentially a "mustConvertDecToUint64".
func DecToUint64(str string) uint64 {
v, err := strconv.ParseUint(str, 10, 64)
if err != nil {
logrus.Fatalf("Failure to dec-convert %s to uint64: %v", str, err)
}
return v
}
// IsValidString checks if string is UTF-8-encoded and only contains expected characters.
func IsValidString(s string) bool {
if s == "" {
return false
}
if !utf8.ValidString(s) {
return false
}
for _, r := range s {
if !unicode.IsPrint(r) {
return false
}
}
return true
}
// NextPowerOfTwo returns the next highest power of 2 for a given value v or v,
// if v is a power of 2.
func NextPowerOfTwo(v uint32) uint32 {
v--
v |= v >> 1
v |= v >> 2
v |= v >> 4
v |= v >> 8
v |= v >> 16
v++
return v
}
// AtomicUpdateMaxUint32 updates the value in store using atomic memory primitives. newValue will
// only be placed in store if newValue is larger than the current value in store.
// To avoid inconsistency parallel updates to store should be avoided.
func AtomicUpdateMaxUint32(store *atomic.Uint32, newValue uint32) {
for {
// Load the current value
oldValue := store.Load()
if newValue <= oldValue {
// No update needed.
break
}
if store.CompareAndSwap(oldValue, newValue) {
// The value was atomically updated.
break
}
// The value changed between load and update attempt.
// Retry with the new value.
}
}
// VersionUint returns a single integer composed of major, minor, patch.
func VersionUint(major, minor, patch uint32) uint32 {
return (major << 16) + (minor << 8) + patch
}
// Range describes a range with Start and End values.
type Range struct {
Start uint64
End uint64
}
// SourceLineno represents a line number within a source file. It is intended to be used for the
// source line numbers associated with offsets in native code, or for source line numbers in
// interpreted code.
type SourceLineno uint64
// OnDiskFileIdentifier can be used as unique identifier for a file.
// It is a structure to identify a particular file on disk by
// deviceID and inode number.
type OnDiskFileIdentifier struct {
DeviceID uint64 // dev_t as reported by stat.
InodeNum uint64 // ino_t should fit into 64 bits
}
func (odfi OnDiskFileIdentifier) Hash32() uint32 {
return uint32(hash.Uint64(odfi.InodeNum) + odfi.DeviceID)
}