-
Notifications
You must be signed in to change notification settings - Fork 25
/
numa-socket.go
164 lines (143 loc) · 3.98 KB
/
numa-socket.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package eal
/*
#include "../../csrc/core/common.h"
*/
import "C"
import (
"encoding/json"
"strconv"
"github.com/graphql-go/graphql"
"go.uber.org/zap"
)
// NumaSocket represents a NUMA socket.
// Zero value is SOCKET_ID_ANY.
type NumaSocket struct {
v int // socket ID + 1
}
var (
_ json.Marshaler = NumaSocket{}
_ json.Unmarshaler = (*NumaSocket)(nil)
)
// ID returns NUMA socket ID.
func (socket NumaSocket) ID() int {
return socket.v - 1
}
// IsAny returns true if this represents SOCKET_ID_ANY.
func (socket NumaSocket) IsAny() bool {
return socket.v == 0
}
// Match returns true if either NumaSocket is SOCKET_ID_ANY, or both are the same NumaSocket.
func (socket NumaSocket) Match(other NumaSocket) bool {
return socket.IsAny() || other.IsAny() || socket.v == other.v
}
func (socket NumaSocket) String() string {
if socket.IsAny() {
return "any"
}
return strconv.Itoa(socket.ID())
}
// MarshalJSON encodes NUMA socket as number.
// Any is encoded as null.
func (socket NumaSocket) MarshalJSON() ([]byte, error) {
if socket.IsAny() {
return json.Marshal(nil)
}
return json.Marshal(socket.ID())
}
// UnmarshalJSON decodes NUMA socket as number.
// null is interpreted as Any.
func (socket *NumaSocket) UnmarshalJSON(p []byte) error {
if string(p) == "null" {
*socket = NumaSocket{}
return nil
}
id, e := strconv.ParseInt(string(p), 10, 64)
if e != nil {
return e
}
*socket = NumaSocketFromID(int(id))
return nil
}
// ZapField returns a zap.Field for logging.
func (socket NumaSocket) ZapField(key string) zap.Field {
if socket.IsAny() {
return zap.String(key, "any")
}
return zap.Int(key, socket.ID())
}
// NumaSocket implements WithNumaSocket.
func (socket NumaSocket) NumaSocket() NumaSocket {
return socket
}
// NumaSocketFromID converts socket ID to NumaSocket.
func NumaSocketFromID(id int) (socket NumaSocket) {
if id < 0 || id >= C.RTE_MAX_NUMA_NODES {
return socket
}
socket.v = id + 1
return socket
}
// RewriteAnyNumaSocket provides a function to change "any NUMA socket" to a concrete NUMA socket.
type RewriteAnyNumaSocket int
const (
// KeepAnyNumaSocket keeps "any NUMA socket" unchanged.
KeepAnyNumaSocket RewriteAnyNumaSocket = -2 - iota
// RewriteAnyNumaSocketFirst rewrites "any NUMA socket" to eal.Sockets[0].
RewriteAnyNumaSocketFirst
// RewriteAnyNumaSocketRandom rewrites "any NUMA socket" to eal.RandomSocket().
RewriteAnyNumaSocketRandom
)
// RewriteAnyNumaSocketTo rewrites "any NUMA socket" to the specified NUMA socket.
func RewriteAnyNumaSocketTo(socket NumaSocket) (r RewriteAnyNumaSocket) {
return RewriteAnyNumaSocket(socket.ID())
}
// Rewrite rewrites the input if it is "any NUMA socket", otherwise keeps it unchanged.
func (r RewriteAnyNumaSocket) Rewrite(socket NumaSocket) NumaSocket {
if !socket.IsAny() {
return socket
}
switch r {
case KeepAnyNumaSocket:
return socket
case RewriteAnyNumaSocketFirst:
if len(Sockets) > 0 {
return Sockets[0]
}
return socket
case RewriteAnyNumaSocketRandom:
return RandomSocket()
default:
return NumaSocketFromID(int(r))
}
}
// WithNumaSocket interface is implemented by types that have an associated or preferred NUMA socket.
type WithNumaSocket interface {
NumaSocket() NumaSocket
}
// ClassifyByNumaSocket classifies items by NUMA socket.
//
// T: type that satisfies WithNumaSocket interface
// s: source []T
//
// Returns map[eal.NumaSocket][]T
func ClassifyByNumaSocket[T WithNumaSocket, S ~[]T](s S, r RewriteAnyNumaSocket) (m map[NumaSocket]S) {
m = map[NumaSocket]S{}
for _, item := range s {
socket := r.Rewrite(item.NumaSocket())
m[socket] = append(m[socket], item)
}
return m
}
// GqlWithNumaSocket is a GraphQL field for source object that implements WithNumaSocket.
var GqlWithNumaSocket = &graphql.Field{
Type: graphql.Int,
Name: "numaSocket",
Description: "NUMA socket.",
Resolve: func(p graphql.ResolveParams) (any, error) {
socket := p.Source.(WithNumaSocket).NumaSocket()
if socket.IsAny() {
return nil, nil
}
return socket.ID(), nil
},
}