How the Delivery of Events Is Guaranteed
There is a total ordering of event generation within the cluster that is preserved in the order of delivery to each client. In other words, if event A is generated within the cluster before event B, then client X receives event A before that client receives event B. However, the total ordering of event delivery to all clients is not preserved. That is, client Y could receive both events A and B before client X receives event A. In this way, slow clients do not hold up delivery to all clients.
All events that the server delivers (except the first event for a subclass and events that follow server errors) occur in response to the actual events that the cluster generates, except if the server experiences an error that causes it to miss cluster-generated events. In this case, the server generates an event for each event type that represents the current state of the system for that type. Each event is sent to clients that registered interest in that event type.
Event delivery follows the "at least once" semantics. That is, the server is allowed to send the same event to a client more than once. This allowance is necessary in cases in which the server goes down temporarily, and when it comes back up, cannot determine if the client has received the latest information.
Contents of an SC_EVENT Message
The SC_EVENT message contains the actual message that is generated within the cluster, translated to fit into the SC_EVENT XML message format. The following table describes the event types that the CRNP delivers, including the name and value pairs, publisher, and vendor.
Class and Subclass | Publisher and Vendor | Name and Value Pairs | Notes |
|---|---|---|---|
EC_Cluster ESC_cluster_membership | Publisher: rgm Vendor: SUNW | Name: node_list Value type: string array Name: state_list Value type: string array | The positions of the array elements for state_list are synchronized with those of the node_list. That is, the state for the node listed first in the node_list array is first in the state_list array. The state_list contains only numbers represented in ASCII. Each number represents the current incarnation number for that node in the cluster. If the number is the same as the number that was received in a previous message, the node has not changed its relationship to the cluster (departed, joined, or rejoined). If the incarnation number is -1, the node is not a member of the cluster. If the incarnation number is a number other than a negative number, the node is a member of the cluster. Additional names starting with ev_ and their associated values might be present, but are not intended for client use. |
EC_Cluster ESC_cluster_rg_state | Publisher: rgm Vendor: SUNW | Name: rg_name Value type: string Name: node_list Value type: string array Name: state_list Value type: string array | The positions of the array elements for state_list are synchronized with those of the node_list. That is, the state for the node listed first in the node_list array is first in the state_list array. The state_list contains string representations of the state of the resource group. Valid values are those values that you can retrieve with the scha_cmds(1HA) commands. Additional names starting with ev_ and their associated values might be present, but are not intended for client use. |
EC_Cluster ESC_cluster_r_state | Publisher: rgm Vendor: SUNW | Three required, as follows: Name: r_name Value type: string Name: node_list Value type: string array Name: state_list Value type: string array | The positions of the array elements for state_list are synchronized with those of the node_list. That is, the state for the node listed first in the node_list array is first in the state_list array. The state_list contains string representations of the state of the resource. Valid values are those values that you can retrieve with the scha_cmds(1HA) commands. Additional names starting with ev_ and their associated values might be present, but are not intended for client use. |
How the CRNP Authenticates Clients and the Server
The server authenticates a client by using a form of TCP wrappers. The source IP address of the registration message (which is also used as the callback IP address on which events are delivered) must be in the list of allowed clients on the server. The source IP address and registration message cannot be in the denied clients list. If the source IP address and registration are not in the list, the server rejects the request and issues an error reply to the client.
When the server receives an SC_CALLBACK_REG ADD_CLIENT message, subsequent SC_CALLBACK_REG messages for that client must contain a source IP address that is the same as the source IP address in the first message. If the CRNP server receives an SC_CALLBACK_REG that does not meet this requirement, the server either:
Ignores the request and sends an error reply to the client, or
Assumes that the request comes from a new client (depending on the contents of the SC_CALLBACK_REG message)
Clients should also similarly authenticate the server. Clients need only accept event deliveries from a server whose source IP address and port number are the same as the registration IP address and port number that the client used.
Because it is expected that clients of the CRNP service are located inside a firewall that protects the cluster, CRNP does not include additional security mechanisms.
Creating a Java Application That Uses CRNP
The following example illustrates how to develop a simple Java application named CrnpClient that uses the CRNP. The application registers for event callbacks with the CRNP server on the cluster, listens for the event callbacks, and processes the events by printing their contents. Before terminating, the application unregisters its request for event callbacks.
Keep the following points in mind when reviewing this example.
The sample application performs XML generation and parsing with the JAXP (Java API for XML Processing). This example does not teach you how to use the JAXP. JAXP is described in more detail at http://java.sun.com/xml/jaxp/index.html.
This example presents pieces of a complete application, which can be found in its entirety in Appendix G, CrnpClient.java Application. To illustrate particular concepts more effectively, the example presented in this chapter differs slightly from the complete application that is presented in Appendix G, CrnpClient.java Application.
For the sake of brevity, comments are excluded from the sample code in the example in this chapter. The complete application in Appendix G, CrnpClient.java Application includes comments.
The application that is shown in this example handles most error conditions by simply exiting the application. Your actual application needs to handle errors more robustly.
Set Up Your Environment
First, you need to set up your environment.
Download and install JAXP and the correct version of the Java compiler and virtual machine.
You can find instructions at http://java.sun.com/xml/jaxp/index.html.
Note - This example requires Java 1.3.1 or a later version of Java.
Ensure that you specify a classpath in your compilation command line so that the compiler can find the JAXP classes. From the directory in which your source file is located, type:
% javac -classpath JAXP_ROOT/dom.jar:JAXP_ROOTjaxp-api. \ jar:JAXP_ROOTsax.jar:JAXP_ROOTxalan.jar:JAXP_ROOT/xercesImpl \ .jar:JAXP_ROOT/xsltc.jar -sourcepath . SOURCE_FILENAME.java
where JAXP_ROOT is the absolute or relative path to the directory in which the JAXP jar files are located and SOURCE_FILENAME is the name of your Java source file.
When you run the application, specify the classpath so that the application can load the proper JAXP class files (note that the first path in the classpath is the current directory):
java -cp .:JAXP_ROOT/dom.jar:JAXP_ROOTjaxp-api. \ jar:JAXP_ROOTsax.jar:JAXP_ROOTxalan.jar:JAXP_ROOT/xercesImpl \ .jar:JAXP_ROOT/xsltc.jar SOURCE_FILENAME ARGUMENTS
Now that your environment is configured, you can develop your application.
Get Started
In this part of the example, you create a basic class called CrnpClient, with a main method that parses the command line arguments and constructs a CrnpClient object. This object passes the command line arguments to the class), waits for the user to terminate the application, calls shutdown on the CrnpClient, and then exits.
The constructor of the CrnpClient class needs to execute the following tasks:
Set up the XML processing objects.
Create a thread that listens for event callbacks.
Contact the CRNP server and register for event callbacks.
Create the Java code that implements the preceding logic.
The following example shows the skeleton code for the CrnpClient class. The implementations of the four helper methods that are referenced in the constructor and shutdown methods are shown later. Note that the code that imports all the packages you need is shown.
import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import org.xml.sax.*; import org.xml.sax.helpers.*; import org.w3c.dom.*; import java.net.*; import java.io.*; import java.util.*; class CrnpClient { public static void main(String []args) { InetAddress regIp = null; int regPort = 0, localPort = 0; try { regIp = InetAddress.getByName(args[0]); regPort = (new Integer(args[1])).intValue(); localPort = (new Integer(args[2])).intValue(); } catch (UnknownHostException e) { System.out.println(e); System.exit(1); } CrnpClient client = new CrnpClient(regIp, regPort, localPort, args); System.out.println("Hit return to terminate demo..."); try { System.in.read(); } catch (IOException e) { System.out.println(e.toString()); } client.shutdown(); System.exit(0); } public CrnpClient(InetAddress regIpIn, int regPortIn, int localPortIn, String []clArgs) { try { regIp = regIpIn; regPort = regPortIn; localPort = localPortIn; regs = clArgs; setupXmlProcessing(); createEvtRecepThr(); registerCallbacks(); } catch (Exception e) { System.out.println(e.toString()); System.exit(1); } } public void shutdown() { try { unregister(); } catch (Exception e) { System.out.println(e); System.exit(1); } } private InetAddress regIp; private int regPort; private EventReceptionThread evtThr; private String regs[]; public int localPort; public DocumentBuilderFactory dbf; }Member variables are discussed in more detail later.



