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 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 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 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 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 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 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 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 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 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 273 getDefaultMessage() 274 { 275 return defaultMessage; 276 } 277 278 private void 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 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