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.io.Serializable; 31 import java.io.*; 32 import java.beans.*; 33 34 /** 35 * Detail about one or more records dropped by DTrace (not reported to 36 * {@link ConsumerListener#dataReceived(DataEvent e) 37 * ConsumerListener.dataReceived()}) due to inadequte buffer space. 38 * <p> 39 * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. 40 * 41 * @see ConsumerListener#dataDropped(DropEvent e) 42 * 43 * @author Tom Erickson 44 */ 45 public final class Drop implements Serializable { 46 static final long serialVersionUID = 26653827678657381L; 47 48 static { 49 try { 50 BeanInfo info = Introspector.getBeanInfo(Drop.class); 51 PersistenceDelegate persistenceDelegate = 52 new DefaultPersistenceDelegate( 53 new String[] {"CPU", "kind", "count", "total", 54 "defaultMessage"}) 55 { 56 protected Expression 57 instantiate(Object oldInstance, Encoder out) 58 { 59 Drop drop = (Drop)oldInstance; 60 return new Expression(oldInstance, oldInstance.getClass(), 61 "new", new Object[] { drop.getCPU(), 62 drop.getKind().name(), drop.getCount(), 63 drop.getTotal(), drop.getDefaultMessage() }); 64 } 65 }; 66 BeanDescriptor d = info.getBeanDescriptor(); 67 d.setValue("persistenceDelegate", persistenceDelegate); 68 } catch (IntrospectionException e) { 69 e.printStackTrace(); 70 } 71 } 72 73 /** 74 * Indicates what kind of buffer space experienced the data drop 75 * (such as principal buffer or aggregation buffer) and possibly a 76 * reason. 77 */ 78 public enum Kind { 79 /** Drop to principal buffer */ 80 PRINCIPAL("Principal buffer"), 81 /** Drop to aggregation buffer */ 82 AGGREGATION("Aggregation"), 83 /** Dynamic drop */ 84 DYNAMIC("Dynamic"), 85 /** Dynamic drop due to rinsing */ 86 DYNRINSE("Dynamic (rinse)"), 87 /** Dynamic drop due to dirtiness */ 88 DYNDIRTY("Dynamic (dirty)"), 89 /** Speculative drop */ 90 SPEC("Speculation"), 91 /** Speculative drop due to business */ 92 SPECBUSY("Speculation (busy)"), 93 /** Speculative drop due to unavailability */ 94 SPECUNAVAIL("Speculation (unavailable)"), 95 /** Stack string table overflow */ 96 STKSTROVERFLOW("Stack string table overflow"), 97 /** Error in ERROR probe */ 98 DBLERROR("error in ERROR probe"), 99 /** Unrecognized value from native DTrace library */ 100 UNKNOWN("Unknown"); 101 102 private String s; 103 104 private Kind(String displayString)105 Kind(String displayString) 106 { 107 s = displayString; 108 } 109 110 /** 111 * Overridden to get the default display value. To 112 * internationalize the display value, use {@link Enum#name()} 113 * instead as an I18N lookup key. 114 */ 115 public String toString()116 toString() 117 { 118 return s; 119 } 120 } 121 122 /** @serial */ 123 private final int cpu; 124 /** @serial */ 125 private final Kind kind; 126 /** @serial */ 127 private final long count; 128 /** @serial */ 129 private final long total; 130 /** @serial */ 131 private final String defaultMessage; 132 133 /** 134 * Creates a {@code Drop} instance with the given CPU, drop kind, 135 * drop counts, and default message. Supports XML persistence. 136 * 137 * @param dropCPU cpu where drops occurred 138 * @param dropKindName name of enumeration value indicating the kind 139 * of buffer space where the drop occurred and possibly a reason 140 * @param dropCount number of drops 141 * @param totalDrops total number of drops since the source {@link 142 * Consumer} started running 143 * @param defaultDropMessage drop message provided by DTrace 144 * @throws IllegalArgumentException if there is no {@code Drop.Kind} 145 * value with the given name or if {@code dropCount} or {@code 146 * totalDrops} is negative 147 * @throws NullPointerException if the given {@code Drop.Kind} name 148 * or default message is {@code null} 149 */ 150 public Drop(int dropCPU, String dropKindName, long dropCount, long totalDrops, String defaultDropMessage)151 Drop(int dropCPU, String dropKindName, long dropCount, long totalDrops, 152 String defaultDropMessage) 153 { 154 cpu = dropCPU; 155 kind = Enum.valueOf(Kind.class, dropKindName); 156 count = dropCount; 157 total = totalDrops; 158 defaultMessage = defaultDropMessage; 159 validate(); 160 } 161 162 private final void validate()163 validate() 164 { 165 if (count < 0) { 166 throw new IllegalArgumentException("count is negative"); 167 } 168 if (total < 0) { 169 throw new IllegalArgumentException("total is negative"); 170 } 171 if (defaultMessage == null) { 172 throw new NullPointerException("default message is null"); 173 } 174 } 175 176 /** 177 * Gets the CPU where the drops occurred. 178 * 179 * @return non-negative CPU ID, or a negative number if the CPU is 180 * unknown 181 */ 182 public int getCPU()183 getCPU() 184 { 185 return cpu; 186 } 187 188 /** 189 * Gets the kind of drop for all drops included in {@link 190 * #getCount()}. 191 * 192 * @return non-null drop kind 193 */ 194 public Kind getKind()195 getKind() 196 { 197 return kind; 198 } 199 200 /** 201 * Gets the number of drops reported by this {@code Drop} instance. 202 * 203 * @return non-negative drop count 204 */ 205 public long getCount()206 getCount() 207 { 208 return count; 209 } 210 211 /** 212 * Gets the total number of drops since the source {@link Consumer} 213 * started running. 214 * 215 * @return non-negative drop total since tracing started 216 */ 217 public long getTotal()218 getTotal() 219 { 220 return total; 221 } 222 223 /** 224 * Gets the message provided by DTrace. 225 * 226 * @return non-null message provided by DTrace 227 */ 228 public String getDefaultMessage()229 getDefaultMessage() 230 { 231 return defaultMessage; 232 } 233 234 private void readObject(ObjectInputStream s)235 readObject(ObjectInputStream s) 236 throws IOException, ClassNotFoundException 237 { 238 s.defaultReadObject(); 239 // check class invariants 240 try { 241 validate(); 242 } catch (Exception e) { 243 InvalidObjectException x = new InvalidObjectException( 244 e.getMessage()); 245 x.initCause(e); 246 throw x; 247 } 248 } 249 250 /** 251 * Gets a string representation of this drop instance, not intended 252 * for display. The exact details of the representation are 253 * unspecified and subject to change, but the following format may 254 * be regarded as typical: 255 * <pre><code> 256 * class-name[property1 = value1, property2 = value2] 257 * </code></pre> 258 */ 259 public String toString()260 toString() 261 { 262 StringBuilder buf = new StringBuilder(); 263 buf.append(Drop.class.getName()); 264 buf.append("[cpu = "); 265 buf.append(cpu); 266 buf.append(", kind = "); 267 buf.append(kind); 268 buf.append(", count = "); 269 buf.append(count); 270 buf.append(", total = "); 271 buf.append(total); 272 buf.append(", defaultMessage = "); 273 buf.append(defaultMessage); 274 buf.append(']'); 275 return buf.toString(); 276 } 277 } 278