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