1 /*
   2  * Copyright (c) 2018, 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.nio.file.Files;
  31 import java.nio.file.Path;
  32 import java.nio.file.Paths;
  33 import java.util.ArrayList;
  34 import java.util.Optional;
  35 import java.util.stream.Stream;
  36 
  37 public class SubSystem {
  38     String root;
  39     String mountPoint;
  40     String path;
  41 
  42     public SubSystem(String root, String mountPoint) {
  43         this.root = root;
  44         this.mountPoint = mountPoint;
  45     }
  46 
  47     public void setPath(String cgroupPath) {
  48         if (root != null && cgroupPath != null) {
  49             if (root.equals("/")) {
  50                 if (cgroupPath.equals("/")) {
  51                     path = mountPoint + cgroupPath;
  52                 }
  53                 else {
  54                     path = mountPoint;
  55                 }
  56             }
  57             else {
  58                 if (root.equals(cgroupPath)) {
  59                     path = mountPoint;
  60                 }
  61                 else {
  62                     if (root.indexOf(cgroupPath) == 0) {
  63                         if (cgroupPath.length() > root.length()) {
  64                             String cgroupSubstr = cgroupPath.substring(root.length());
  65                             path = mountPoint + cgroupSubstr;
  66                         }
  67                     }
  68                 }
  69             }
  70         }
  71     }
  72 
  73     public String path() {
  74         return path;
  75     }
  76 
  77     /**
  78      * getSubSystemStringValue
  79      *
  80      * Return the first line of the file "parm" argument from the subsystem.
  81      *
  82      * TODO:  Consider using weak references for caching BufferedReader object.
  83      *
  84      * @param subsystem
  85      * @param parm
  86      * @return Returns the contents of the file specified by param.
  87      */
  88     public static String getStringValue(SubSystem subsystem, String parm) {
  89         if (subsystem == null) return null;
  90 
  91         try(BufferedReader bufferedReader = Files.newBufferedReader(Paths.get(subsystem.path(), parm))) {
  92             String line = bufferedReader.readLine();
  93             return line;
  94         }
  95         catch (IOException e) {
  96             return null;
  97         }
  98 
  99     }
 100 
 101     public static long getLongValue(SubSystem subsystem, String parm) {
 102         String strval = getStringValue(subsystem, parm);
 103 
 104         if (strval == null) return 0L;
 105 
 106         long retval = Long.parseLong(strval);
 107 
 108         return retval;
 109     }
 110 
 111     public static double getDoubleValue(SubSystem subsystem, String parm) {
 112         String strval = getStringValue(subsystem, parm);
 113 
 114         if (strval == null) return 0L;
 115 
 116         double retval = Double.parseDouble(strval);
 117 
 118         return retval;
 119     }
 120 
 121     /**
 122      * getSubSystemlongEntry
 123      *
 124      * Return the long value from the line containing the string "entryname"
 125      * within file "parm" in the "subsystem".
 126      *
 127      * TODO:  Consider using weak references for caching BufferedReader object.
 128      *
 129      * @param subsystem
 130      * @param parm
 131      * @param entryname
 132      * @return long value
 133      */
 134     public static long getLongEntry(SubSystem subsystem, String parm, String entryname) {
 135         String val = null;
 136 
 137         if (subsystem == null) return 0L;
 138 
 139         try (Stream<String> lines = Files.lines(Paths.get(subsystem.path(), parm))) {
 140 
 141             Optional<String> result = lines.map(line -> line.split(" "))
 142                                            .filter(line -> (line.length == 2 &&
 143                                                    line[0].equals(entryname)))
 144                                            .map(line -> line[1])
 145                                            .findFirst();
 146 
 147             return result.isPresent() ? Long.parseLong(result.get()) : 0L;
 148         }
 149         catch (IOException e) {
 150             return 0L;
 151         }
 152     }
 153 
 154     public static int getIntValue(SubSystem subsystem, String parm) {
 155         String val = getStringValue(subsystem, parm);
 156 
 157         if (val == null) return 0;
 158 
 159         return Integer.parseInt(val);
 160     }
 161 
 162     /**
 163      * StringRangeToIntArray
 164      *
 165      * Convert a string in the form of  1,3-4,6 to an array of
 166      * integers containing all the numbers in the range.
 167      *
 168      * @param range
 169      * @return int[] containing a sorted list of processors or memory nodes
 170      */
 171     public static int[] StringRangeToIntArray(String range) {
 172         int[] ints = new int[0];
 173 
 174         if (range == null) return ints;
 175 
 176         ArrayList<Integer> results = new ArrayList<>();
 177         String strs[] = range.split(",");
 178         for (String str : strs) {
 179             if (str.contains("-")) {
 180                 String lohi[] = str.split("-");
 181                 // validate format
 182                 if (lohi.length != 2) {
 183                     continue;
 184                 }
 185                 int lo = Integer.parseInt(lohi[0]);
 186                 int hi = Integer.parseInt(lohi[1]);
 187                 for (int i = lo; i <= hi; i++) {
 188                     results.add(i);
 189                 }
 190             }
 191             else {
 192                 results.add(Integer.parseInt(str));
 193             }
 194         }
 195 
 196         // sort results
 197         results.sort(null);
 198 
 199         // convert ArrayList to primitive int array
 200         ints = new int[results.size()];
 201         int i = 0;
 202         for (Integer n : results) {
 203             ints[i++] = n;
 204         }
 205 
 206         return ints;
 207     }
 208 }