1 /* 2 * Copyright (c) 2019, Red Hat Inc. 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; 27 28 import java.io.IOException; 29 import java.math.BigInteger; 30 import java.nio.file.Path; 31 import java.nio.file.Paths; 32 import java.util.ArrayList; 33 import java.util.List; 34 import java.util.Optional; 35 import java.util.function.Function; 36 import java.util.stream.Stream; 37 38 /** 39 * Cgroup version agnostic controller logic 40 * 41 */ 42 public interface CgroupSubsystemController { 43 44 public static final String EMPTY_STR = ""; 45 46 public String path(); 47 48 /** 49 * getStringValue 50 * 51 * Return the first line of the file "parm" argument from the controller. 52 * 53 * TODO: Consider using weak references for caching BufferedReader object. 54 * 55 * @param controller 56 * @param parm 57 * @return Returns the contents of the file specified by param. 58 */ 59 public static String getStringValue(CgroupSubsystemController controller, String param) { 60 if (controller == null) return null; 61 62 try { 63 return CgroupUtil.readStringValue(controller, param); 64 } 65 catch (IOException e) { 66 return null; 67 } 68 69 } 70 71 public static long getLongValueMatchingLine(CgroupSubsystemController controller, 72 String param, 73 String match, 74 Function<String, Long> conversion) { 75 long retval = Metrics.LONG_RETVAL_UNLIMITED; 76 try { 77 Path filePath = Paths.get(controller.path(), param); 78 List<String> lines = CgroupUtil.readAllLinesPrivileged(filePath); 79 for (String line : lines) { 80 if (line.startsWith(match)) { 81 retval = conversion.apply(line); 82 break; 83 } 84 } 85 } catch (IOException e) { 86 // Ignore. Default is unlimited. 87 } 88 return retval; 89 } 90 91 public static long getLongValue(CgroupSubsystemController controller, 92 String parm, 93 Function<String, Long> conversion) { 94 String strval = getStringValue(controller, parm); 95 return conversion.apply(strval); 96 } 97 98 public static double getDoubleValue(CgroupSubsystemController controller, String parm) { 99 String strval = getStringValue(controller, parm); 100 101 if (strval == null) return 0L; 102 103 double retval = Double.parseDouble(strval); 104 105 return retval; 106 } 107 108 /** 109 * getSubSystemlongEntry 110 * 111 * Return the long value from the line containing the string "entryname" 112 * within file "parm" in the "subsystem". 113 * 114 * TODO: Consider using weak references for caching BufferedReader object. 115 * 116 * @param controller 117 * @param parm 118 * @param entryname 119 * @return long value 120 */ 121 public static long getLongEntry(CgroupSubsystemController controller, String parm, String entryname) { 122 if (controller == null) return 0L; 123 124 try (Stream<String> lines = CgroupUtil.readFilePrivileged(Paths.get(controller.path(), parm))) { 125 126 Optional<String> result = lines.map(line -> line.split(" ")) 127 .filter(line -> (line.length == 2 && 128 line[0].equals(entryname))) 129 .map(line -> line[1]) 130 .findFirst(); 131 132 return result.isPresent() ? Long.parseLong(result.get()) : 0L; 133 } 134 catch (IOException e) { 135 return 0L; 136 } 137 } 138 139 /** 140 * StringRangeToIntArray 141 * 142 * Convert a string in the form of 1,3-4,6 to an array of 143 * integers containing all the numbers in the range. 144 * 145 * @param range 146 * @return int[] containing a sorted list of processors or memory nodes 147 */ 148 public static int[] stringRangeToIntArray(String range) { 149 if (range == null || EMPTY_STR.equals(range)) return null; 150 151 int[] ints = new int[0]; 152 ArrayList<Integer> results = new ArrayList<>(); 153 String strs[] = range.split(","); 154 for (String str : strs) { 155 if (str.contains("-")) { 156 String lohi[] = str.split("-"); 157 // validate format 158 if (lohi.length != 2) { 159 continue; 160 } 161 int lo = Integer.parseInt(lohi[0]); 162 int hi = Integer.parseInt(lohi[1]); 163 for (int i = lo; i <= hi; i++) { 164 results.add(i); 165 } 166 } 167 else { 168 results.add(Integer.parseInt(str)); 169 } 170 } 171 172 // sort results 173 results.sort(null); 174 175 // convert ArrayList to primitive int array 176 ints = new int[results.size()]; 177 int i = 0; 178 for (Integer n : results) { 179 ints[i++] = n; 180 } 181 182 return ints; 183 } 184 185 public static long convertStringToLong(String strval, long overflowRetval) { 186 long retval = 0; 187 if (strval == null) return 0L; 188 189 try { 190 retval = Long.parseLong(strval); 191 } catch (NumberFormatException e) { 192 // For some properties (e.g. memory.limit_in_bytes) we may overflow 193 // the range of signed long. In this case, return unlimited 194 BigInteger b = new BigInteger(strval); 195 if (b.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { 196 return overflowRetval; 197 } 198 } 199 return retval; 200 } 201 202 }