< prev index next >

src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java

Print this page
@  rev 57734 : Review feedback
|
o  rev 57733 : 8231111: Cgroups v2: Rework Metrics in java.base so as to recognize unified hierarchy
|  Reviewed-by: bobv, mchung
~
o  rev 56862 : 8231111: Cgroups v2: Rework Metrics in java.base so as to recognize unified hierarchy
|  Reviewed-by: bobv
~
   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.IOException;
  29 import java.nio.file.Files;
  30 import java.nio.file.Path;
  31 import java.nio.file.Paths;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedActionException;
  34 import java.security.PrivilegedExceptionAction;
  35 import java.util.stream.Stream;
  36 
  37 import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem;
  38 
  39 public class Metrics implements jdk.internal.platform.Metrics {
  40     private MemorySubSystem memory;
  41     private SubSystem cpu;
  42     private SubSystem cpuacct;
  43     private SubSystem cpuset;
  44     private SubSystem blkio;



  45     private boolean activeSubSystems;
  46 
  47     // Values returned larger than this number are unlimited.
  48     static long unlimited_minimum = 0x7FFFFFFFFF000000L;
  49 
  50     private static final Metrics INSTANCE = initContainerSubSystems();
  51 
  52     private static final String PROVIDER_NAME = "cgroupv1";
  53 
  54     private Metrics() {
  55         activeSubSystems = false;
  56     }
  57 
  58     public static Metrics getInstance() {
  59         return INSTANCE;
  60     }
  61 
  62     private static Metrics initContainerSubSystems() {
  63         Metrics metrics = new Metrics();
  64 
  65         /**
  66          * Find the cgroup mount points for subsystems
  67          * by reading /proc/self/mountinfo
  68          *
  69          * Example for docker MemorySubSystem subsystem:
  70          * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/MemorySubSystem ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,MemorySubSystem
  71          *
  72          * Example for host:
  73          * 34 28 0:29 / /sys/fs/cgroup/MemorySubSystem rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,MemorySubSystem
  74          */
  75         try (Stream<String> lines =
  76              readFilePrivileged(Paths.get("/proc/self/mountinfo"))) {
  77 
  78             lines.filter(line -> line.contains(" - cgroup "))
  79                  .map(line -> line.split(" "))
  80                  .forEach(entry -> createSubSystem(metrics, entry));
  81 
  82         } catch (IOException e) {
  83             return null;
  84         }
  85 
  86         /**
  87          * Read /proc/self/cgroup and map host mount point to
  88          * local one via /proc/self/mountinfo content above
  89          *
  90          * Docker example:
  91          * 5:memory:/docker/6558aed8fc662b194323ceab5b964f69cf36b3e8af877a14b80256e93aecb044
  92          *
  93          * Host example:
  94          * 5:memory:/user.slice
  95          *
  96          * Construct a path to the process specific memory and cpuset
  97          * cgroup directory.
  98          *
  99          * For a container running under Docker from memory example above
 100          * the paths would be:
 101          *
 102          * /sys/fs/cgroup/memory
 103          *
 104          * For a Host from memory example above the path would be:
 105          *
 106          * /sys/fs/cgroup/memory/user.slice
 107          *
 108          */
 109         try (Stream<String> lines =
 110              readFilePrivileged(Paths.get("/proc/self/cgroup"))) {
 111 
 112             lines.map(line -> line.split(":"))
 113                  .filter(line -> (line.length >= 3))
 114                  .forEach(line -> setSubSystemPath(metrics, line));
 115 
 116         } catch (IOException e) {
 117             return null;
 118         }
 119 
 120         // Return Metrics object if we found any subsystems.
 121         if (metrics.activeSubSystems()) {
 122             return metrics;
 123         }
 124 
 125         return null;
 126     }
 127 
 128     static Stream<String> readFilePrivileged(Path path) throws IOException {
 129         try {
 130             PrivilegedExceptionAction<Stream<String>> pea = () -> Files.lines(path);
 131             return AccessController.doPrivileged(pea);
 132         } catch (PrivilegedActionException e) {
 133             unwrapIOExceptionAndRethrow(e);
 134             throw new InternalError(e.getCause());
 135         }
 136     }
 137 
 138     static void unwrapIOExceptionAndRethrow(PrivilegedActionException pae) throws IOException {
 139         Throwable x = pae.getCause();
 140         if (x instanceof IOException)
 141             throw (IOException) x;
 142         if (x instanceof RuntimeException)
 143             throw (RuntimeException) x;
 144         if (x instanceof Error)
 145             throw (Error) x;
 146     }
 147     /**
 148      * createSubSystem objects and initialize mount points
 149      */
 150     private static void createSubSystem(Metrics metric, String[] mountentry) {
 151         if (mountentry.length < 5) return;
 152 
 153         Path p = Paths.get(mountentry[4]);
 154         String[] subsystemNames = p.getFileName().toString().split(",");
 155 
 156         for (String subsystemName: subsystemNames) {
 157             switch (subsystemName) {
 158                 case "memory":
 159                     metric.setMemorySubSystem(new MemorySubSystem(mountentry[3], mountentry[4]));
 160                     break;
 161                 case "cpuset":
 162                     metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4]));
 163                     break;
 164                 case "cpuacct":
 165                     metric.setCpuAcctSubSystem(new SubSystem(mountentry[3], mountentry[4]));
 166                     break;
 167                 case "cpu":
 168                     metric.setCpuSubSystem(new SubSystem(mountentry[3], mountentry[4]));
 169                     break;
 170                 case "blkio":
 171                     metric.setBlkIOSubSystem(new SubSystem(mountentry[3], mountentry[4]));
 172                     break;
 173                 default:
 174                     // Ignore subsystems that we don't support
 175                     break;
 176             }
 177         }
 178     }
 179 
 180     /**
 181      * setSubSystemPath based on the contents of /proc/self/cgroup
 182      */
 183     private static void setSubSystemPath(Metrics metric, String[] entry) {
 184         String controller;
 185         String base;
 186         SubSystem subsystem = null;
 187         SubSystem subsystem2 = null;
 188 
 189         controller = entry[1];
 190         base = entry[2];
 191         if (controller != null && base != null) {
 192             switch (controller) {
 193                 case "memory":
 194                     subsystem = metric.MemorySubSystem();
 195                     break;
 196                 case "cpuset":
 197                     subsystem = metric.CpuSetSubSystem();
 198                     break;
 199                 case "cpu,cpuacct":
 200                 case "cpuacct,cpu":
 201                     subsystem = metric.CpuSubSystem();
 202                     subsystem2 = metric.CpuAcctSubSystem();
 203                     break;
 204                 case "cpuacct":
 205                     subsystem = metric.CpuAcctSubSystem();
 206                     break;
 207                 case "cpu":
 208                     subsystem = metric.CpuSubSystem();
 209                     break;
 210                 case "blkio":
 211                     subsystem = metric.BlkIOSubSystem();
 212                     break;
 213                 // Ignore subsystems that we don't support
 214                 default:
 215                     break;
 216             }
 217         }
 218 
 219         if (subsystem != null) {
 220             subsystem.setPath(base);
 221             if (subsystem instanceof MemorySubSystem) {
 222                 MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem;
 223                 boolean isHierarchial = getHierarchical(memorySubSystem);
 224                 memorySubSystem.setHierarchical(isHierarchial);
 225             }
 226             metric.setActiveSubSystems();
 227         }
 228         if (subsystem2 != null) {
 229             subsystem2.setPath(base);
 230         }
 231     }
 232 
 233 
 234     private static boolean getHierarchical(MemorySubSystem subsystem) {
 235         long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy");
 236         return hierarchical > 0;
 237     }
 238 
 239     private void setActiveSubSystems() {
 240         activeSubSystems = true;
 241     }
 242 
 243     private boolean activeSubSystems() {
 244         return activeSubSystems;
 245     }
 246 
 247     private void setMemorySubSystem(MemorySubSystem memory) {
 248         this.memory = memory;
 249     }
 250 
 251     private void setCpuSubSystem(SubSystem cpu) {
 252         this.cpu = cpu;
 253     }
 254 
 255     private void setCpuAcctSubSystem(SubSystem cpuacct) {
 256         this.cpuacct = cpuacct;
 257     }
 258 
 259     private void setCpuSetSubSystem(SubSystem cpuset) {
 260         this.cpuset = cpuset;
 261     }
 262 
 263     private void setBlkIOSubSystem(SubSystem blkio) {
 264         this.blkio = blkio;
 265     }
 266 
 267     private SubSystem MemorySubSystem() {
 268         return memory;
 269     }
 270 
 271     private SubSystem CpuSubSystem() {
 272         return cpu;
 273     }
 274 
 275     private SubSystem CpuAcctSubSystem() {
 276         return cpuacct;
 277     }
 278 
 279     private SubSystem CpuSetSubSystem() {
 280         return cpuset;
 281     }
 282 
 283     private SubSystem BlkIOSubSystem() {
 284         return blkio;
 285     }
 286 







 287     public String getProvider() {
 288         return PROVIDER_NAME;
 289     }
 290 
 291     /*****************************************************************
 292      * CPU Accounting Subsystem
 293      ****************************************************************/
 294 
 295 
 296     public long getCpuUsage() {
 297         return SubSystem.getLongValue(cpuacct, "cpuacct.usage");
 298     }
 299 
 300     public long[] getPerCpuUsage() {
 301         String usagelist = SubSystem.getStringValue(cpuacct, "cpuacct.usage_percpu");
 302         if (usagelist == null) {
 303             return new long[0];
 304         }
 305 
 306         String list[] = usagelist.split(" ");
 307         long percpu[] = new long[list.length];
 308         for (int i = 0; i < list.length; i++) {
 309             percpu[i] = Long.parseLong(list[i]);
 310         }
 311         return percpu;
 312     }
 313 
 314     public long getCpuUserUsage() {
 315         return SubSystem.getLongEntry(cpuacct, "cpuacct.stat", "user");
 316     }
 317 
 318     public long getCpuSystemUsage() {
 319         return SubSystem.getLongEntry(cpuacct, "cpuacct.stat", "system");
 320     }
 321 
 322 
 323     /*****************************************************************
 324      * CPU Subsystem
 325      ****************************************************************/
 326 
 327 
 328     public long getCpuPeriod() {
 329         return SubSystem.getLongValue(cpu, "cpu.cfs_period_us");
 330     }
 331 
 332     public long getCpuQuota() {
 333         return SubSystem.getLongValue(cpu, "cpu.cfs_quota_us");
 334     }
 335 
 336     public long getCpuShares() {
 337         long retval = SubSystem.getLongValue(cpu, "cpu.shares");
 338         if (retval == 0 || retval == 1024)
 339             return -1;
 340         else
 341             return retval;
 342     }
 343 
 344     public long getCpuNumPeriods() {
 345         return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_periods");
 346     }
 347 
 348     public long getCpuNumThrottled() {
 349         return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_throttled");
 350     }
 351 
 352     public long getCpuThrottledTime() {
 353         return SubSystem.getLongEntry(cpu, "cpu.stat", "throttled_time");
 354     }
 355 
 356     public long getEffectiveCpuCount() {
 357         return Runtime.getRuntime().availableProcessors();
 358     }
 359 
 360 
 361     /*****************************************************************
 362      * CPUSet Subsystem
 363      ****************************************************************/
 364 
 365     public int[] getCpuSetCpus() {
 366         return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.cpus"));
 367     }
 368 
 369     public int[] getEffectiveCpuSetCpus() {
 370         return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.effective_cpus"));
 371     }
 372 
 373     public int[] getCpuSetMems() {
 374         return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.mems"));
 375     }
 376 
 377     public int[] getEffectiveCpuSetMems() {
 378         return SubSystem.StringRangeToIntArray(SubSystem.getStringValue(cpuset, "cpuset.effective_mems"));
 379     }
 380 
 381     public double getCpuSetMemoryPressure() {
 382         return SubSystem.getDoubleValue(cpuset, "cpuset.memory_pressure");
 383     }
 384 
 385     public boolean isCpuSetMemoryPressureEnabled() {
 386         long val = SubSystem.getLongValue(cpuset, "cpuset.memory_pressure_enabled");
 387         return (val == 1);
 388     }
 389 
 390 
 391     /*****************************************************************
 392      * Memory Subsystem
 393      ****************************************************************/
 394 
 395 
 396     public long getMemoryFailCount() {
 397         return SubSystem.getLongValue(memory, "memory.failcnt");
 398     }
 399 
 400     public long getMemoryLimit() {
 401         long retval = SubSystem.getLongValue(memory, "memory.limit_in_bytes");
 402         if (retval > unlimited_minimum) {
 403             if (memory.isHierarchical()) {
 404                 // memory.limit_in_bytes returned unlimited, attempt
 405                 // hierarchical memory limit
 406                 String match = "hierarchical_memory_limit";
 407                 retval = SubSystem.getLongValueMatchingLine(memory,
 408                                                             "memory.stat",
 409                                                             match,
 410                                                             Metrics::convertHierachicalLimitLine);
 411             }
 412         }
 413         return retval > unlimited_minimum ? -1L : retval;
 414     }
 415 
 416     public static long convertHierachicalLimitLine(String line) {
 417         String[] tokens = line.split("\\s");
 418         if (tokens.length == 2) {
 419             String strVal = tokens[1];
 420             return SubSystem.convertStringToLong(strVal);
 421         }
 422         return unlimited_minimum + 1; // unlimited
 423     }
 424 
 425     public long getMemoryMaxUsage() {
 426         return SubSystem.getLongValue(memory, "memory.max_usage_in_bytes");
 427     }
 428 
 429     public long getMemoryUsage() {
 430         return SubSystem.getLongValue(memory, "memory.usage_in_bytes");
 431     }
 432 
 433     public long getKernelMemoryFailCount() {
 434         return SubSystem.getLongValue(memory, "memory.kmem.failcnt");
 435     }
 436 
 437     public long getKernelMemoryLimit() {
 438         long retval = SubSystem.getLongValue(memory, "memory.kmem.limit_in_bytes");
 439         return retval > unlimited_minimum ? -1L : retval;
 440     }
 441 
 442     public long getKernelMemoryMaxUsage() {
 443         return SubSystem.getLongValue(memory, "memory.kmem.max_usage_in_bytes");
 444     }
 445 
 446     public long getKernelMemoryUsage() {
 447         return SubSystem.getLongValue(memory, "memory.kmem.usage_in_bytes");
 448     }
 449 
 450     public long getTcpMemoryFailCount() {
 451         return SubSystem.getLongValue(memory, "memory.kmem.tcp.failcnt");
 452     }
 453 
 454     public long getTcpMemoryLimit() {
 455         long retval =  SubSystem.getLongValue(memory, "memory.kmem.tcp.limit_in_bytes");
 456         return retval > unlimited_minimum ? -1L : retval;
 457     }
 458 
 459     public long getTcpMemoryMaxUsage() {
 460         return SubSystem.getLongValue(memory, "memory.kmem.tcp.max_usage_in_bytes");
 461     }
 462 
 463     public long getTcpMemoryUsage() {
 464         return SubSystem.getLongValue(memory, "memory.kmem.tcp.usage_in_bytes");
 465     }
 466 
 467     public long getMemoryAndSwapFailCount() {
 468         return SubSystem.getLongValue(memory, "memory.memsw.failcnt");
 469     }
 470 
 471     public long getMemoryAndSwapLimit() {
 472         long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes");
 473         if (retval > unlimited_minimum) {
 474             if (memory.isHierarchical()) {
 475                 // memory.memsw.limit_in_bytes returned unlimited, attempt
 476                 // hierarchical memory limit
 477                 String match = "hierarchical_memsw_limit";
 478                 retval = SubSystem.getLongValueMatchingLine(memory,
 479                                                             "memory.stat",
 480                                                             match,
 481                                                             Metrics::convertHierachicalLimitLine);
 482             }
 483         }
 484         return retval > unlimited_minimum ? -1L : retval;
 485     }
 486 
 487     public long getMemoryAndSwapMaxUsage() {
 488         return SubSystem.getLongValue(memory, "memory.memsw.max_usage_in_bytes");
 489     }
 490 
 491     public long getMemoryAndSwapUsage() {
 492         return SubSystem.getLongValue(memory, "memory.memsw.usage_in_bytes");
 493     }
 494 
 495     public boolean isMemoryOOMKillEnabled() {
 496         long val = SubSystem.getLongEntry(memory, "memory.oom_control", "oom_kill_disable");
 497         return (val == 0);
 498     }
 499 
 500     public long getMemorySoftLimit() {
 501         long retval = SubSystem.getLongValue(memory, "memory.soft_limit_in_bytes");
 502         return retval > unlimited_minimum ? -1L : retval;
 503     }
 504 
 505 
 506     /*****************************************************************
 507      * BlKIO Subsystem
 508      ****************************************************************/
 509 
 510 
 511     public long getBlkIOServiceCount() {
 512         return SubSystem.getLongEntry(blkio, "blkio.throttle.io_service_bytes", "Total");
 513     }
 514 
 515     public long getBlkIOServiced() {
 516         return SubSystem.getLongEntry(blkio, "blkio.throttle.io_serviced", "Total");
 517     }
 518 
 519 }
   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 java.io.IOException;

  29 import java.nio.file.Path;
  30 import java.nio.file.Paths;



  31 import java.util.stream.Stream;
  32 
  33 import jdk.internal.platform.CgroupSubsystem;
  34 import jdk.internal.platform.CgroupSubsystemController;
  35 import jdk.internal.platform.CgroupUtil;
  36 import jdk.internal.platform.MetricsCgroupV1;
  37 
  38 public class CgroupV1Subsystem implements CgroupSubsystem, MetricsCgroupV1 {
  39     private CgroupV1MemorySubSystemController memory;
  40     private CgroupV1SubsystemController cpu;
  41     private CgroupV1SubsystemController cpuacct;
  42     private CgroupV1SubsystemController cpuset;
  43     private CgroupV1SubsystemController blkio;
  44     private boolean activeSubSystems;
  45 
  46     private static final CgroupV1Subsystem INSTANCE = initSubSystem();



  47 
  48     private static final String PROVIDER_NAME = "cgroupv1";
  49 
  50     private CgroupV1Subsystem() {
  51         activeSubSystems = false;
  52     }
  53 
  54     public static CgroupV1Subsystem getInstance() {
  55         return INSTANCE;
  56     }
  57 
  58     private static CgroupV1Subsystem initSubSystem() {
  59         CgroupV1Subsystem subsystem = new CgroupV1Subsystem();
  60 
  61         /**
  62          * Find the cgroup mount points for subsystems
  63          * by reading /proc/self/mountinfo
  64          *
  65          * Example for docker MemorySubSystem subsystem:
  66          * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/MemorySubSystem ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,MemorySubSystem
  67          *
  68          * Example for host:
  69          * 34 28 0:29 / /sys/fs/cgroup/MemorySubSystem rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,MemorySubSystem
  70          */
  71         try (Stream<String> lines =
  72                 CgroupUtil.readFilePrivileged(Paths.get("/proc/self/mountinfo"))) {
  73 
  74             lines.filter(line -> line.contains(" - cgroup "))
  75                  .map(line -> line.split(" "))
  76                  .forEach(entry -> createSubSystemController(subsystem, entry));
  77 
  78         } catch (IOException e) {
  79             return null;
  80         }
  81 
  82         /**
  83          * Read /proc/self/cgroup and map host mount point to
  84          * local one via /proc/self/mountinfo content above
  85          *
  86          * Docker example:
  87          * 5:memory:/docker/6558aed8fc662b194323ceab5b964f69cf36b3e8af877a14b80256e93aecb044
  88          *
  89          * Host example:
  90          * 5:memory:/user.slice
  91          *
  92          * Construct a path to the process specific memory and cpuset
  93          * cgroup directory.
  94          *
  95          * For a container running under Docker from memory example above
  96          * the paths would be:
  97          *
  98          * /sys/fs/cgroup/memory
  99          *
 100          * For a Host from memory example above the path would be:
 101          *
 102          * /sys/fs/cgroup/memory/user.slice
 103          *
 104          */
 105         try (Stream<String> lines =
 106                 CgroupUtil.readFilePrivileged(Paths.get("/proc/self/cgroup"))) {
 107 
 108             lines.map(line -> line.split(":"))
 109                  .filter(line -> (line.length >= 3))
 110                  .forEach(line -> setSubSystemControllerPath(subsystem, line));
 111 
 112         } catch (IOException e) {
 113             return null;
 114         }
 115 
 116         // Return Metrics object if we found any subsystems.
 117         if (subsystem.activeSubSystems()) {
 118             return subsystem;
 119         }
 120 
 121         return null;
 122     }
 123 



















 124     /**
 125      * createSubSystem objects and initialize mount points
 126      */
 127     private static void createSubSystemController(CgroupV1Subsystem subsystem, String[] mountentry) {
 128         if (mountentry.length < 5) return;
 129 
 130         Path p = Paths.get(mountentry[4]);
 131         String[] subsystemNames = p.getFileName().toString().split(",");
 132 
 133         for (String subsystemName: subsystemNames) {
 134             switch (subsystemName) {
 135                 case "memory":
 136                     subsystem.setMemorySubSystem(new CgroupV1MemorySubSystemController(mountentry[3], mountentry[4]));
 137                     break;
 138                 case "cpuset":
 139                     subsystem.setCpuSetController(new CgroupV1SubsystemController(mountentry[3], mountentry[4]));
 140                     break;
 141                 case "cpuacct":
 142                     subsystem.setCpuAcctController(new CgroupV1SubsystemController(mountentry[3], mountentry[4]));
 143                     break;
 144                 case "cpu":
 145                     subsystem.setCpuController(new CgroupV1SubsystemController(mountentry[3], mountentry[4]));
 146                     break;
 147                 case "blkio":
 148                     subsystem.setBlkIOController(new CgroupV1SubsystemController(mountentry[3], mountentry[4]));
 149                     break;
 150                 default:
 151                     // Ignore subsystems that we don't support
 152                     break;
 153             }
 154         }
 155     }
 156 
 157     /**
 158      * setSubSystemPath based on the contents of /proc/self/cgroup
 159      */
 160     private static void setSubSystemControllerPath(CgroupV1Subsystem subsystem, String[] entry) {
 161         String controllerName;
 162         String base;
 163         CgroupV1SubsystemController controller = null;
 164         CgroupV1SubsystemController controller2 = null;
 165 
 166         controllerName = entry[1];
 167         base = entry[2];
 168         if (controllerName != null && base != null) {
 169             switch (controllerName) {
 170                 case "memory":
 171                     controller = subsystem.memoryController();
 172                     break;
 173                 case "cpuset":
 174                     controller = subsystem.cpuSetController();
 175                     break;
 176                 case "cpu,cpuacct":
 177                 case "cpuacct,cpu":
 178                     controller = subsystem.cpuController();
 179                     controller2 = subsystem.cpuAcctController();
 180                     break;
 181                 case "cpuacct":
 182                     controller = subsystem.cpuAcctController();
 183                     break;
 184                 case "cpu":
 185                     controller = subsystem.cpuController();
 186                     break;
 187                 case "blkio":
 188                     controller = subsystem.blkIOController();
 189                     break;
 190                 // Ignore subsystems that we don't support
 191                 default:
 192                     break;
 193             }
 194         }
 195 
 196         if (controller != null) {
 197             controller.setPath(base);
 198             if (controller instanceof CgroupV1MemorySubSystemController) {
 199                 CgroupV1MemorySubSystemController memorySubSystem = (CgroupV1MemorySubSystemController)controller;
 200                 boolean isHierarchial = getHierarchical(memorySubSystem);
 201                 memorySubSystem.setHierarchical(isHierarchial);
 202             }
 203             subsystem.setActiveSubSystems();
 204         }
 205         if (controller2 != null) {
 206             controller2.setPath(base);
 207         }
 208     }
 209 
 210 
 211     private static boolean getHierarchical(CgroupV1MemorySubSystemController controller) {
 212         long hierarchical = getLongValue(controller, "memory.use_hierarchy");
 213         return hierarchical > 0;
 214     }
 215 
 216     private void setActiveSubSystems() {
 217         activeSubSystems = true;
 218     }
 219 
 220     private boolean activeSubSystems() {
 221         return activeSubSystems;
 222     }
 223 
 224     private void setMemorySubSystem(CgroupV1MemorySubSystemController memory) {
 225         this.memory = memory;
 226     }
 227 
 228     private void setCpuController(CgroupV1SubsystemController cpu) {
 229         this.cpu = cpu;
 230     }
 231 
 232     private void setCpuAcctController(CgroupV1SubsystemController cpuacct) {
 233         this.cpuacct = cpuacct;
 234     }
 235 
 236     private void setCpuSetController(CgroupV1SubsystemController cpuset) {
 237         this.cpuset = cpuset;
 238     }
 239 
 240     private void setBlkIOController(CgroupV1SubsystemController blkio) {
 241         this.blkio = blkio;
 242     }
 243 
 244     private CgroupV1SubsystemController memoryController() {
 245         return memory;
 246     }
 247 
 248     private CgroupV1SubsystemController cpuController() {
 249         return cpu;
 250     }
 251 
 252     private CgroupV1SubsystemController cpuAcctController() {
 253         return cpuacct;
 254     }
 255 
 256     private CgroupV1SubsystemController cpuSetController() {
 257         return cpuset;
 258     }
 259 
 260     private CgroupV1SubsystemController blkIOController() {
 261         return blkio;
 262     }
 263 
 264     private static long getLongValue(CgroupSubsystemController controller,
 265                               String parm) {
 266         return CgroupSubsystemController.getLongValue(controller,
 267                                                       parm,
 268                                                       CgroupV1SubsystemController::convertStringToLong);
 269     }
 270 
 271     public String getProvider() {
 272         return PROVIDER_NAME;
 273     }
 274 
 275     /*****************************************************************
 276      * CPU Accounting Subsystem
 277      ****************************************************************/
 278 
 279 
 280     public long getCpuUsage() {
 281         return getLongValue(cpuacct, "cpuacct.usage");
 282     }
 283 
 284     public long[] getPerCpuUsage() {
 285         String usagelist = CgroupSubsystemController.getStringValue(cpuacct, "cpuacct.usage_percpu");
 286         if (usagelist == null) {
 287             return null;
 288         }
 289 
 290         String list[] = usagelist.split(" ");
 291         long percpu[] = new long[list.length];
 292         for (int i = 0; i < list.length; i++) {
 293             percpu[i] = Long.parseLong(list[i]);
 294         }
 295         return percpu;
 296     }
 297 
 298     public long getCpuUserUsage() {
 299         return CgroupSubsystemController.getLongEntry(cpuacct, "cpuacct.stat", "user");
 300     }
 301 
 302     public long getCpuSystemUsage() {
 303         return CgroupSubsystemController.getLongEntry(cpuacct, "cpuacct.stat", "system");
 304     }
 305 
 306 
 307     /*****************************************************************
 308      * CPU Subsystem
 309      ****************************************************************/
 310 
 311 
 312     public long getCpuPeriod() {
 313         return getLongValue(cpu, "cpu.cfs_period_us");
 314     }
 315 
 316     public long getCpuQuota() {
 317         return getLongValue(cpu, "cpu.cfs_quota_us");
 318     }
 319 
 320     public long getCpuShares() {
 321         long retval = getLongValue(cpu, "cpu.shares");
 322         if (retval == 0 || retval == 1024)
 323             return CgroupSubsystem.LONG_RETVAL_UNLIMITED;
 324         else
 325             return retval;
 326     }
 327 
 328     public long getCpuNumPeriods() {
 329         return CgroupSubsystemController.getLongEntry(cpu, "cpu.stat", "nr_periods");
 330     }
 331 
 332     public long getCpuNumThrottled() {
 333         return CgroupSubsystemController.getLongEntry(cpu, "cpu.stat", "nr_throttled");
 334     }
 335 
 336     public long getCpuThrottledTime() {
 337         return CgroupSubsystemController.getLongEntry(cpu, "cpu.stat", "throttled_time");
 338     }
 339 
 340     public long getEffectiveCpuCount() {
 341         return Runtime.getRuntime().availableProcessors();
 342     }
 343 
 344 
 345     /*****************************************************************
 346      * CPUSet Subsystem
 347      ****************************************************************/
 348 
 349     public int[] getCpuSetCpus() {
 350         return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.cpus"));
 351     }
 352 
 353     public int[] getEffectiveCpuSetCpus() {
 354         return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.effective_cpus"));
 355     }
 356 
 357     public int[] getCpuSetMems() {
 358         return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.mems"));
 359     }
 360 
 361     public int[] getEffectiveCpuSetMems() {
 362         return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(cpuset, "cpuset.effective_mems"));
 363     }
 364 
 365     public double getCpuSetMemoryPressure() {
 366         return CgroupSubsystemController.getDoubleValue(cpuset, "cpuset.memory_pressure");
 367     }
 368 
 369     public Boolean isCpuSetMemoryPressureEnabled() {
 370         long val = getLongValue(cpuset, "cpuset.memory_pressure_enabled");
 371         return (val == 1);
 372     }
 373 
 374 
 375     /*****************************************************************
 376      * Memory Subsystem
 377      ****************************************************************/
 378 
 379 
 380     public long getMemoryFailCount() {
 381         return getLongValue(memory, "memory.failcnt");
 382     }
 383 
 384     public long getMemoryLimit() {
 385         long retval = getLongValue(memory, "memory.limit_in_bytes");
 386         if (retval > CgroupV1SubsystemController.UNLIMITED_MIN) {
 387             if (memory.isHierarchical()) {
 388                 // memory.limit_in_bytes returned unlimited, attempt
 389                 // hierarchical memory limit
 390                 String match = "hierarchical_memory_limit";
 391                 retval = CgroupSubsystemController.getLongValueMatchingLine(memory,
 392                                                             "memory.stat",
 393                                                             match,
 394                                                             CgroupV1Subsystem::convertHierachicalLimitLine);
 395             }
 396         }
 397         return CgroupV1SubsystemController.longValOrUnlimited(retval);
 398     }
 399 
 400     public static long convertHierachicalLimitLine(String line) {
 401         String[] tokens = line.split("\\s");
 402         if (tokens.length == 2) {
 403             String strVal = tokens[1];
 404             return CgroupV1SubsystemController.convertStringToLong(strVal);
 405         }
 406         return CgroupV1SubsystemController.UNLIMITED_MIN + 1; // unlimited
 407     }
 408 
 409     public long getMemoryMaxUsage() {
 410         return getLongValue(memory, "memory.max_usage_in_bytes");
 411     }
 412 
 413     public long getMemoryUsage() {
 414         return getLongValue(memory, "memory.usage_in_bytes");
 415     }
 416 
 417     public long getKernelMemoryFailCount() {
 418         return getLongValue(memory, "memory.kmem.failcnt");
 419     }
 420 
 421     public long getKernelMemoryLimit() {
 422         return CgroupV1SubsystemController.longValOrUnlimited(getLongValue(memory, "memory.kmem.limit_in_bytes"));

 423     }
 424 
 425     public long getKernelMemoryMaxUsage() {
 426         return getLongValue(memory, "memory.kmem.max_usage_in_bytes");
 427     }
 428 
 429     public long getKernelMemoryUsage() {
 430         return getLongValue(memory, "memory.kmem.usage_in_bytes");
 431     }
 432 
 433     public long getTcpMemoryFailCount() {
 434         return getLongValue(memory, "memory.kmem.tcp.failcnt");
 435     }
 436 
 437     public long getTcpMemoryLimit() {
 438         return CgroupV1SubsystemController.longValOrUnlimited(getLongValue(memory, "memory.kmem.tcp.limit_in_bytes"));

 439     }
 440 
 441     public long getTcpMemoryMaxUsage() {
 442         return getLongValue(memory, "memory.kmem.tcp.max_usage_in_bytes");
 443     }
 444 
 445     public long getTcpMemoryUsage() {
 446         return getLongValue(memory, "memory.kmem.tcp.usage_in_bytes");
 447     }
 448 
 449     public long getMemoryAndSwapFailCount() {
 450         return getLongValue(memory, "memory.memsw.failcnt");
 451     }
 452 
 453     public long getMemoryAndSwapLimit() {
 454         long retval = getLongValue(memory, "memory.memsw.limit_in_bytes");
 455         if (retval > CgroupV1SubsystemController.UNLIMITED_MIN) {
 456             if (memory.isHierarchical()) {
 457                 // memory.memsw.limit_in_bytes returned unlimited, attempt
 458                 // hierarchical memory limit
 459                 String match = "hierarchical_memsw_limit";
 460                 retval = CgroupSubsystemController.getLongValueMatchingLine(memory,
 461                                                             "memory.stat",
 462                                                             match,
 463                                                             CgroupV1Subsystem::convertHierachicalLimitLine);
 464             }
 465         }
 466         return CgroupV1SubsystemController.longValOrUnlimited(retval);
 467     }
 468 
 469     public long getMemoryAndSwapMaxUsage() {
 470         return getLongValue(memory, "memory.memsw.max_usage_in_bytes");
 471     }
 472 
 473     public long getMemoryAndSwapUsage() {
 474         return getLongValue(memory, "memory.memsw.usage_in_bytes");
 475     }
 476 
 477     public Boolean isMemoryOOMKillEnabled() {
 478         long val = CgroupSubsystemController.getLongEntry(memory, "memory.oom_control", "oom_kill_disable");
 479         return (val == 0);
 480     }
 481 
 482     public long getMemorySoftLimit() {
 483         return CgroupV1SubsystemController.longValOrUnlimited(getLongValue(memory, "memory.soft_limit_in_bytes"));

 484     }
 485 
 486 
 487     /*****************************************************************
 488      * BlKIO Subsystem
 489      ****************************************************************/
 490 
 491 
 492     public long getBlkIOServiceCount() {
 493         return CgroupSubsystemController.getLongEntry(blkio, "blkio.throttle.io_service_bytes", "Total");
 494     }
 495 
 496     public long getBlkIOServiced() {
 497         return CgroupSubsystemController.getLongEntry(blkio, "blkio.throttle.io_serviced", "Total");
 498     }
 499 
 500 }
< prev index next >