1 /* 2 * Copyright (c) 2017, 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.jfr.internal; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.Objects; 31 32 import jdk.jfr.SettingDescriptor; 33 34 /** 35 * Implementation of event type. 36 * 37 * To avoid memory leaks, this class must not hold strong reference to an event 38 * class or a setting class 39 */ 40 public final class PlatformEventType extends Type { 41 private final boolean isJVM; 42 private final boolean isJDK; 43 private final boolean isMethodSampling; 44 private final List<SettingDescriptor> settings = new ArrayList<>(5); 45 private final boolean dynamicSettings; 46 private final int stackTraceOffset; 47 48 // default values 49 private boolean enabled = false; 50 private boolean stackTraceEnabled = true; 51 private long thresholdTicks = 0; 52 private long period = 0; 53 private boolean hasHook; 54 55 private boolean beginChunk; 56 private boolean endChunk; 57 private boolean hasStackTrace = true; 58 private boolean hasDuration = true; 59 private boolean hasPeriod = true; 60 private boolean hasCutoff = false; 61 private boolean isInstrumented; 62 private boolean markForInstrumentation; 63 private boolean registered = true; 64 private boolean commitable = enabled && registered; 65 66 67 // package private 68 PlatformEventType(String name, long id, boolean isJDK, boolean dynamicSettings) { 69 super(name, Type.SUPER_TYPE_EVENT, id); 70 this.dynamicSettings = dynamicSettings; 71 this.isJVM = Type.isDefinedByJVM(id); 72 this.isMethodSampling = name.equals(Type.ORACLE_EVENT_PREFIX + "ExecutionSample") || name.equals(Type.ORACLE_EVENT_PREFIX + "NativeMethodSample"); 73 this.isJDK = isJDK; 74 this.stackTraceOffset = stackTraceOffset(name, isJDK); 75 } 76 77 private static int stackTraceOffset(String name, boolean isJDK) { 78 if (isJDK) { 79 if (name.equals(Type.ORACLE_EVENT_PREFIX + "JavaExceptionThrow")) { 80 return 5; 81 } 82 if (name.equals(Type.ORACLE_EVENT_PREFIX + "JavaErrorThrow")) { 83 return 5; 84 } 85 } 86 return 4; 87 } 88 89 public void add(SettingDescriptor settingDescriptor) { 90 Objects.requireNonNull(settingDescriptor); 91 settings.add(settingDescriptor); 92 } 93 94 public List<SettingDescriptor> getSettings() { 95 if (dynamicSettings) { 96 List<SettingDescriptor> list = new ArrayList<>(settings.size()); 97 for (SettingDescriptor s : settings) { 98 if (Utils.isSettingVisible(s.getTypeId(), hasHook)) { 99 list.add(s); 100 } 101 } 102 return list; 103 } 104 return settings; 105 } 106 107 public List<SettingDescriptor> getAllSettings() { 108 return settings; 109 } 110 111 public void setHasStackTrace(boolean hasStackTrace) { 112 this.hasStackTrace = hasStackTrace; 113 } 114 115 public void setHasDuration(boolean hasDuration) { 116 this.hasDuration = hasDuration; 117 } 118 119 public void setHasCutoff(boolean hasCutoff) { 120 this.hasCutoff = hasCutoff; 121 } 122 123 public void setCutoff(long cutoffNanos) { 124 if (isJVM) { 125 long cutoffTicks = Utils.nanosToTicks(cutoffNanos); 126 JVM.getJVM().setCutoff(getId(), cutoffTicks); 127 } 128 } 129 130 public void setHasPeriod(boolean hasPeriod) { 131 this.hasPeriod = hasPeriod; 132 } 133 134 public boolean hasStackTrace() { 135 return this.hasStackTrace; 136 } 137 138 public boolean hasDuration() { 139 return this.hasDuration; 140 } 141 142 public boolean hasPeriod() { 143 return this.hasPeriod; 144 } 145 146 public boolean hasCutoff() { 147 return this.hasCutoff; 148 } 149 150 public boolean isEnabled() { 151 return enabled; 152 } 153 154 public boolean isJVM() { 155 return isJVM; 156 } 157 158 public boolean isJDK() { 159 return isJDK; 160 } 161 162 public void setEnabled(boolean enabled) { 163 this.enabled = enabled; 164 updateCommitable(); 165 if (isJVM) { 166 if (isMethodSampling) { 167 long p = enabled ? period : 0; 168 JVM.getJVM().setMethodSamplingInterval(getId(), p); 169 } else { 170 JVM.getJVM().setEnabled(getId(), enabled); 171 } 172 } 173 } 174 175 public void setPeriod(long periodMillis, boolean beginChunk, boolean endChunk) { 176 if (isMethodSampling) { 177 long p = enabled ? periodMillis : 0; 178 JVM.getJVM().setMethodSamplingInterval(getId(), p); 179 } 180 this.beginChunk = beginChunk; 181 this.endChunk = endChunk; 182 this.period = periodMillis; 183 } 184 185 public void setStackTraceEnabled(boolean stackTraceEnabled) { 186 this.stackTraceEnabled = stackTraceEnabled; 187 if (isJVM) { 188 JVM.getJVM().setStackTraceEnabled(getId(), stackTraceEnabled); 189 } 190 } 191 192 public void setThreshold(long thresholdNanos) { 193 this.thresholdTicks = Utils.nanosToTicks(thresholdNanos); 194 if (isJVM) { 195 JVM.getJVM().setThreshold(getId(), thresholdTicks); 196 } 197 } 198 199 public boolean isEveryChunk() { 200 return period == 0; 201 } 202 203 public boolean getStackTraceEnabled() { 204 return stackTraceEnabled; 205 } 206 207 public long getThresholdTicks() { 208 return thresholdTicks; 209 } 210 211 public long getPeriod() { 212 return period; 213 } 214 215 public boolean hasEventHook() { 216 return hasHook; 217 } 218 219 public void setEventHook(boolean hasHook) { 220 this.hasHook = hasHook; 221 } 222 223 public boolean isBeginChunk() { 224 return beginChunk; 225 } 226 227 public boolean isEndChunk() { 228 return endChunk; 229 } 230 231 public boolean isInstrumented() { 232 return isInstrumented; 233 } 234 235 public void setInstrumented() { 236 isInstrumented = true; 237 } 238 239 public void markForInstrumentation(boolean markForInstrumentation) { 240 this.markForInstrumentation = markForInstrumentation; 241 } 242 243 public boolean isMarkedForInstrumentation() { 244 return markForInstrumentation; 245 } 246 247 public boolean setRegistered(boolean registered) { 248 if (this.registered != registered) { 249 this.registered = registered; 250 updateCommitable(); 251 LogTag logTag = isJVM() || isJDK() ? LogTag.JFR_SYSTEM_EVENT : LogTag.JFR_EVENT; 252 if (registered) { 253 Logger.log(logTag, LogLevel.INFO, "Registered " + getLogName()); 254 } else { 255 Logger.log(logTag, LogLevel.INFO, "Unregistered " + getLogName()); 256 } 257 if (!registered) { 258 MetadataRepository.getInstance().setUnregistered(); 259 } 260 return true; 261 } 262 return false; 263 } 264 265 private void updateCommitable() { 266 this.commitable = enabled && registered; 267 } 268 269 public final boolean isRegistered() { 270 return registered; 271 } 272 273 // Efficient check of enabled && registered 274 public boolean isCommitable() { 275 return commitable; 276 } 277 278 public int getStackTraceOffset() { 279 return stackTraceOffset; 280 } 281 }