1 /*
2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.internal.platform.cgroupv1;
27
28 import java.io.BufferedReader;
29 import java.io.IOException;
30 import java.math.BigInteger;
31 import java.nio.file.Files;
32 import java.nio.file.Paths;
33 import java.security.AccessController;
34 import java.security.PrivilegedActionException;
35 import java.security.PrivilegedExceptionAction;
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.Optional;
39 import java.util.function.Function;
40 import java.util.stream.Stream;
41
42 public class SubSystem {
43 String root;
44 String mountPoint;
45 String path;
46
47 public SubSystem(String root, String mountPoint) {
48 this.root = root;
49 this.mountPoint = mountPoint;
50 }
51
52 public void setPath(String cgroupPath) {
53 if (root != null && cgroupPath != null) {
54 if (root.equals("/")) {
55 if (!cgroupPath.equals("/")) {
56 path = mountPoint + cgroupPath;
57 }
58 else {
59 path = mountPoint;
60 }
61 }
62 else {
63 if (root.equals(cgroupPath)) {
64 path = mountPoint;
65 }
66 else {
67 if (cgroupPath.startsWith(root)) {
68 if (cgroupPath.length() > root.length()) {
69 String cgroupSubstr = cgroupPath.substring(root.length());
70 path = mountPoint + cgroupSubstr;
71 }
72 }
73 }
74 }
75 }
76 }
77
78 public String path() {
79 return path;
80 }
81
82 /**
83 * getSubSystemStringValue
84 *
85 * Return the first line of the file "parm" argument from the subsystem.
86 *
87 * TODO: Consider using weak references for caching BufferedReader object.
88 *
89 * @param subsystem
90 * @param parm
91 * @return Returns the contents of the file specified by param.
92 */
93 public static String getStringValue(SubSystem subsystem, String parm) {
94 if (subsystem == null) return null;
95
96 try {
97 return subsystem.readStringValue(parm);
98 } catch (IOException e) {
99 return null;
100 }
101 }
102
103 private String readStringValue(String param) throws IOException {
104 PrivilegedExceptionAction<BufferedReader> pea = () ->
105 Files.newBufferedReader(Paths.get(path(), param));
106 try (BufferedReader bufferedReader =
107 AccessController.doPrivileged(pea)) {
108 String line = bufferedReader.readLine();
109 return line;
110 } catch (PrivilegedActionException e) {
111 Metrics.unwrapIOExceptionAndRethrow(e);
112 throw new InternalError(e.getCause());
113 }
114 }
115
116 public static long getLongValueMatchingLine(SubSystem subsystem,
117 String param,
118 String match,
119 Function<String, Long> conversion) {
120 long retval = Metrics.unlimited_minimum + 1; // default unlimited
121 try {
122 List<String> lines = subsystem.readMatchingLines(param);
123 for (String line : lines) {
124 if (line.startsWith(match)) {
125 retval = conversion.apply(line);
126 break;
127 }
128 }
129 } catch (IOException e) {
130 // Ignore. Default is unlimited.
131 }
132 return retval;
133 }
134
135 private List<String> readMatchingLines(String param) throws IOException {
136 try {
137 PrivilegedExceptionAction<List<String>> pea = () ->
138 Files.readAllLines(Paths.get(path(), param));
139 return AccessController.doPrivileged(pea);
140 } catch (PrivilegedActionException e) {
141 Metrics.unwrapIOExceptionAndRethrow(e);
142 throw new InternalError(e.getCause());
143 }
144 }
145
146 public static long getLongValue(SubSystem subsystem, String parm) {
147 String strval = getStringValue(subsystem, parm);
148 return convertStringToLong(strval);
149 }
150
151 public static long convertStringToLong(String strval) {
152 long retval = 0;
153 if (strval == null) return 0L;
154
155 try {
156 retval = Long.parseLong(strval);
157 } catch (NumberFormatException e) {
158 // For some properties (e.g. memory.limit_in_bytes) we may overflow the range of signed long.
159 // In this case, return Long.MAX_VALUE
160 BigInteger b = new BigInteger(strval);
161 if (b.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
162 return Long.MAX_VALUE;
163 }
164 }
165 return retval;
166 }
167
168 public static double getDoubleValue(SubSystem subsystem, String parm) {
169 String strval = getStringValue(subsystem, parm);
170
171 if (strval == null) return 0L;
172
173 double retval = Double.parseDouble(strval);
174
175 return retval;
176 }
177
178 /**
179 * getSubSystemlongEntry
180 *
181 * Return the long value from the line containing the string "entryname"
182 * within file "parm" in the "subsystem".
183 *
184 * TODO: Consider using weak references for caching BufferedReader object.
185 *
186 * @param subsystem
187 * @param parm
188 * @param entryname
189 * @return long value
190 */
191 public static long getLongEntry(SubSystem subsystem, String parm, String entryname) {
192 String val = null;
193
194 if (subsystem == null) return 0L;
195
196 try (Stream<String> lines = Metrics.readFilePrivileged(Paths.get(subsystem.path(), parm))) {
197
198 Optional<String> result = lines.map(line -> line.split(" "))
199 .filter(line -> (line.length == 2 &&
200 line[0].equals(entryname)))
201 .map(line -> line[1])
202 .findFirst();
203
204 return result.isPresent() ? Long.parseLong(result.get()) : 0L;
205 }
206 catch (IOException e) {
207 return 0L;
208 }
209 }
210
211 public static int getIntValue(SubSystem subsystem, String parm) {
212 String val = getStringValue(subsystem, parm);
213
214 if (val == null) return 0;
215
216 return Integer.parseInt(val);
217 }
218
219 /**
220 * StringRangeToIntArray
221 *
222 * Convert a string in the form of 1,3-4,6 to an array of
223 * integers containing all the numbers in the range.
224 *
225 * @param range
226 * @return int[] containing a sorted list of processors or memory nodes
227 */
228 public static int[] StringRangeToIntArray(String range) {
229 int[] ints = new int[0];
230
231 if (range == null) return ints;
232
233 ArrayList<Integer> results = new ArrayList<>();
234 String strs[] = range.split(",");
235 for (String str : strs) {
236 if (str.contains("-")) {
237 String lohi[] = str.split("-");
238 // validate format
239 if (lohi.length != 2) {
240 continue;
241 }
242 int lo = Integer.parseInt(lohi[0]);
243 int hi = Integer.parseInt(lohi[1]);
244 for (int i = lo; i <= hi; i++) {
245 results.add(i);
246 }
247 }
248 else {
249 results.add(Integer.parseInt(str));
250 }
251 }
252
253 // sort results
254 results.sort(null);
255
256 // convert ArrayList to primitive int array
257 ints = new int[results.size()];
258 int i = 0;
259 for (Integer n : results) {
260 ints[i++] = n;
261 }
262
263 return ints;
264 }
265
266 public static class MemorySubSystem extends SubSystem {
267
268 private boolean hierarchical;
269
270 public MemorySubSystem(String root, String mountPoint) {
271 super(root, mountPoint);
272 }
273
274 boolean isHierarchical() {
275 return hierarchical;
276 }
277
278 void setHierarchical(boolean hierarchical) {
279 this.hierarchical = hierarchical;
280 }
281
282 }
283 }
|
1 /*
2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.internal.platform.cgroupv1;
27
28 import jdk.internal.platform.CgroupSubsystem;
29 import jdk.internal.platform.CgroupSubsystemController;
30
31 public class CgroupV1SubsystemController implements CgroupSubsystemController {
32
33 private static final double DOUBLE_RETVAL_UNLIMITED = CgroupSubsystem.LONG_RETVAL_UNLIMITED;
34 // Values returned larger than this number are unlimited.
35 static long UNLIMITED_MIN = 0x7FFFFFFFFF000000L;
36 String root;
37 String mountPoint;
38 String path;
39
40 public CgroupV1SubsystemController(String root, String mountPoint) {
41 this.root = root;
42 this.mountPoint = mountPoint;
43 }
44
45 public void setPath(String cgroupPath) {
46 if (root != null && cgroupPath != null) {
47 if (root.equals("/")) {
48 if (!cgroupPath.equals("/")) {
49 path = mountPoint + cgroupPath;
50 }
51 else {
52 path = mountPoint;
53 }
54 }
55 else {
56 if (root.equals(cgroupPath)) {
57 path = mountPoint;
58 }
59 else {
60 if (cgroupPath.startsWith(root)) {
61 if (cgroupPath.length() > root.length()) {
62 String cgroupSubstr = cgroupPath.substring(root.length());
63 path = mountPoint + cgroupSubstr;
64 }
65 }
66 }
67 }
68 }
69 }
70
71 @Override
72 public String path() {
73 return path;
74 }
75
76 public static long getLongEntry(CgroupSubsystemController controller, String param, String entryname) {
77 return CgroupSubsystemController.getLongEntry(controller,
78 param,
79 entryname,
80 CgroupSubsystem.LONG_RETVAL_UNLIMITED /* retval on error */);
81 }
82
83 public static double getDoubleValue(CgroupSubsystemController controller, String parm) {
84 return CgroupSubsystemController.getDoubleValue(controller,
85 parm,
86 DOUBLE_RETVAL_UNLIMITED /* retval on error */);
87 }
88
89 public static long convertStringToLong(String strval) {
90 return CgroupSubsystemController.convertStringToLong(strval,
91 Long.MAX_VALUE /* overflow value */,
92 CgroupSubsystem.LONG_RETVAL_UNLIMITED /* retval on error */);
93 }
94
95 public static long longValOrUnlimited(long value) {
96 return value > UNLIMITED_MIN ? CgroupSubsystem.LONG_RETVAL_UNLIMITED : value;
97 }
98
99 public static long getLongValueMatchingLine(CgroupSubsystemController controller,
100 String param,
101 String match) {
102 return CgroupSubsystemController.getLongValueMatchingLine(controller,
103 param,
104 match,
105 CgroupV1SubsystemController::convertHierachicalLimitLine,
106 CgroupSubsystem.LONG_RETVAL_UNLIMITED);
107 }
108
109 public static long convertHierachicalLimitLine(String line) {
110 String[] tokens = line.split("\\s");
111 if (tokens.length == 2) {
112 String strVal = tokens[1];
113 return CgroupV1SubsystemController.convertStringToLong(strVal);
114 }
115 return CgroupV1SubsystemController.UNLIMITED_MIN + 1; // unlimited
116 }
117
118 }
|