JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Remote Administration Daemon Developer Guide     Oracle Solaris 11.1 Information Library
search filter icon
search icon

Document Information

Preface

1.  Introduction

2.  Concepts

Interface

Name

Derived Types

Features

Methods

Attributes

Events

Versioning

Numbering

Commitment

Clients and Versioning

rad Namespace

Naming

Equality

Patterns

Operations

Data Typing

Base Types

Derived Types

Optional Data

3.  Abstract Data Representation

4.  libadr

5.  Client Libraries

6.  Module Development

7.  rad Best Practices

A.  rad Binary Protocol

Interface

An interface defines how a rad client can interact with an object. An object implements an interface, providing a concrete behavior to be invoked when a client makes a request.

The primary purpose of rad is to consistently expose the various pieces of the system for administration. Not all subsystems are alike, however: each has a data and state model tuned to the problems they are solving. Although there are major benefits to using a common model across components when possible, uniformity comes with trade-offs. The increased inefficiency and client complexity, and risk of decreased developer adoption, often warrant using an interface designed for problem at hand.

An interface is a formal definition of how a client may interact with a rad server object. An interface may be shared amongst several objects, for example, when maintaining a degree of uniformity is possible and useful, or may be implemented by only one. A rad interface is analogous to an interface or pure abstract class in an object oriented programming language. In the case of rad, an interface consists of a name, the set of features a client may interact with, optionally a set of derived types referenced by the features, and a version. The features supported include:

Name

Each interface has a name. This name is used by the toolchain to construct identifier names when generating code, and is returned by the server along with the rest of the interface definition when an object is examined by a client. There is no global namespace for interfaces, however. A client is expected either to know which objects implement which interfaces (typical consumer) or to query rad for the object's full interface definition (debugger or interactive tools).

Derived Types

Three classes of derived types may be defined for use by features: structures, unions, and enumerations. Each type defined must be uniquely named. As with interfaces, there is no global type namespace. The types defined in an API are available only to the features defined in that API.

Features

The only thing all three feature types — methods, attributes, and events — have in common is that they are named. All three feature types' names exist in the same namespace and must therefore be unique. You can not have both a method and an attribute called “foo.” This exclusion avoids the majority of conflicts that could arise when trying to naturally map these interface features to a client environment.


Note - Enforcing a common namespace for interface features isn't always enough. Some language environments place additional constraints on naming. For instance, a JMX client using MXBean proxies will see an interface with synthetic methods of the form getXXX() or setXXX() for accessing attribute XXX that must coexist with other method names. Explicitly defining methods with those names will cause a conflict.


Methods

A method is a procedure call made in the context of the object it is called on. In addition to a name, a method may define a return type, can define zero or more arguments, and may declare that it returns an error, optionally with an error return type.

If a method does not define a return type, it returns no value. It is effectively of type void. If a method defines a return type and that type is permitted to be nullable, the return value may be defined to be nullable.

Each method argument has a name and a type. If any argument's type is permitted to be nullable, that argument may be defined to be nullable.

If a method does not declare that it returns an error, it theoretically cannot fail. However, because the connection to rad could be broken either due to a network problem or a catastrophic failure in rad itself, all method calls can fail with an I/O error. If a method declares that it returns an error but does not specify a type, the method may fail due to API-specific reasons. Clients will be able to distinguish this failure type from I/O failures.

Finally, if a method also defines an error return type, data of that type may be provided to the client in the case where the API-specific failure occurs. Error payloads are implicitly optional, and must therefore be of a type that is permitted to be nullable.


Note - Methods names may not be overloaded.


Attributes

An attribute is metaphorically a property of the object. Attributes have the following characteristics:

Reading a read-only or read-write attribute returns the value of that attribute. Writing a write-only or read-write attribute sets the value of that attribute. Reading a write-only attribute or writing a read-only attribute is invalid. Clients may treat attempts to write to a read-only attribute as a write to an attribute that does not exist. Likewise, attempts to read from a write-only attribute may be treated as an attempt to read from an attribute that does not exist.

If an attribute's type is permitted to be nullable, its value may be defined to be nullable.

An attribute may optionally declare that it returns an error, with the same semantics as declaring (or not declaring) an error for a method. Unlike a method, an attribute may have different error declarations for reading the attribute and writing the attribute.

Attribute names may not be overloaded. Defining a read-only attribute and a write-only attribute with the same name is not valid.

Given methods, attributes are arguably a superfluous interface feature. Writing an attribute of type X can be implemented with a method that takes one argument of type X and returns nothing, and reading an attribute of type X can be implemented with a method that takes no arguments and returns a value of type X. Attributes are included because they have slightly different semantics.

In particular, an explicit attribute mechanism has the following characteristics:

Events

An event is an asynchronous notification generated by rad and consumed by clients. A client may subscribe to events by name to register interest in them. The subscription is performed on an object which implements an interface. In addition to a name, each event has a type.

Events have the following characteristics:

A client can rely on sequential delivery of events from a server as long as the connection to the server is maintained. If the connection fails, then events will be lost. On reconnection, a client must resubscribe to resume the flow of events.

Once a client has subscribed to an event, event notifications will be received until the client unsubscribes from the event.

On receipt of a subscribed event, a client receives a payload of the defined type.

Versioning

rad interfaces are versioned for the following reasons:

Numbering

The first issue is measuring the compatibility of a change. rad uses a simple major.minor versioning scheme. When a compatible change to an interface is made, its minor version number is incremented. When an incompatible change is made, its major version number is incremented and its minor version number is reset to 0.

In other words, an implementation of an interface that claims to be version X.Y (where X is the major version and Y is the minor version) must support any client expecting version X.Z, where Z <= Y.

The following interface changes are considered compatible:

The following interface changes are considered incompatible:


Note - An interface is more than just a set of methods, attributes, and events. Associated with those features are well-defined behaviors. If those behaviors change, even if the structure of the interface remains the same, a change to the version number might be required.


Commitment

To solve the problem of different features being intended for different consumers, rad defines three commitment levels: private, uncommitted, and committed. Each method, attribute, and event in an interface defines its commitment level independently. The interface is assigned a separate version number, per commitment level.

Each commitment level is considered a superset of the next more-committed level. For example, “private” is a superset of “uncommitted.” Therefore, when an uncommitted (or committed) interface changes, the private version number needs to be changed as well. By having separate version numbers instead of just adding more dots to the existing one, private/uncommitted consumers are not broken by compatible changes to uncommitted/committed interfaces.

When a feature changes commitment level, it is treated as if the feature was removed from the old commitment level and added to the new one. If a feature becomes less committed, then that implies an incompatible change for the every commitment level that no longer includes that feature but no change for every commitment level that still includes the feature due to the implicit nesting of commitment levels. If a feature becomes more committed, then that implies a compatible change for each commitment level that gained the feature and no change for each commitment level that had it before.

The simple case of an API containing interfaces of only a single commitment level reduces to traditional commitment-agnostic major/minor versioning.

Clients and Versioning

A rad client can ask for interface version information if the protocol in use does not automatically provide it. The client decides what to do with this information. It can expose that information directly to interface consumers, or it can provide APIs that encapsulate verifying that the version the client expects is the version the server is providing.