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 package org.opensolaris.os.dtrace; 27 28 import java.io.*; 29 import java.beans.*; 30 31 /** 32 * Triplet of attributes consisting of two stability levels and a 33 * dependency class. Attributes may vary independently. They use 34 * labels described in the {@code attributes(7)} man page to help set 35 * expectations for what kinds of changes might occur in different kinds 36 * of future releases. The D compiler includes features to dynamically 37 * compute the stability levels of D programs you create. For more 38 * information, refer to the <a 39 * href=http://dtrace.org/guide/chp-stab.html> 40 * <b>Stability</b></a> chapter of the <i>Dynamic Tracing 41 * Guide</i>. 42 * <p> 43 * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. 44 * 45 * @see Consumer#getProgramInfo(Program program) 46 * @see Consumer#enable(Program program) 47 * @see Consumer#listProbes(ProbeDescription filter) 48 * @see Consumer#listProgramProbes(Program program) 49 * 50 * @author Tom Erickson 51 */ 52 public final class InterfaceAttributes implements Serializable { 53 static final long serialVersionUID = -2814012588381562694L; 54 55 static { 56 try { 57 BeanInfo info = Introspector.getBeanInfo(InterfaceAttributes.class); 58 PersistenceDelegate persistenceDelegate = 59 new DefaultPersistenceDelegate( 60 new String[] {"nameStability", "dataStability", 61 "dependencyClass" }) 62 { 63 /* 64 * Need to prevent DefaultPersistenceDelegate from using 65 * overridden equals() method, resulting in a 66 * StackOverFlowError. Revert to PersistenceDelegate 67 * implementation. See 68 * http://forum.java.sun.com/thread.jspa?threadID= 69 * 477019&tstart=135 70 */ 71 protected boolean 72 mutatesTo(Object oldInstance, Object newInstance) 73 { 74 return (newInstance != null && oldInstance != null && 75 oldInstance.getClass() == newInstance.getClass()); 76 } 77 78 protected Expression 79 instantiate(Object oldInstance, Encoder out) 80 { 81 InterfaceAttributes attr = (InterfaceAttributes) 82 oldInstance; 83 return new Expression(oldInstance, oldInstance.getClass(), 84 "new", new Object[] { 85 attr.getNameStability().name(), 86 attr.getDataStability().name(), 87 attr.getDependencyClass().name() }); 88 } 89 }; 90 BeanDescriptor d = info.getBeanDescriptor(); 91 d.setValue("persistenceDelegate", persistenceDelegate); 92 } catch (IntrospectionException e) { 93 e.printStackTrace(); 94 } 95 } 96 97 /** 98 * Interface stability level. Assists developers in making risk 99 * assessments when developing scripts and tools based on DTrace by 100 * indicating how likely an interface or DTrace entity is to change 101 * in a future release or patch. 102 */ 103 public enum Stability { 104 /** 105 * The interface is private to DTrace itself and represents an 106 * implementation detail of DTrace. Internal interfaces might 107 * change in minor or micro releases. 108 */ 109 INTERNAL("Internal"), 110 /** 111 * The interface is private to Sun and represents an interface 112 * developed for use by other Sun products that is not yet 113 * publicly documented for use by customers and ISVs. Private 114 * interfaces might change in minor or micro releases. 115 */ 116 PRIVATE("Private"), 117 /** 118 * The interface is supported in the current release but is 119 * scheduled to be removed, most likely in a future minor 120 * release. When support of an interface is to be discontinued, 121 * Sun will attempt to provide notification before discontinuing 122 * the interface. The D compiler might produce warning messages 123 * if you attempt to use an Obsolete interface. 124 */ 125 OBSOLETE("Obsolete"), 126 /** 127 * The interface is controlled by an entity other than Sun. At 128 * Sun's discretion, Sun can deliver updated and possibly 129 * incompatible versions as part of any release, subject to 130 * their availability from the controlling entity. Sun makes no 131 * claims regarding either the source or binary compatibility 132 * for External interfaces between two releases. Applications 133 * based on these interfaces might not work in future releases, 134 * including patches that contain External interfaces. 135 */ 136 EXTERNAL("External"), 137 /** 138 * The interface is provided to give developers early access to 139 * new or rapidly changing technology or to an implementation 140 * artifact that is essential for observing or debugging system 141 * behavior for which a more stable solution is anticipated in 142 * the future. Sun makes no claims about either source of 143 * binary compatibility for Unstable interfaces from one minor 144 * release to another. 145 */ 146 UNSTABLE("Unstable"), 147 /** 148 * The interface might eventually become Standard or Stable but 149 * is still in transition. Sun will make reasonable efforts to 150 * ensure compatibility with previous releases as it evolves. 151 * When non-upward compatible changes become necessary, they 152 * will occur in minor and major releases. These changes will 153 * be avoided in micro releases whenever possible. If such a 154 * change is necessary, it will be documented in the release 155 * notes for the affected release, and when feasible, Sun will 156 * provide migration aids for binary compatibility and continued 157 * D program development. 158 */ 159 EVOLVING("Evolving"), 160 /** 161 * The interface is a mature interface under Sun's control. Sun 162 * will try to avoid non-upward-compatible changes to these 163 * interfaces, especially in minor or micro releases. If 164 * support of a Stable interface must be discontinued, Sun will 165 * attempt to provide notification and the stability level 166 * changes to Obsolete. 167 */ 168 STABLE("Stable"), 169 /** 170 * The interface complies with an industry standard. The 171 * corresponding documentation for the interface will describe 172 * the standard to which the interface conforms. Standards are 173 * typically controlled by a standards development organization, 174 * and changes can be made to the interface in accordance with 175 * approved changes to the standard. This stability level can 176 * also apply to interfaces that have been adopted (without a 177 * formal standard) by an industry convention. Support is 178 * provided for only the specified versions of a standard; 179 * support for later versions is not guaranteed. If the 180 * standards development organization approves a 181 * non-upward-compatible change to a Standard interface that Sun 182 * decides to support, Sun will announce a compatibility and 183 * migration strategy. 184 */ 185 STANDARD("Standard"); 186 187 private String s; 188 189 private Stability(String displayName)190 Stability(String displayName) 191 { 192 s = displayName; 193 } 194 195 /** 196 * Overridden to get the default display value. To 197 * internationalize the display value, use {@link 198 * java.lang.Enum#name()} instead as a lookup key. 199 */ 200 @Override 201 public String toString()202 toString() 203 { 204 return s; 205 } 206 } 207 208 /** 209 * Architectural dependency class. Tells whether an interface is 210 * common to all platforms and processors, or whether the 211 * interface is associated with a particular architecture such as 212 * SPARC processors only. 213 */ 214 public enum DependencyClass { 215 // Note that the compareTo() method depends on the order in 216 // which the instances are instantiated 217 218 /** 219 * The interface has an unknown set of architectural dependencies. 220 * DTrace does not necessarily know the architectural dependencies of 221 * all entities, such as data types defined in the operating system 222 * implementation. The Unknown label is typically applied to interfaces 223 * of very low stability for which dependencies cannot be computed. The 224 * interface might not be available when using DTrace on <i>any</i> 225 * architecture other than the one you are currently using. 226 */ 227 UNKNOWN("Unknown"), 228 /** 229 * The interface is specific to the CPU model of the current 230 * system. You can use the {@code psrinfo(8)} utility's {@code 231 * -v} option to display the current CPU model and 232 * implementation names. Interfaces with CPU model dependencies 233 * might not be available on other CPU implementations, even if 234 * those CPUs export the same instruction set architecture 235 * (ISA). For example, a CPU-dependent interface on an 236 * UltraSPARC-III+ microprocessor might not be available on an 237 * UltraSPARC-II microprocessor, even though both processors 238 * support the SPARC instruction set. 239 */ 240 CPU("CPU"), 241 /** 242 * The interface is specific to the hardware platform of the current 243 * system. A platform typically associates a set of system components 244 * and architectural characteristics such as a set of supported CPU 245 * models with a system name such as <code>SUNW, 246 * Ultra-Enterprise-10000</code>. You can display the current 247 * platform name using the {@code uname(1)} {@code -i} option. 248 * The interface might not be available on other hardware 249 * platforms. 250 */ 251 PLATFORM("Platform"), 252 /** 253 * The interface is specific to the hardware platform group of the 254 * current system. A platform group typically associates a set of 255 * platforms with related characteristics together under a single name, 256 * such as {@code sun4u}. You can display the current platform 257 * group name using the {@code uname(1)} {@code -m} option. The 258 * interface is available on other platforms in the platform 259 * group, but might not be available on hardware platforms that 260 * are not members of the group. 261 */ 262 GROUP("Group"), 263 /** 264 * The interface is specific to the instruction set architecture (ISA) 265 * supported by the microprocessor on this system. The ISA describes a 266 * specification for software that can be executed on the 267 * microprocessor, including details such as assembly language 268 * instructions and registers. You can display the native 269 * instruction sets supported by the system using the {@code 270 * isainfo(1)} utility. The interface might not be supported on 271 * systems that do not export any of of the same instruction 272 * sets. For example, an ISA-dependent interface on a 273 * SPARC system might not be supported on an x86 system. 274 */ 275 ISA("ISA"), 276 /** 277 * The interface is common to all systems regardless of the 278 * underlying hardware. DTrace programs and layered applications that 279 * depend only on Common interfaces can be executed and deployed on 280 * other systems with the same illumos and DTrace revisions. 281 * The majority of DTrace interfaces are Common, so you can use them 282 * wherever you use illumos. 283 */ 284 COMMON("Common"); 285 286 private String s; 287 288 private DependencyClass(String displayString)289 DependencyClass(String displayString) 290 { 291 s = displayString; 292 } 293 294 /** 295 * Overridden to get the default display value. To 296 * internationalize the display value, use {@link 297 * java.lang.Enum#name()} instead as a lookup key. 298 */ 299 @Override 300 public String toString()301 toString() 302 { 303 return s; 304 } 305 } 306 307 /** @serial */ 308 private Stability nameStability; 309 /** @serial */ 310 private Stability dataStability; 311 /** @serial */ 312 private DependencyClass dependencyClass; 313 314 /** 315 * Called by native code. 316 */ 317 private InterfaceAttributes()318 InterfaceAttributes() 319 { 320 } 321 322 /** 323 * Creates an interface attribute triplet from the given attributes. 324 * 325 * @param nameStabilityAttribute the stability level of the 326 * interface associated with its name in a D program 327 * @param dataStabilityAttribute stability of the data format used 328 * by the interface and any associated data semantics 329 * @param dependencyClassAttribute describes whether the interface 330 * is specific to the current operating platform or microprocessor 331 * @throws NullPointerException if any parameter is {@code null} 332 */ 333 public InterfaceAttributes(Stability nameStabilityAttribute, Stability dataStabilityAttribute, DependencyClass dependencyClassAttribute)334 InterfaceAttributes(Stability nameStabilityAttribute, 335 Stability dataStabilityAttribute, 336 DependencyClass dependencyClassAttribute) 337 { 338 nameStability = nameStabilityAttribute; 339 dataStability = dataStabilityAttribute; 340 dependencyClass = dependencyClassAttribute; 341 validate(); 342 } 343 344 /** 345 * Creates an interface attribute triplet from the given attribute 346 * names. Supports XML persistence. 347 * 348 * @throws NullPointerException if any parameter is {@code null} 349 * @throws IllegalArgumentException if any parameter fails to match 350 * an enumerated stability value 351 */ 352 public InterfaceAttributes(String nameStabilityAttributeName, String dataStabilityAttributeName, String dependencyClassAttributeName)353 InterfaceAttributes(String nameStabilityAttributeName, 354 String dataStabilityAttributeName, 355 String dependencyClassAttributeName) 356 { 357 this(Enum.valueOf(Stability.class, nameStabilityAttributeName), 358 Enum.valueOf(Stability.class, dataStabilityAttributeName), 359 Enum.valueOf(DependencyClass.class, 360 dependencyClassAttributeName)); 361 // validate() unnecessary because Enum.valueOf() has already 362 // thrown the exception 363 } 364 365 private final void validate()366 validate() 367 { 368 if (nameStability == null) { 369 throw new NullPointerException("nameStability is null"); 370 } 371 if (dataStability == null) { 372 throw new NullPointerException("dataStability is null"); 373 } 374 if (dependencyClass == null) { 375 throw new NullPointerException("dependencyClass is null"); 376 } 377 } 378 379 /** 380 * Gets the stability level of an interface associated with its name 381 * as it appears in a D program. For example, the {@code execname} 382 * D variable is a {@link Stability#STABLE STABLE} name: Sun 383 * guarantees this identifier will continue to be supported in D 384 * programs according to the rules described for Stable interfaces. 385 * 386 * @return the stability level of an interface associated with its 387 * name as it appears in a D program 388 */ 389 public Stability getNameStability()390 getNameStability() 391 { 392 return nameStability; 393 } 394 395 /** 396 * Called by native code. 397 */ 398 private void setNameStability(String s)399 setNameStability(String s) 400 { 401 nameStability = Enum.valueOf(Stability.class, s); 402 } 403 404 /** 405 * Gets the stability level of the data format used by an interface 406 * and any associated data semantics. For example, the {@code pid} 407 * D variable is a {@link Stability#STABLE STABLE} interface: 408 * process IDs are a stable concept in illumos, and it is guaranteed 409 * that the {@code pid} variable will be of type {@code pid_t} with 410 * the semantic that it is set to the process ID corresponding to 411 * the thread that fired a given probe in accordance with the rules 412 * described for Stable interfaces. 413 * 414 * @return the stability level of the data format used by an 415 * interface and any associated data semantics. 416 */ 417 public Stability getDataStability()418 getDataStability() 419 { 420 return dataStability; 421 } 422 423 /** 424 * Called by native code. 425 */ 426 private void setDataStability(String s)427 setDataStability(String s) 428 { 429 dataStability = Enum.valueOf(Stability.class, s); 430 } 431 432 /** 433 * Gets the interface dependency class. 434 * 435 * @return the dependency class describing whether the interface is 436 * specific to the current operating platform or microprocessor 437 */ 438 public DependencyClass getDependencyClass()439 getDependencyClass() 440 { 441 return dependencyClass; 442 } 443 444 /** 445 * Called by native code. 446 */ 447 private void setDependencyClass(String s)448 setDependencyClass(String s) 449 { 450 dependencyClass = Enum.valueOf(DependencyClass.class, s); 451 } 452 453 /** 454 * Compares the specified object with this attribute triplet for 455 * equality. Defines equality as having the same attributes. 456 * 457 * @return {@code true} if and only if the specified object is also 458 * an {@code InterfaceAttributes} instance and has all the same 459 * attributes as this instance. 460 */ 461 @Override 462 public boolean equals(Object o)463 equals(Object o) 464 { 465 if (o == this) { 466 return true; 467 } 468 if (o instanceof InterfaceAttributes) { 469 InterfaceAttributes a = (InterfaceAttributes)o; 470 return ((nameStability == a.nameStability) && 471 (dataStability == a.dataStability) && 472 (dependencyClass == a.dependencyClass)); 473 } 474 return false; 475 } 476 477 /** 478 * Overridden to ensure that equal {@code InterfaceAttributes} 479 * instances have equal hashcodes. 480 */ 481 @Override 482 public int hashCode()483 hashCode() 484 { 485 int hash = 17; 486 hash = (37 * hash) + nameStability.hashCode(); 487 hash = (37 * hash) + dataStability.hashCode(); 488 hash = (37 * hash) + dependencyClass.hashCode(); 489 return hash; 490 } 491 492 private void readObject(ObjectInputStream s)493 readObject(ObjectInputStream s) 494 throws IOException, ClassNotFoundException 495 { 496 s.defaultReadObject(); 497 // Check constructor invariants 498 try { 499 validate(); 500 } catch (Exception e) { 501 InvalidObjectException x = new InvalidObjectException( 502 e.getMessage()); 503 x.initCause(e); 504 throw x; 505 } 506 } 507 508 /** 509 * Gets the string representation of this triplet of interface 510 * attributes. The format follows the convention described in the 511 * <a href=http://dtrace.org/guide/chp-stab.html#chp-stab-3> 512 * <b>Interface Attributes</b></a> section of the <b>Stability</b> 513 * chapter of the <i>Dynamic Tracing Guide</i>. The 514 * attributes appear in the following order, separated by slashes: 515 * <pre><code> 516 * <i>name-stability / data-stability / dependency-class</i> 517 * </code></pre> 518 */ 519 public String toString()520 toString() 521 { 522 StringBuilder buf = new StringBuilder(); 523 buf.append(nameStability); 524 buf.append(" / "); 525 buf.append(dataStability); 526 buf.append(" / "); 527 buf.append(dependencyClass); 528 return buf.toString(); 529 } 530 } 531