|
SA Forum - Java AIS API (R2 A.01.01) | |||||||||
PREV NEXT | FRAMES NO FRAMES |
See:
Description
Packages | |
---|---|
org.saforum.ais | This package contains common types and constants for the AIS service APIs. |
org.saforum.ais.amf | This package contains common types and constants of the Java language binding for the AIS Availability Management Framework defined by Service Availability Forum. |
org.saforum.ais.clm | This package contains common types and constants of the Java language binding for the AIS Cluster Membership Service defined by Service Availability Forum. |
This set of packages (published under the Service Availability Forum Specification License Agreement) defines a Java language binding that provides access to high availability middleware implementations compliant with the Application Interface Specification defined by Service Availability Forum.
Copyright statement is specified here.
The Application Interface Specification (AIS) defined by SA Forum standardizes the interface between a SAF-compliant High Availability (HA) middleware and service applications. AIS defines a set of AIS Services, which are services designed to support highly available applications in a cluster. Furthermore, AIS Frameworks are AIS Services that in addition to providing service for their clients also define an information model that these clients must use.
The current AIS release (B.01.01, i.e. Release 2) defines the following services and frameworks: Availability Management Framework (AMF), Cluster Membership Service (CLM), Checkpoint Service (CKPT), Message Service (MSG), Event Service (EVT) and Lock Service (LCK). Further AIS services may be specified in future releases by SA Forum.
The following AIS services and frameworks are supported in this release of Java APIs:
Availability Management Framework
(AMF):
AMF is the software entity that provides service availability by coordinating redundant resources within a cluster
to deliver a system with no single point of failure. AMF provides a set of APIs to enable high levels of
service availability.Cluster Membership Service
(CLM): CLM provides applications with membership information
about the nodes that have been administratively configured in the cluster configuration.
In the future SA Forum will publish Java API mappings according to the following guidelines:
The above specification documents define the semantics of the services and also describe the APIs provided for applications using the services (the APIs are defined in the C programming language). If you are not familiar with these specification documents, you are strongly advised to study them: this javadoc can be used as a programming reference, but it does not explain the underlying AIS services. Furthermore, the knowledge of the C API will help understand the Java API as certain patterns are "imported" from the C API.
The specification for the Java mapping contains two documents:
FactoryImpl
) to facilitate quick implementation of these APIs.
Implementors are allowed (though not encouraged) to replace the implementation parts as
long as the contract of the interfaces (as defined in this javadoc) is fully respected.
The AIS service API definitions in Java are based very closely on the corresponding C language APIs for AIS. They are designed so that:
There are presently two levels of packages:
The functionality of the AIS services is presented to the client code by Java methods. These methods are declared in interfaces rather than in classes. Interfaces preserve the separation between implementation and specification as well as keeping the class hierarchy flexible.
The AIS library life cycle is based upon the following model:
Thus, the core object of each service is the <Area>Handle, representing the dynamic association between the AIS component and the AIS area server. This object:
The client usually is free to use more than one <Area>Handle objects to communicate with the area server (the only restriction applies to AMF, which allows only a single library handle to carry out operations that require registration).
The two AIS library life cycle operations are the initialization and the finalization of the library handle.
Initialization is done by invoking the initializeHandle() method
of the appropriate service factory object (i.e. <Area>HandleFactory).
The client code must specify the Version
of the requested AIS service and pass a
<Area>Callbacks object containing the set of implemented callback interfaces
used by the library for asynchronous communication.
The factory framework is specified in the following manner:
Factory
. All the service factory objects implement this interface. This
is a generic interface parameterized by the service interface ("S", representing the library handle) and
the callback class ("C", representing the set of callback - or listener, if you like - interfaces used by the library
for asynchronous communication).Callbacks
abstract class has been added, from which all other callback classes
derive. This class is empty: i.e. it extends Object but
without adding or changing anything. It is used as a marker for the
generic interfaces.FactoryImpl
in the "ais" package.The finalization is done by invoking the finalizeHandle() method on the <Area>Handle object. This makes it invalid for further use, but note that the references of <Area>Handle and the related objects still need to be dropped to give the garbage collector a chance to clean up.
The library handle provides the infrastructure for asynchronous communication between the client and the AIS area server. This infrastructure has three elements:
Finally, the library handle provides a gateway for service specific API functionality. In order to avoid the creation of a potentially huge spaghetti class, <Area>Handle objects do not declare methods offering service specific API functionality directly. Instead, service specific methods are implemented by closely associated objects and the library handle provides methods returning references to these associated objects. These library handle methods (and consequently the associated objects) come in two different flavours:
AmfHandle
declares many getter functions: getComponentRegistry(), getCsiManager(), etc.
that in turn return the ComponentRegistry
,
CsiManager
, etc. objects defining various
methods of the AMF API, respectively. These objects are pure
Java objects and therefore require no special method for clean-up after use.
As a general rule, the Java API uses commonly accepted naming conventions. These conventions dictate using uppercase letters to begin type names, lowercase letters for methods, all caps for constants, and all lower case letters for packages. Also note that method names start with a verb, followed by the subject of the action.
The C AIS API uses naming conventions that heavily rely on the usage of service specific prefixes (sa, saAmf, saCkpt, etc.). These prefixes reflect the lack of namespaces in C language. Since Java packages do provide namespaces, the Java API does not generally use these prefixes. This rule applies to all public names, i.e. classes, methods, formal parameters, fields, constants. There are a few exceptions, though:
AisLibraryException
AmfHandle
instead of org.saforum.ais.amf.Handle, etc.).
Consts
).
The result of these rules is that most names of the Java API are shorter than the corresponding C API name. Nevertheless,
it is still very easy to "find" corresponding names of the two APIs. For example,
saAmfComponentRegister() becomes registerComponent() (see ComponentRegistry
).
AmfHandle.Callbacks
) does not change in AMF B.03.01, even though it is extended with two new fields.
Enumerated types (Enum classes) are used to define most constant values. The basic form of Java Enums defines a set of symbolic identifiers without explicitly assigning a numeric value to the identifiers. In the Java AIS API enums are extended so that each symbolic identifier is tied to the numeric value defined by the corresponding C API definition. The reason for this extension is that the Java client may have to forward the numeric value to a non-Java entity within the SA Forum cluster (e.g. embed the value into a message or a log).
The Java API uses public static final fields of the appropriate primitive type for constants that cannot be Enums. Enumerated types are in general more favourable, but they cannot always be used to define constants, mostly because the set of legal values of an enumeration type is strictly limited to those listed in its definition. As a consequence:
Primitive data types are usually converted to their Java counterparts of the same bit-size. E.g. a type defined in the C API as SaInt16T (directly or via typedef) is mapped to a short type in the Java API. However, there are a few exceptions. Certain unsigned values in the C API represent identifiers/handles that are converted into full-scale Java objects. Another frequent example is the size information for C buffers: these are typically presented as arrays in the Java API, where the length information is a built-in language construct.
Note that unsigned integer types are also usually converted to the signed Java primitive type of the same bit-size: thus, an SaUint32T becomes (a signed) int in the Java API. Although this could in theory cause interpretation problems if e.g. arithmetic or relational operations were used carelessly, in practice most unsigned integer types of the C API are used for special purposes, so this is not a problem:
Version
are expected to be used in comparison operations, therefore they
are declared as short instead of byte, so that the whole 8-bit unsigned range is included in their
type.
There are several ways strings are represented in the C API (e.g null-terminated strings, character arrays, SaNameT). All of these types are represented by the String class in the Java API. It is the responsibility of the Java API implementation to carry out any conversion, if necessary.
There are C structs that encapsulate a buffer pointer and its length: these are represented as Java arrays. Otherwise, C structs are defined in Java as public classes with public fields. For the sake of simplicity and effectiveness, no code is added to them, not even setters or getters. The reasons for this arguable decision are the following:
C unions are replaced by a hierarchy of classes, the root class representing the union as a type, subclasses representing particular union components.
C arrays are defined as Java arrays.
Function pointers -- callbacks -- are defined as interfaces with a single method defining the signature of the callback
The functions of the C API are mapped to methods of the Java API. In most cases there is one-to-one correspondence in functionality between the C function and the Java method. In such cases, as explained above, typically the naming has been simplified in the Java API in such a manner that the equivalent C function name is obvious. Noteworthy exceptions to the naming of such Java methods is the initialization and finalization of handles:
There are cases where a single C API function is refactored to several Java methods with different parameter lists. These C functions use certain parameters to govern what the function actually should do. These functions are decomposed into several Java methods. Below you can find some examples:
ComponentRegistry
interface) for registering different component
types. E.g. one of these registers "normal" SA-aware coponents, another one registers
registers proxied components (by their proxy).
Similarly, there are separated unregister methods for different component types, replacing
saAmfComponentUnregister().
ProtectionGroupManager
), each requesting
tracked object information, but in different manners:
In Java, memory is never freed explicitly. Instead, the garbage collector reclaims unused memory. Therefore, C API functions freeing up memory (typically named as sa<Area><SomeEntity>Free() do not have their counterparts in Java.
In the C API, a "handle" is often passed to a function. In Java, this is not the case. The "handle" is the object on which the method is invoked. Within the method, this can be used to explicitly refer to this implicit parameter.
The C AIS API follows a typical C error handling convention: the return value of each API functions invoked by the AIS Component is an integer value (enum type SaAisErrorT) representing the error status of the executed function. SA_AIS_OK represents a successful execution, whereas SA_AIS_ERR_<SOME_ERROR> values represent possible errors.
Errors are handled using exceptions in Java, therefore the Java AIS API declares
appropriate exceptions for the possible AIS errors.
For each SA_AIS_ERR_<SOME_ERROR> value there is an Ais<SomeError>Exception
class declared in the org.saforum.ais
package.
So, Java AIS API methods throw one of these exceptions instead of returning an error value.
(If no exception is thrown, the method executed successfully
i.e. this is the equivalent behaviour with the C function returning SA_AIS_OK).
There is a superclass AisException
for all the exception classes:
it is never thrown by the API but can be used by the applications for error handling,
especially if the error handling code is generic and applies to all possible exceptions thrown by the API method.
(However, note that many argue that catching individual exceptions is the best ? and preferred -
programming style in Java...) The AisException
is a checked exception (i.e. Exception subclass),
which means that the clients of AIS API methods are forced to handle the Ais<SomeError>Exceptions
either by catching the exceptions or by explicitly declaring them in the enclosing methods.
As usual in Java, extra status information is embedded in an exception when it is thrown:
e.g. a stack trace, a possible nested exception, a message string.
There is an enumerated type AisStatus
that corresponds to the C
SaAisErrorT values (including SA_AIS_OK).
It is used to indicate the status of operations executed asynchronously, i.e.
the status of an operation other than the one initiated by the actual method call. Some examples are as follows:
AmfHandle
uses AisStatus
to indicate the result of a formerly invoked AMF callback.
AisStatus
to indicate the status of the asynchronous
call (see e.g. TrackProtectionGroupCallback
)
Often in the C API, the parameters being passed must be accompanied by descriptive data. For example, often a pointer to an array is passed along with a second parameter giving the number of (valid) elements. In the Java API, this is not done. Instead, Java's type checking/safety and ability to interrogate objects is used. For example, to get the number of elements in an array, the ".length" attribute is used, etc.
The replacement of handles with object references, the use of exceptions instead of a status return, and the elimination of descriptive parameters means that the Java methods have far fewer parameters (approximately one half, on average) compared to the C functions. So the signatures are quite different. Also, the elimination of the status return frees up this usage for other return values. Hence, there are very few "out" parameters in the Java API.
Java generic types are used to create a uniform factory framework. The C API
"factories" (i.e. the sa<Area>Initialize() functions) provide the same
initialization scheme, but still have to be declared separately in the C API for each service because
of the differences in the formal parameter list. By using a generic interface,
the Java API can capture the uniformity of library handle initialization in a more elegant way.
Thus, the Java API declares a generic initializeHandle() method (see Factory
).
There are two actual differences between the
initializers for the different services: the set of callbacks supported by the
service and the actual library handle implementation returned by the factory.
Hence, in the interface you will find two type variables:
S" for Service (i.e. the library handle) and "C" for Callbacks.
Permission to use, copy, and distribute this mapping specification for any purpose without fee is hereby granted, provided that this entire notice is included in all copies. No permission is granted for, and users are prohibited from, modifying or making derivative works of the mapping specification.
|
SAIM-AIS-R2-JD-A.01.01 | |||||||||
PREV NEXT | FRAMES NO FRAMES |