1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * ident "%Z%%M% %I% %E% SMI" 27 */ 28 package org.opensolaris.os.dtrace; 29 30 import java.util.*; 31 import java.io.*; 32 import java.beans.*; 33 34 /** 35 * An error encountered in the native DTrace library while tracing probe 36 * data. Each of the fault name constants beginning with {@code 37 * DTRACEFLT_} identifies a specific fault with a name that is 38 * guaranteed not to change across API versions. 39 * <p> 40 * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. 41 * 42 * @see ConsumerListener#errorEncountered(ErrorEvent e) 43 * 44 * @author Tom Erickson 45 */ 46 public final class Error implements Serializable { 47 static final long serialVersionUID = 5069931629562700614L; 48 49 /** 50 * Invalid address. 51 */ 52 public static final String DTRACEFLT_BADADDR = "DTRACEFLT_BADADDR"; 53 /** 54 * Invalid alignment. 55 */ 56 public static final String DTRACEFLT_BADALIGN = "DTRACEFLT_BADALIGN"; 57 /** 58 * Illegal operation. 59 */ 60 public static final String DTRACEFLT_ILLOP = "DTRACEFLT_ILLOP"; 61 /** 62 * Divide-by-zero. 63 */ 64 public static final String DTRACEFLT_DIVZERO = "DTRACEFLT_DIVZERO"; 65 /** 66 * Out of scratch space. 67 */ 68 public static final String DTRACEFLT_NOSCRATCH = "DTRACEFLT_NOSCRATCH"; 69 /** 70 * Invalid kernel access. 71 */ 72 public static final String DTRACEFLT_KPRIV = "DTRACEFLT_KPRIV"; 73 /** 74 * Invalid user access. 75 */ 76 public static final String DTRACEFLT_UPRIV = "DTRACEFLT_UPRIV"; 77 /** 78 * Tuple stack overflow. 79 */ 80 public static final String DTRACEFLT_TUPOFLOW = "DTRACEFLT_TUPOFLOW"; 81 /** 82 * Library-level fault. 83 */ 84 public static final String DTRACEFLT_LIBRARY = "DTRACEFLT_LIBRARY"; 85 86 static { 87 try { 88 BeanInfo info = Introspector.getBeanInfo(Error.class); 89 PersistenceDelegate persistenceDelegate = 90 new DefaultPersistenceDelegate( 91 new String[] {"probeDescription", 92 "enabledProbeID", "CPU", "action", "offset", 93 "fault", "address", "defaultMessage"}); 94 BeanDescriptor d = info.getBeanDescriptor(); 95 d.setValue("persistenceDelegate", persistenceDelegate); 96 } catch (IntrospectionException e) { 97 e.printStackTrace(); 98 } 99 } 100 101 /** @serial */ 102 private final ProbeDescription probeDescription; 103 /** @serial */ 104 private final int epid; 105 /** @serial */ 106 private final int cpu; 107 /** @serial */ 108 private final int action; 109 /** @serial */ 110 private final int offset; 111 /** @serial */ 112 private final String fault; 113 /** @serial */ 114 private final long address; 115 /** @serial */ 116 private final String defaultMessage; 117 118 /** 119 * Creates a DTrace error with the given properties. Supports XML 120 * persistence. 121 * 122 * @param pdesc probe description that identifies the error-inducing 123 * probe among all the probes on the system 124 * @param enabledProbeID identifies the error-inducing probe among 125 * all probes enabled by the same {@link Consumer} 126 * @param errorCPU non-negative ID of the CPU where the error was 127 * encountered, or a negative number if the CPU is unknown 128 * @param errorAction integer that identifies the error-inducing 129 * action as the nth action (starting at one) in the error-inducing 130 * probe, or zero if the error is in the predicate rather than in an 131 * action 132 * @param errorOffset error offset in compiled DTrace Intermediate 133 * Format (DIF), or a negative number if the offset is not available 134 * @param faultName name of the specific fault, or {@code null} 135 * if the fault is unknown to the Java DTrace API 136 * @param faultAddress address of fault, or -1 if address is not 137 * applicable to the specific fault 138 * @param errorMessage default message from the native DTrace 139 * library preconstructed from the properties of this error 140 * @throws NullPointerException if the given probe description or 141 * default message is {@code null} 142 */ 143 public Error(ProbeDescription pdesc, int enabledProbeID, int errorCPU, int errorAction, int errorOffset, String faultName, long faultAddress, String errorMessage)144 Error(ProbeDescription pdesc, int enabledProbeID, int errorCPU, 145 int errorAction, int errorOffset, String faultName, 146 long faultAddress, String errorMessage) 147 { 148 probeDescription = pdesc; 149 epid = enabledProbeID; 150 cpu = errorCPU; 151 action = errorAction; 152 offset = errorOffset; 153 fault = faultName; 154 address = faultAddress; 155 defaultMessage = errorMessage; 156 validate(); 157 } 158 159 private final void validate()160 validate() 161 { 162 if (probeDescription == null) { 163 throw new NullPointerException( 164 "enabled probe description is null"); 165 } 166 if (defaultMessage == null) { 167 throw new NullPointerException("default message is null"); 168 } 169 } 170 171 /** 172 * Gets the probe description that identifies the error-inducing 173 * probe among all the probes on the system. 174 * 175 * @return non-null probe description 176 */ 177 public ProbeDescription getProbeDescription()178 getProbeDescription() 179 { 180 return probeDescription; 181 } 182 183 /** 184 * Gets the enabled probe ID. The "epid" is different from {@link 185 * ProbeDescription#getID()} because it identifies a probe among all 186 * the probes enabled by a {@link Consumer}, rather than among all 187 * the probes on the system. 188 * 189 * @return the enabled probe ID 190 */ 191 public int getEnabledProbeID()192 getEnabledProbeID() 193 { 194 return epid; 195 } 196 197 /** 198 * Gets the CPU that encountered the error. 199 * 200 * @return non-negative CPU ID, or a negative number if the CPU is 201 * unknown 202 */ 203 public int getCPU()204 getCPU() 205 { 206 return cpu; 207 } 208 209 /** 210 * Gets the error-inducing action as the <i>nth</i> action (starting 211 * at one) in the error-inducing probe, or zero if the error is in 212 * the predicate rather than in an action. Note that some actions 213 * in a D program consist of multiple actions internally within the 214 * DTrace library. 215 * 216 * @return zero if the error is in the probe predicate, otherwise 217 * the <i>nth</i> action (<i>n</i> starting at one) from the start 218 * of the probe that induced the error 219 */ 220 public int getAction()221 getAction() 222 { 223 return action; 224 } 225 226 /** 227 * Gets the error offset in compiled DTrace Intermediate Format 228 * (DIF), or a negative number if the offset is not available. 229 * 230 * @return the error offset in compiled DTrace Intermediate Format 231 * (DIF), or a negative number if the offset is not available 232 */ 233 public int getOffset()234 getOffset() 235 { 236 return offset; 237 } 238 239 /** 240 * Gets the name identifying the specific fault. The names are 241 * guaranteed not to change across API versions as long as the fault 242 * cases they identify still exist. 243 * 244 * @return name of the specific fault or {@code null} if the 245 * fault is unknown to the Java DTrace API 246 */ 247 public String getFault()248 getFault() 249 { 250 return fault; 251 } 252 253 /** 254 * Gets the address of the fault, if any. 255 * 256 * @return address of fault, or -1 if address is not applicable to 257 * the specific fault (the fault is not one of {@link 258 * #DTRACEFLT_BADADDR} or {@link #DTRACEFLT_BADALIGN}) 259 */ 260 public long getAddress()261 getAddress() 262 { 263 return address; 264 } 265 266 /** 267 * Gets the default message from the native DTrace library 268 * preconstructed from the properties of this error. 269 * 270 * @return non-null preconstructed message 271 */ 272 public String getDefaultMessage()273 getDefaultMessage() 274 { 275 return defaultMessage; 276 } 277 278 private void readObject(ObjectInputStream s)279 readObject(ObjectInputStream s) 280 throws IOException, ClassNotFoundException 281 { 282 s.defaultReadObject(); 283 // check class invariants 284 try { 285 validate(); 286 } catch (Exception e) { 287 InvalidObjectException x = new InvalidObjectException( 288 e.getMessage()); 289 x.initCause(e); 290 throw x; 291 } 292 } 293 294 /** 295 * Gets a string representation of this error useful for logging and 296 * not intended for display. The exact details of the 297 * representation are unspecified and subject to change, but the 298 * following format may be regarded as typical: 299 * <pre><code> 300 * class-name[property1 = value1, property2 = value2] 301 * </code></pre> 302 */ 303 public String toString()304 toString() 305 { 306 StringBuilder buf = new StringBuilder(); 307 buf.append(Error.class.getName()); 308 buf.append("[probeDescription = "); 309 buf.append(probeDescription); 310 buf.append(", epid = "); 311 buf.append(epid); 312 buf.append(", cpu = "); 313 buf.append(cpu); 314 buf.append(", action = "); 315 buf.append(action); 316 buf.append(", offset = "); 317 buf.append(offset); 318 buf.append(", fault = "); 319 buf.append(fault); 320 buf.append(", address = "); 321 buf.append(address); 322 buf.append(", defaultMessage = "); 323 buf.append(defaultMessage); 324 buf.append(']'); 325 return buf.toString(); 326 } 327 } 328