1 /* 2 * Copyright (c) 2020, 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.lang.System.Logger; 30 import java.lang.System.Logger.Level; 31 import java.nio.file.Paths; 32 import java.util.HashMap; 33 import java.util.List; 34 import java.util.Map; 35 36 import jdk.internal.platform.cgroupv1.CgroupV1Subsystem; 37 import jdk.internal.platform.cgroupv2.CgroupV2Subsystem; 38 39 class CgroupSubsystemFactory { 40 41 private static final String CPU_CTRL = "cpu"; 42 private static final String CPUACCT_CTRL = "cpuacct"; 43 private static final String CPUSET_CTRL = "cpuset"; 44 private static final String BLKIO_CTRL = "blkio"; 45 private static final String MEMORY_CTRL = "memory"; 46 47 static CgroupMetrics create() { 48 Map<String, CgroupInfo> infos = new HashMap<>(); 49 try { 50 List<String> lines = CgroupUtil.readAllLinesPrivileged(Paths.get("/proc/cgroups")); 51 for (String line : lines) { 52 if (line.startsWith("#")) { 53 continue; 54 } 55 CgroupInfo info = CgroupInfo.fromCgroupsLine(line); 56 switch (info.getName()) { 57 case CPU_CTRL: infos.put(CPU_CTRL, info); break; 58 case CPUACCT_CTRL: infos.put(CPUACCT_CTRL, info); break; 59 case CPUSET_CTRL: infos.put(CPUSET_CTRL, info); break; 60 case MEMORY_CTRL: infos.put(MEMORY_CTRL, info); break; 61 case BLKIO_CTRL: infos.put(BLKIO_CTRL, info); break; 62 } 63 } 64 } catch (IOException e) { 65 return null; 66 } 67 68 // For cgroups v1 all controllers need to have non-zero hierarchy id 69 boolean isCgroupsV2 = true; 70 boolean anyControllersEnabled = false; 71 boolean anyCgroupsV2Controller = false; 72 boolean anyCgroupsV1Controller = false; 73 for (CgroupInfo info: infos.values()) { 74 anyCgroupsV1Controller = anyCgroupsV1Controller || info.getHierarchyId() != 0; 75 anyCgroupsV2Controller = anyCgroupsV2Controller || info.getHierarchyId() == 0; 76 isCgroupsV2 = isCgroupsV2 && info.getHierarchyId() == 0; 77 anyControllersEnabled = anyControllersEnabled || info.isEnabled(); 78 } 79 80 // If no controller is enabled, return no metrics. 81 if (!anyControllersEnabled) { 82 return null; 83 } 84 // Warn about mixed cgroups v1 and cgroups v2 controllers. The code is 85 // not ready to deal with that on a per-controller basis. Return no metrics 86 // in that case 87 if (anyCgroupsV1Controller && anyCgroupsV2Controller) { 88 Logger logger = System.getLogger("jdk.internal.platform"); 89 logger.log(Level.DEBUG, "Mixed cgroupv1 and cgroupv2 not supported. Metrics disabled."); 90 return null; 91 } 92 93 if (isCgroupsV2) { 94 CgroupSubsystem subsystem = CgroupV2Subsystem.getInstance(); 95 return subsystem != null ? new CgroupMetrics(subsystem) : null; 96 } else { 97 CgroupV1Subsystem subsystem = CgroupV1Subsystem.getInstance(); 98 return subsystem != null ? new CgroupV1MetricsImpl(subsystem) : null; 99 } 100 } 101 }