Java cdev & jdm

Java Packages 
for Building Client Applets 
to Access Jefferson Lab Accelerator Data 
Across the Internet

 
Prepared for
South Eastern Universities Research Association /
Thomas Jefferson National Accelerator Facility

by

Cuong C. Quach

September 12, 1997




CONTENTS

iii. List of Figures
1. Introduction
2. Background
3. Overview
4. Software Architecture and Applications Interface
4.1 Java cdev Internals
4.2 JDM Internals
5. Java cdev Class Description (cdev)
5.1 cdev.CSystem
5.1.1 Communication Management
5.1.2 Device List
5.1.3 Transaction Table
5.1.4 Optimizing Transactions
5.2 cdev.Device
5.3 cdev.Callback
5.4 cdev.Data
5.5 cdevDataEntry
5.6 cdevTimeStamp
5.7 cdev.xdrReader
5.8 cdev.xdrWriter
5.9 cdev.Packet
5.10 cdev.socketReader
5.11 cdev.responseHandler
5.12 cdev.FIFO
6. JDM Class Description
6.1 Layout Manager
6.2 Parser
6.3 Widget Set
6.3.1 Static widgets
6.3.2 Active widgets
7. Performance Issues
7.1 Clip Protocol Performance
7.2 Applet Load Times
7.3 In Java's Defense

APPENDIX A: Example Java cdev Applet
APPENDIX B: Example JDM Applets
1. Creating screens by parsing an ADL screen description.
2. Creating screens by direct instantiation of widgets
APPENDIX C: Java CDEV & JDM API

References





ii

List of Figures

FIGURE 1: THREE TIERED MODEL FOR DISTRIBUTED CONTROL SYSTEM USING Java CDEV AND JDM AT JEFFERSON LAB.
FIGURE 2: ACCELERATOR AND PHYSICS SYSTEMS INTERFACED THROUGH CDEV.
FIGURE 3: EXAMPLE MEDM PANEL.
FIGURE 4: CAPABILITIES ADDED BY JAVA CDEV & JDM PACKAGES.
FIGURE 5: JAVA EXTENSION TO CDEV METAPHOR.
FIGURE 6: JAVA CDEV CLASS STRUCTURE.
FIGURE 7: JAVA CDEV INTERFACES.
FIGURE 8: JDM CLASS STRUCTURE.
FIGURE 9: CDEV.CSYSTEM INTERNALS.
FIGURE 10: CODE FOR CDEV.CALLBACK CLASS.
FIGURE 11: CDEV.DATA OBJECT.

 




iii

1. Introduction

This document describes the development of Java cdev (Java CDEV) and the Java Display Manager (JDM). They are Java packages for developing the client in a three tiered information system for a distributed control system. Figure 1 illustrates a conceptual model of such a system. This model varies from a management information system (MIS) three tiered databases in two respects:

The information source in a MIS database is typically a database engine whereas the information source in this three tiered model is the cluster of components that directly perform the control and data acquisition in the distributed control system. This group of computers and controllers are inter-networked and communicate with a server that acts as an information gateway to external clients that request data from the inner cluster. In the MIS model, the server gathers information from the database (or group of databases) then performs some recombining of the data and sends the summary data to the client. As indicated in Figure 1, the server in this model acts as a protocol translator, as well as request concentration, and name resolution. The protocol translation allows external clients to make information requests of internal Data acquisition and control components without having to deal with the specific protocol used by the devices. The request concentration is necessary because nodes on the internal network communicate time or event critical information for control functions and must have priority access on the internal network. Hence, the server has to minimize the traffic originating from external clients. The name resolution function at the server allows clients to address components of the control system in a conceptual manner without having to know what or where it is on the net work. The client only has to know what parameter (information) is available or controlled at the device.

Figure1: Three tiered model for distributed control system using Java CDEV and JDMat Jefferson Lab.

This model has applications to any industry needing process control and monitoring (PC&M) functions.[Ref. 1] It can be used by manufacturers to export their PC&M functions to off-site locations. For manufacturers with multiple facilities, it offers a migration path to centralizing high level PC&M functions to one location - a possible cost and man power savings. This model is also being used to develop training simulators for the human subjects who are managing the PC&M functions such as operators of nuclear and chemical plants.

Currently, the packages are targeted for use at Jefferson Lab in the accelerator and physics facilities. Control systems at Jefferson Lab are ideal proving grounds because they are complex and large systems with about 50,000 control and monitorable channels (I/O points) just for the accelerator. These I/O points are spread among various buildings along the accelerator track and monitor parameters such as magnet current, magnet temperature, tunnel pressure, etc. The accelerator (CEBAF) instrumentation is responsible for controlling the beam to the required specifications for scientific experimentation. The physics instrumentation includes the equipment for conducting experiments as well as the I/O points for the particle detectors. The Java packages are slated for developing the capability to display information about the accelerator over the internet. It is intended to display information in the same format as the MEDM tool currently in use at CEBAF. As illustrated in Figure 1, Java CDEV and JDM will communicate with servers that are written using the CDEV library or servers that implement the CLIP protocol described in later sections.

2. Background

The CEBAF control system consists of a distributed network of single-board computers(SBC) running various real-time operating system software such as VxWorks. The SBCs control hardware which is interfaced to VME and CAMAC crates for functions such as beam control and data acquisition. All computers communicate with UNIX workstations which provide the user-interface for the control system. A Jefferson Lab developed package called "CDEV" (Control DEVice - not to be confused with "Java CDEV") is used to provide a uniform interface between workstations and the various parts of the control system [Ref. 2-4].

CDEV is a C++ class library that provides a common API (Application Program Interface) to the underlying CEBAF control system as well as other systems in use at Jefferson Lab. It allows client applications to share information with CEBAF devices without having to implement the different protocols necessary to communicate with each device. CDEV is public domain and can be obtained by anonymous ftp from ftp.cebaf.gov/pub/cdev. Currently, CDEV provides a standard interface for EPICS (a widely used package for controlling and querying distributed hardware), and ACE (Adaptive Communications Environment) [Ref. 5] which is used for communications with the CEBAF Online Data Acquisition System (CODA). CDEV has been interfaced to TCL to allow clients to be written which display data using the TCL interface.

CDEV implements a two layer abstraction that allows a heterogeneous set of control software and associated protocols to be interfaced with one common "device-services" metaphor (Figure 2). The upper layer, (device layer) presents the control system to the application software as a series of abstract devices which provide services requested by messagessent to the device. The lower layer (service layer) provides the interfaces to the control system software and dynamically loads a service when it is requested by the application software through a messagesent through a device.

An application that communicates with a CDEV server can treat accelerator and physics devices as named entities that can be sent messages. Each device/message pair is mapped, by the server (written using CDEV), to a specific service available in the underlying control system. This mapping of abstract devices to the services permits creation of abstract devices that, in reality, are serviced by multiple control system components. Furthermore, devices are referenced by name and are mapped to a particular controller via a "name service". This allows the implementation of the underlying service to change without breaking the client level code.

Figure 2: Accelerator and Physics systems interfaced through CDEV.

Data from the control system is currently displayed using MEDM (Motif Editor and Display Manager) [Ref. 6]. MEDM provides for the creation of graphical panels, such as Figure 3, which represent various parts of the control system. Each panel displays only a small subset of the 50,000 I/O points. Jefferson Lab operators and researchers uses over 1,000 of these panels to monitor and control the operations of the accelerator. For the accelerator, these panels get real-time updates from the control system through the EPICS Channel Access protocol. Where applicable, these screens also contain buttons and other input widgets for setting parameters in the control system.

Figure 3: Example MEDM panel.

MEDM is based on the X-windows system. The tool allows for panel creation, and panel execution. In the creation mode, the user is given a canvas on which to place various widgets. These widgets include meters, bar charts, strip charts, x-y plots, etc. Text and static graphics widgets are also provided. Properties may be assigned to these widgets to specify the I/O point to connect, color to display etc. Panels such as Figure 3 are created in MEDM and saved as an ASCII screen description. This document will refer to these ASCII screen descriptions as ADL (ASCII Display List) files. In the execution mode, the panel specified by the ADL file is display and the connections to the control system are made. MEDM can be used to deliver information to nodes outside CEBAF but require the remote node to be an X-server.

3. Overview

Prior to implementation of Java CDEV and JDM, it has been possible to connect to CDEV using the TCL interface while the MEDM interface connects to accelerator devices using the EPICS and Channel Access libraries as illustrated in Figure 4. With Java CDEV and JDM, CDEV connectivity has been extended to the Java environment so that the capability to display graphical panels showing accelerator activity can be easily exported over the internet. Java CDEV has been written to extend CDEV's device/service metaphor to the Java environment and makes connecting to a CDEV server transparent. JDM has been written to create MEDM-like displays without requiring X-servers.

Figure 4: Capabilities added by Java CDEV & JDM packages

While Java CDEV and JDM are not intended to replace the TCL and MEDM libraries, they add the capability of creating internet applets/applications to display Jefferson Lab\x9b s accelerator and physics data in a web browser. These packages also allow users to create client application to access CEBAF's control systems and display the data in the same manner as MEDM. Java CDEV uses CLIP to communicate with the CDEV server while the CDEV server connects to the control system devices through EPICS and ACE. This lets clients treat the control system at the server as a series of devices as illustrated in Figure 5. Java applications will obtain accelerator data through a server written using CDEV's server class [Ref. 8]. The server acts as an internet "gateway" to CEBAF's subnet and will communicate with clients that use the CLIP protocol [Ref. 9]. Data from the server is received by the Java CDEV package and displayed by the widgets in the JDM package.

Figure 5: Java extension to CDEV metaphor.

In developing Java CDEV, there are three major objectives that guided the design and coding effort.

  1. It has to provide an interface to the user application that is similar to its C++ counterpart.
  2. It must provide an interface so that MEDM-like panels can be created by the application.
  3. It has to be efficient with system resources at the client node since it will most likely run embedded in a browser.

The Java CDEV, like its C++ counterpart, provides a common interface to services available in the accelerator control system. It allows applets to treat the control system as a series of devices that are sent messages. When communicating with the server, these device abstractions are referenced by name and are not bound to physical devices or services at the client applet. The binding occurs on the gateway server. The communications that take place between the applet and the CDEV gateway is handled very much like a transaction processing system where the client (applet) submits requests and the server replies to those requests.

To display output from the CDEV devices, users can interface to the Java CDEV package by using their own interfaces or by using widgets provided in the JDM package. It is possible to create a graphical display by having JDM parse an ADL file created using MEDM. This permits applets to be developed that leverage on the large inventory of MEDM screens currently in use at Jefferson and other research labs. Alternatively, the applet loaded will itself be the graphical panel. The panel will have a series of GUI objects that are connected to the server. Each of these GUI objects will instantiate one or more devices and post transactions to those devices. The GUI objects can initiate both asynchronous or synchronous transactions to the server and the Java CDEV pack age will manage the transaction processing so that it is transparent to the GUI object. Additionally, these GUI widgets can get responses from the CDEV package either by way of a generic data object or a callback function that the GUI registered to execute when the response arrives.

Because of the interpreted nature of Java applications, great emphasis is placed on making Java CDEV very efficient in both class loading and execution. This includes minimizing the number of classes to reduce the time required to load the applet and all its classes across the internet. However, this requirement may be relaxed with future releases of Java which promise to improve applet transport times. To reduce execution time, many of the methods are final so that the Java virtual machine has one less step in dynamic linking. Additionally, transaction processing in CDEV is managed in such a way as to optimize network bandwidth and minimize requests to the gateway. Network bandwidth is optimized by buffering transmissions to the server until there is enough data to fill an IP packet. Transactions to the server are minimized by maintaining a list of outstanding transactions so that if multiple requests come from the application code to the same device and attribute, the duplicate requests are not sent to the server.

4. Software Architecture and Applications Interface

4.1 Java CDEV Internals

Figure 6: Java CDEV class structure.

Java CDEV consists of 13 Java classes that carry out the overall functions of message delivery to the server and call back or data delivery to applets (Figure 6). Of these, applets only need to interface with 6 classes; other classes handle specifics for this implementation. Java CDEV's API classes are:

If one can imagine the cdev.CSystem object as a "software bus" between the applet and devices in the server subnet, then thecdev.Device objects represent the devices connected to the bus and the cdev.Data objects are the data signals that traverse the bus. A cdev.DataEntry object encapsulates each piece of raw data placed inside the cdev.Data object. The cdev.Callback objects provide a way for the applets to get responses/events from the bus. The cdev.TimeStamp class provides a standard way for passing time stamps between the applet and devices on the network. The implementation classes, which consist of cdev.TagTable, cdev.Packet, cdev.FIFO, cdev.socketReader, cdev.xdrReader, cdev.xdrWriter, and cdev.responseHandler, provide the data management and formatting between the applet and server. In general, the cdev.responseHandler class manages the callback deliveries; the cdev.xdrWriter, cdev.xdrReader, and cdev.socketReader manage the networking and XDR conversions; the cdev.Packet handles CLIP conversions; and the others handle internal data structures.

Applets can easily interface to the Java CDEV package. As illustrated in Figure 7, each applet instantiates a cdev.CSystem object for communicating with the server. With the cdev.CSystem object created, the applet can call the getDevice() method in the cdev.CSystem class to create any number of devices. Device names must match with names known to exist server side. String messages can then be sent to devices with or without accompanying data. Data to be sent to devices are first encapsulated in cdev.Data objects. This is done by first instantiating a cdev.Data object; then calling its insert() method. Data is sent to the devices on the server side by calling one of three send() methods in the cdev.Device class. Depending on the control flow desired, the applet may either wait for cdev.Data objects to return or implement a callback function that gets called when the server replies. If a callback is desired, the applet must implement thecdev.Callback class and have an execute() method. Appendix A gives an example applet showing the general steps to interface to the Java CDEV package.

Figure 7: Java CDEV interfaces.

The cdev.CSystem class is the heart of the Java CDEV package and a central point to efficiently manage transactions. It coordinates the activities of the other objects to perform networking, transaction processing, and callback delivery. When the applet calls one of the send() functions in cdev.Device, the transactions are actually passed to the cdev.CSystem object. Messages passed to the cdev.CSystem object are treated as requests to the server. How these requests are handled depend on what is in the transaction table at the time of the send call. Typically, the transaction gets entered into a transaction table and is then turned into a cdev.Packet and submitted to the output queue. Transaction entry and queue flushing is optimized to reduce the network load. The output queue to the server is not flushed until either the applet calls the cdev.CSystem's flush() method or the data in the queue can fill up an IP packet (16KB). A flush also occurs when cdev.Device's send() method is called. This exception is necessary to permit the send to complete a synchronous transaction. The other two send methods, sendCallback() and sendNoBlock(), are asynchronous in nature and will not cause applet execution to block.

The cdev.CSystem is designed so that the applet code may have multiple references to the same device. (e.g. multi-threading) The multiplicity is handled by maintaining the transaction table so that each entry in the table represents one unique request sent to the server. Requests from the user code are considered the same if they come through the same device and have identical message text. The transaction table is optimized by allowing multiple sends from the applet to be grouped together if they request the same data. When transactions are grouped, only one request is sent to the server. When the server replies, the cdev.responseHandler passes the reply to each requester in the group. It does this by either posting the return data or executing the callback method implemented in the applet.

Referring back to the virtual bus paradigm, cdev.Data objects represent the data that traverse the virtual bus. The cdev.Data class encapsulates raw data for transport between server and client. The raw data can range from a single byte to a virtually unlimited (to the extent that the Java Virtual Machine can handle) number of multi-dimensional arrays of Java types. Raw data inserted into a cdev.Data object can be associated with a string or integer tag. The tag can be used to retrieve the raw data from the cdev.Data object.

The cdev.Device class is used by the applet to create abstractions of real devices/services available at the server. This class implements the three send functions that allow the user to send messages to the actual device/service on the server side. The applet requests these device objects using the cdev.CSystem's getDevice() method. Device requests have been centralized at the cdev.CSystem class to avoid multiple copies of the same device from being created and to make device management easier. It also presumes that specific device names are known either in advance or gotten from an ADL file. To communicate with the actual device, the applet will use one of the three send methods in cdev.Device to send a string message with the associated data or callback references. The data is packaged in a cdev.Data object and the callback is a reference to any object that implements the cdev.Callback interface.


4.2 JDM Internals

Java CDEV has been interfaced to the JDM package to permit graphical display of information from the control system. JDM can be used as an alternative to directly interfacing with the Java CDEV package. The JDM package (Figure 8) consists of a layout manager and a set of widgets that allows windows to be created in a similar manner as MEDM screens. The package is flexible enough so that windows can be created from Java code or from an ASCII description (the same files as used by MEDM). The package contains a parser that can build a window from an ADL file description. The layout manager is different from Java layout managers in that it is based on the Canvas and allows the specification of the exact size and location of the widget to be placed on the canvas. The layout manager handles the repainting of the objects and delivers events to the widget at which the mouse is pointing. The package supports both active and static widgets. Static widgets are used to build the artwork in the window and are not attached to any devices (hence not updated). Active widgets allow data to displayed using instrument metaphors such as meters, bar charts, etc. Static widgets can be made active by attaching a DynamicAttribute object and connecting it to a device-attribute combination. This is useful for building blinking lights or status flags, etc.

Rather than focusing on the unwieldy number of classes illustrated in Figure 8, JDM is more easily understood by its three groups. They are the layout manager, the parser, and the widgets. The layout manager consists of the jdm.Display, jdm.adlColor, and jdm.Canvas classes. In this group, the jdm.Display is the public interface to the user code. The parser is mostly contained in the ADL class which is also the public interface. When parsing an ADL file, each widget is also responsible for some of the parsing. This is mostly to get parameters specific to the widget. The widgets comprise the remainder of the classes.

JDM can be used to build display windows from an ADL file. An example of the code to do this is given in Appendix B part 1. The parser is a content handler designed to load files across the net from the same node that delivered the HTML (Hyper Text Markup Language) document. In the applet, it is only necessary to create one parser (i.e. adl object) but it is necessary to create a URL (Uniform Resource Locator) connection for each file that is to be displayed. It is also necessary to create a layout manager (i.e. an jdm.Display object) for each window. In the sample code which loads two files, an jdm.Display object is created for each file. It is also essential to set the cdevSystem reference so that the widgets created in the windows will all connect to the same cdev.CSystem object.

JDM can also be used without the parser. The classes in the widget set have constructors for direct instantiation and supporting methods for setting channel names and measurement ranges. An example of this is given in Appendix B part 2. The essentials for direct instantiation are similar to that of windows from ADL files. A cdev.CSystem must still be created to connect to the server. Each window to be created still requires an jdm.Display object. However instead of creating a parser, the widgets are individually instantiated and given the references to the cdev.CSystem and jdm.Display object.

Figure 8: JDM class structure.

5. Java CDEV Class Description

5.1 cdev.CSystem      API

The cdev.CSystem class is the main class that will interface to user applets. Its main attributes are a device list, a transaction table, and an input queue (Figure 9). Its uses many of the CJE internal classes to accomplish its primary responsibilities. These include:

  1. Manage communications with the CDEV server
  2. Manage the list of all devices
  3. Maintain a transaction table for current outstanding transactions
  4. Optimizing transaction processing to minimize network usage.



5.1.1 Communication Management

The cdev.CSystem manages communication with the gateway using two internal classes. It uses an cdev.xdrWriter object to handle outgoing data and a cdev.socketReader object to handle incoming data from the socket. The cdev.xdrWriter has its own internal queue to optimize outgoing communications as mentioned in section 4.1. When instantiated, cdev.CSystem establishes a connection with the server and passes the socket to a cdev.socketReader and cdev.xdrWriter objects. The cdev.xdrWriter creates a buffered connection to the socket and then waits for output data in the same thread as the cdev.CSystem.

The cdev.socketReader is launched as a daemon thread running at a higher priority to monitor server input. This prevents cdev.CSystem from blocking when the input buffer is empty. When data arrives from the server, cdev.socketReader will enqueue the incoming data in the packet queue (FIFO) and notify the cdev.responseHandler object that there is data to be processed. The cdev.responseHandler is also launched by cdev.CSystem at startup as a daemon thread with a higher priority than cdev.CSystem. Separately threading these two objects allows implementation of asynchronous message handling using Java's wait()/notify() mechanism.

Figure 9: cdev.CSystem internals.



5.1.2 Device list

The device list is used to manage device instantiations in the cdev.CSystem object. It prevents user code from making multiple device objects with the same name. In order to keep track of devices created, the cdev.CSystem object uses a hash table to catalog all devices instantiated. When the user code requests a new device, this hash table is first checked to see if the device is already created. If so, then the existing object is passed to the user code. This necessitates the user to call a cdev.CSystem method to create a device instead of the traditional way of calling the cdev.Device constructor. Methods are available for device removal.



5.1.3 Transaction table

The transaction table is used to log all transactions initiated by the user code through one of the device.sendxxx() methods. Each transaction record in the table contains a transaction number, the device reference, the message string, a callback/data reference, and a reference to the last value returned from the server for this request. The message string is space delimited and consists of a verb and an attribute. For transaction grouping and optimization purposes, the first field is considered to be the verb. In the current implementation, no other format restrictions are placed on the message so multiple attributes are permissible.

The transaction table is used to manage transactions (requests) to the server in such a way as to minimize the network bandwidth requirement. This is accomplished by grouping similar or identical transactions together and only submitting one request to the server. Transaction grouping is based on the verb in the message that is to be sent and is only performed for the four standard verbs: monitorOn, monitorOff, get, set.. The get and set verbs are used to post transactions to retrieve or set, respectively, the value of an attribute of a device. The monitorOn verb is used to inform the server to send an update to the client every time an attribute's value changes. monitorOn requests remain effective until a monitorOff message is sent to the server.



5.1.4 Optimizing transactions

Duplicate requests are defined as requests where the device and message are identical and the device context has not changed from the previous request. cdev.CSystem handles duplicate requests by vectoring the callback references from the requests and delivering the server response to all requesters on the callback list. The transaction table also caches the most recent response to a monitorOn request. This is so that the second and subsequent requester of a monitor, who's requests are not sent to the server, will get an immediate reading on the most recent value for that parameter without having to wait till the next server response to that monitor. All entries into this table are made with the enterTrans() method call in cdev.CSystem. The method implements the following rules to optimize transaction processing:

  1. for any single device, monitorOn messages containing the same attribute will have their callbacks vectored.
  2. for any single device, get message with an attribute that is already monitored will immediately return the cached result from the monitor if a result is available; otherwise, it is vectored with the monitorOn transaction.
  3. monitorOff messages sent for a device will not be sent to the server unless there is only one callback object associated with the transaction. In cases where multiple callback objects are associated with a transaction, the monitorOff will only cause the specific callback to be removed from the list.

Responses from the server are handled by coordinating two separate threads to handle socket input and callback delivery. The cdev.socketReader object "listens" for server response at the socket. When the socket is empty, this cdev.socketReader thread blocks. When responses arrive, it reads the packets into a packet queue. It also notifies the cdev.responseHandler object that there is data in the input queue to be processed. The cdev.responseHandler thread will dequeue packets from the queue and match the transaction number of the dequeued item to a transaction in cdev.CSystem's transaction table. Once a match is found, the data is delivered to all the references in the callback vector in the table. Once callbacks have been delivered, the callback list is trimmed of all non-cdevCallback references.

In this implementation, it is assumed that monitorOn messages will be posted with the sendCallback() method. The transaction processing algorithm allows for get messages to be sent with the sendCallback() method. As stated in case 2 above, get messages are also vector onto the callback list in the transaction table. This creates a problem with processing monitorOn transactions where there are multiple cdev.Callback references in the callback list. There is no way to distinguish whether a callback reference came from a monitorOn message or a get message. In order to prevent get message from receiving multiple results (hence behaving like a monitorOn message), an indirect reference is added to the callback list instead of the real callback reference. The indirect reference points to an alternate transaction to be processed and deleted. This is achieved by vectoring an Integer object in the callback reference


5.2 cdev.Device      API

cdev.Device objects are logical representations of devices available in the control system. To maintain abstractness, only the name is known. The mapping to locate the specific device referenced by a name is done by the gateway. On the client side, these objects allow the user code to reference and send messages to the device.

This class has a constructor Device(), and attach() methods to be compatible with the C++ version. Like the C++ version, there is an alternative way to get devices. While the device class has a constructor, the application code can also call the getDevice() method in the cdev.CSystem object. This allows the cdev.CSystem object to check for duplicate cdev.Device.

cdev.Device objects communicate with their associated service by using the: send(), sendNoBlock(), sendCallback() methods. The send() method provides a synchronous communication mechanism to the device services while the sendNoBlock() and sendCallback() are asynchronous. Each of these calls enter a transaction into the transaction table in the system. If the context is changed, the context will also be sent, otherwise, no context is sent int he message packet to the gateway.


5.3 cdev.Callback      API

The cdev.Callback class is an abstract class that only has an execute method. It is a mechanism for the cdev.CSystem to deliver callbacks. Application code or GUI objects that require responses from the server to trigger some action should implement the execute function in this class. When a transaction is posted with a callback object (via the sendCallback() method) the response handler will call this method when the server replies to the transaction associated with this method. The code for this class is given in Figure 10 blow.

Figure 10: Code for cdev.Callback class.


5.4 cdev.Data      API

This class encapsulates the raw data for transport between the applet and the server. Each cdev.Data object is a vector of self-describing entries called cdev.DataEntry as seen in Figure 11. A cdev.Data object is typically created by the applet and passed to the cdev.CSystem object to be delivered to the server. Raw data is put into a cdev.Data object using the insert() method. The insert() method will actually put the raw data into a cdev.DataEntry object and then add the entry into the cdev.Data container. The insert() method currently supports all Java native types as well as Java Objects which include arrays and the cdev.TimeStamp object.

Figure 11: cdev.Data object.

During the insertion, the data entry is associated with a tag. The tag can be either an integer or a string. If the new entry, being inserted, uses a tag that is already being used, the older entry is replaced. Tags are kept in a global tag table that is not visible outside the Java CDEV package. However there are methods in the cdev.Data class for manipulating this tag table. These methods include tagC2I(), tagI2C(), insertTag(), changeTag(). The following tags are in the global tag table by default:

Standard tags in the Global Tag table
Integer Tag
String Tag
0
"value"
1
"status"
2
"severity"
3
"time"
4
"units"
5
"displayHigh"
6
"displayLow"
7
"alarmHigh"
8
"alarmLow"
9
"warningHigh"
10
"warningLow"
11
"controlHigh"
12
"controlLow"
13
"bitMask"
14
"file"
15
"class"
16
"device"
17
"message"
18
"verb"
19
"attribute"

The main manipulation done to cdev.Data objects in the Java CDEV package is to convert the object into a byte array for transmission to the server; and to recreate the data object from byte arrays sent by the server. This is done with the xdrExport() and xdrImport() methods in the cdev.Packet class and is transparent to the user's applet.


5.5 cdev.DataEntry      API

Objects in this class are used to encapsulate raw data for inserting into the cdev.Data container. This class provides a self describing data object that includes type and array sizes information on the raw data. For multi-dimensional raw data, there is also internal data to give the offset and length of each dimension. Individual parts of the cdev.DataEntry can be accessed through methods in this class.


5.6 cdev.TimeStamp      API

This is a Java implementation of the time structure as defined in the POSIX standard. It uses two integers to identify the time. It extends Java's Number class so that it can be treated as types other than integer.


5.7 cdev.xdrReader

The cdev.xdrReader class handles data conversion from the network's XDR format [Ref. 7] to data types supported in Java. It can be instantiated as a socket connected object or a buffer connected object. When connected to a socket, the caller can read data directly from a buffered input socket. When there is no data at the socket, a call to any of the get functions will cause the object to block until data is available at the socket. When connected to a buffer, the socket will read from the given buffer and will throw exceptions when the buffer is exhausted.

This class is heavily used for unpacking data from the socket and for converting the stream data into CDEV objects. It is used in the cdev.socketReader, cdev.Data, and cdev.Packet. Unlike its C++ counterpart, the get methods in this cdev.xdrReader have not been overloaded because they do not take any input parameters. Instead of returning a status as in the C++ implementation of CDEV, they return the value read. This is because Java has a well designed exception mechanism for indicating failures.


5.8 cdev.xdrWriter

The cdev.xdrWriter class performs data conversion from Java types to XDR format, which is then ready for network transport. Like the cdev.xdrReader class, this class is also polymorphic in that it can write to a socket or a buffer. The former behavior saves from having to have an extra class just for socket output. The later behavior makes this class operate in a compatible manner with its C++ counterpart. Unlike the cdev.xdrReader, the put() functions in this class are overloadable because there is type information in the formal argument.

When instantiated with a Java Socket object, this class will write to a buffered output stream through a circular self-expanding queue. In the socket connected mode, it is intended that the user will call the enqueue(), dequeue(), and flush() methods to write data out to the socket. The queuing allows for more efficient use of network bandwidth. Hence the packets of data being sent to the server will concatenate multiple requests to avoid sending a multitude of single request packets. Each object enqueued is a transaction request in the form of a byte array that has been previously converted by other instances of the cdev.xdrWriter. The final packing into the socket is not performed until the user calls the flush() method. This allows insertion of a packet length and packet count in the first 2 fields of the stream going out the socket to meet CLIP protocol requirements [Ref. 9].

The default constructor will create an internal self expanding byte stream. This mode is used in converting CDEV objects into byte streams either for enqueuing or further processing. A method is provided to get a reference to this internal byte stream.


5.9 cdev.Packet

This class implements the transaction packing protocol outlined in the CLIP documentation [Ref. 9]. It is the object created when a transaction has to be sent to the server. It has methods to convert itself to and from a serial stream. The format for the serial stream is described in detail in Ref. 9 and is not repeated here.


5.10 cdev.socketReader

This cdev.socketReader class is a threaded input stream monitor for use primarily in the cdev.CSystem class. It runs as a daemon thread so that it does not prevent the Java state machine from terminating when other threads have completed execution. This extra class is necessary because Java's stream classes will block when no data is available in the input stream. Using an extra thread is the typical technique in Java to handle socket communication. Without a separate thread for socket inputs, it was found that cdev.CSystem objects will block waiting for input and not respond to any other requests.

The cdev.socketReader class performs the first layer of unpacking of server data as specified in the CLIP protocol. When data arrives, the multi-packet message is broken into a series of opaque byte arrays each comprising one transaction response. Each byte array is enqueued into the packet queue in the cdev.CSystem class. The cdev.responseHandler is then notified that there are transactions in the queue to be processed. Because separate threads are performing queue operations, there is a slight performance penalty because the packet queue has to be locked during each separate operation. The queue lock is necessary because during the enqueue operations, it may be necessary to enlarge the queue. In the queue enlargement operation, a new queue twice the size as the original one is actually created and the entries in the original queue is copied to the new queue. The garbage collector is then involked to recycle the memory used by the original.


5.11 cdev.responseHandler

This class is used in the cdev.CSystem class to handle responses from the gateway server. It runs as a daemon thread and is awaken by the cdev.socketReader thread when ever there is data in the system's packet queue. Its primary function is to take packets from the packets queue and match them by transaction number with entries in the transaction table to get the callback function references and finally to dispatch the callbacks if necessary.


5.12 cdev.FIFO

This is a FIFO queue used in the cdev.CSystem object to implement the packet queue. It is implemented as a self-expanding array of objects. This object tracks its occupancy rate. When this rate exceeds a preset percentage, it create another array twice the size of the original and copies the entries from the original to the new array. The reason for having a separate class instead of using a Vector class is because the Vector class re-indexes its array each time an element is removed. This can be somewhat inefficient when the communication load is large.


5.13 cdev.TagTable      API

This class contains the static tag table that is used in the cdev.Data class. Its methods are accessed through the cdev.Data class.



6. JDM Class Descriptions

6.1 Layout Manager      API

The layout manager handles the display of widgets in the window. This functionality is encapsulated in the jdm.Display class and the jdm.adlCanvas class. It has a canvas on which widgets are drawn and maintains list of widgets that have been added to the canvas. The jdm.Display handles the adding and removing of widgets while adlCanvas handles the widget repaints and user events. The adlColor class is a wrapper around the color index that is used when loading from an ADL file. It is not needed in direct instantiation of widgets. This layout manager differs from JDK managers in three respects. First, widgets can specify where exactly they want to be on the canvas by specifying their clip rectangle. This can be done in direct instantiation as well as from an ADL file. This feature is important because it allows panels to be created that are displayed identically on different platforms without getting the artwork reshuffled. A side effect of using the canvas is that it clips the display if the window area is smaller than the canvas. The second deviation from JDK is when creating the widgets by either method, a reference to the display (jdm.Display object) is given to the widget so that it (the widget) can request a repaint from the display. Lastly, this display manager places widgets in a canvas and passes mouse and keyboard events to the widget. The JDK managers only pass events to the canvas.


6.2 Parser      API

The parsing function is divided between the jdm.adlParser class and the constructors of the display widgets. It is organized in the following fashion. The jdm.adlParser class contains a tokenizer and a syntax handler for working with the first level of an adl screen description. This level specifies the widget desired. When the jdm.adlParser determines the widget desired, the constructor for that widget is called to process the subsequent information. This information consists of a standard set of descriptors that specify the details for the widget. Because these detail descriptors are standard for describing different widgets, much of the parsing code for these descriptors have been factored into the superclass jdm.DisplayItem. There are also several small classes whose primary reason for existing is to handle ADL file syntax. These include the jdm.BasicAttribute, jdm.ObjectAttribute, jdm.PlotCommAttribute, and the jdm.IoAttribute class.

One last point to note is that the adlParser implements Java's contentHandler interface. This allows it to retrieve files from the same URL connection that delivered the HTML document. In order for the parser to work properly, it must have a reference to a cdev.CSystem and an jdm.Display object. These references are assigned by the setDisplay() method as described in the jdm.Display API. Once the file has been retrieved from across the net and the cdev.CSystem and jdm.Display references are known, the parser can commence.


6.3 Widgets

The widgets interface to the Java CDEV package in the manner described in section 4.3. All have a similar pattern of methods and inherit from the jdm.DisplayItem superclass. Though the widgets are divided into two groups, all widgets have two constructors and a paint method. One constructor for use with ADL file parsing and the other for direct instantiation. Widgets in the JDM package can be classified as either static or dynamic.



6.3.1 Static widgets

Static widgets can be used to create static art work in the window. They are typically not connected to the server to get updated data. Accordingly, these classes will not contain the execute() methods or implement the cdev.Callback class. However, they can optionally be made active by adding a DynamicAttribute object. This is done by calling the attachDynamicAttribute() method implemented in jdm.DisplayItem. This DynamicAttribute object will handle the actual transaction posting and serves as the callback. When created with a DynamicAttribute, the static widget will become dynamically visible depending on the value of the channel. A DynamicAttribute object can be added to a static widget by calling the attachDynamicAttribute() method. Currently implemented static widgets include:

  1. jdm.Oval
  2. jdm.Arc
  3. jdm.Rect
  4. jdm.PolyLine
  5. jdm.NGon
  6. jdm.Text




6.3.2 Active widgets

Active widgets are a bit more complex and have their own methods for interfacing with the Java CDEV package instead of using a DynamicAttribute object. In addition to the constructors and the paint method, active widgets have an eventHandler() and implement the execute() method so that they can be recast as a cdev.Callback object when posting transactions with the cdev.CSystem object. In most cases, active widgets inherit from the analogItem class which has a default implementation of the execute() method. Active widgets include:

  1. jdm.Meter
  2. jdm.Bar
  3. jdm.StripChart
  4. jdm.Cartesian
  5. jdm.MessageButton
  6. jdm.jdm.TextUpdate
  7. jdm.Valuator



7. Performance Issues

7.1 CLIP protocol performance

A very thin client consisting of the Java CDEV package and a few lines of test code was used to measure the callback rate. It was found that the Java CDEV package could deliver callbacks at a rate of approximately 80 per second. The test consists of a C++ client (Also very thin) which continuously submits "set attribute" transactions to a server running on the same node. The server then sends the updates to the Java client running at another node in the CEBAF intranet. The Java client does nothing in the callback method accept summing the hits and calculating the transaction time per thousand hits. Since the Java client does no processing, the 15ms should be treated as a best performance for Java CDEV on the test platform running JVM 1.0.2. This test was conducted during low net usage period; as with the tests discussed immediately following.


7.2 Applet load times

The JDM package is designed to display panels from both Java code and ADL files. A comparison has been made of the load time incurred for both techniques by measuring the load time for a display consisting of four (meter, slider, bar, text) widgets. The result indicates that loading display panels from an ADL file takes almost twice as long as loading from applets (See table below). This may be because the ADL file is bigger than the Java code.

Parsing versus direct instantiation

Average Load Time(ms)
File size(bytes)
Panels from ADL file
649
3979
Panels from Java Code
357
2236


7.3 In Java's defense

A web survey indicates that performance for Java code is slated for much improvement. With recent versions of JIT (Just-in-time) compilers, Java code speed has been tested on various platforms and found to perform as much as five times faster than interpreted code.[Ref. 10] Some speedup can also be expected in the graphics logic although not as significant. Surveys indicate that JITs will accelerate graphics codes in the 10% to 20% range. Sun predicts a 10 fold overall performance improvement with JIT compilers.[Ref. 11] It is reasonable to project that the Java CDEV transaction processing code will run several orders of magnitude faster with JITs and a more efficient JVM. This is because a majority of the speed improvement coming from JITs will be in the looping and method calling logic.[Ref. 11] The expanded code size might have a slight negative impact on performance because JIT compiled code is typically larger. Looking further into the future, Java cast in silicon is expected to give another performance boost to Java applications. Sun Microelectronics' picoJava I design is projected to give a 5-10 fold increase in speed over JIT compiled code.[Ref. 12]

One additional concern is the way applets are loaded. The current Java environment will load the Java CDEV and JDM classes in separate network transactions making poor use of network bandwidth. With eventual migration to Java 1.1, both packages can be archived and compressed. Then the transfer will be done in one network transaction.



Appendix A. Example Java CDEV Applet

The following is an example of the minimal code necessary to interface to CJE. All three methods of sending messages to devices use the same steps except for the send call. This example demonstrates sending messages to devices using a callback transaction. The steps are:

  1. creating a system object - which will connect to the server;
  2. creating a device reference;
  3. creating a callback reference;
  4. sending a message using the device methods;
  5. flushing the message out the port to the server.
  6. The callback class is only required for the sendCallback method.


//---------------------------------------------------------------//
// Simple example of direct interface to CJE package.
//---------------------------------------------------------------//

import java.lang.*;
import java.io.*;
import cdev.*;

public class cjeDemo
{

  	public static void main (String[] argv)
  	{
    	//----- create a system -----------------------------//
    	CSystem  mySystem = new CSystem(); 
    
    	//----- get a device from the system ----------------//
    	Device myDevice = mySystem.getDevice ("device1");

    	//----- create a callback object --------------------//
    	devCB myCb = new devCB(mySystem, myDevice);

    	//----- post a monitor on attribute 1 of device -----//
    	myDevice.sendCallback("monitorOn attrib1",null, myCb);

    	mySystem.flush();

  		while (true);  // infinite loop
  	}

}


class devCB implements cdev.Callback
{
  	CSystem machine = null;
  	Device Dev = null;
  	int count = 0;

  	public devCB (CSystem sys, Device de)
  	{
    	machine = sys;
   		Dev = de;
  	}
  
  	public void execute (int	  CompletionCode  
				,Device  device
				,String  message
				,Data    result   )
  	{
    		count++;
    		System.out.println ("****  "+count+"  **** Callback executed");
    		System.out.println ("\t"+result.toString("result delivered ") );
    		Data data = new Data();
    		data.insert ("value",count);
    		Dev.sendCallback("set attrib1", data, (cdevCallback)this);
    		machine.flush();
  	}
  
}


AppendixB. Example JDM Applets

B.1 Creating screens by parsing and adl screen description.

This applet creates a screen by parsing an ADL screen description. It is implemented here.

import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
import jdm.*;
import cdev.*;

public class parserTest extends Applet {

	public URL		url;
	URLConnection 		fp;

	//***************************************************************************//
	/* The code to load adl file and create display.
    	*/
	public void init() 
	{
		CSystem			system = null;
		Display			display = null;

		//----- connect to sever --------------------//
		system = new CSystem();
		
        	try  {
	   		//----- create display 1 -----------//
		       url = new URL(getCodeBase(),"fourThings.adl");
		    	fp = url.openConnection();
		    	if (fp != null) {
				display = new Display ("fourThings.adl", system);
				adlParser parser = new adlParser ();
				parser.setDisplay (display, system);
				parser.getContent(fp);
		    	} else
				System.out.println("Can not fetch file");
	   	} catch(Exception e)  {
			System.out.println(e);
		}
	
	}


}    


B.2 Creating screens by direct instantiation of widgets.

This applet illustrates the Java code needed to create a screen by directly instantiating the widgets. It is implemented here.

import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
import jdm.*;
import cdev.*;


public class createDisplay implements Runnable 
{

 	public void run ()  
	{
		CSystem		system = null;
		Display		display = null;
		Colormap	cm = new Colormap();


		//----- Create the client object to connect server -------------//
		system = new CSystem();
		
		//----- Create the display which creates the canvas ------------//
		display = new Display("Compiled Display", system);
		display.setAttributes(new  Rectangle(500,100,400,400)
				        ,new adlColor(53)
				        ,new adlColor(57) );

		//----- Create the GUI widgets and add them to the display -----//
		try {

 		   //----- Create a meter -----//
 		   Rectangle meterRec = new Rectangle (140, 100, 72, 75);
		   Meter voltMeter = new Meter(meterRec
						  ,Color.white
						  ,Color.blue
						  ,display
						  ,system
						  ,"device1.attrib1");
		   voltMeter.setRange (0, 100);
 		   display.addItem ( voltMeter );

 		   //----- Create a slider -----//
		   Rectangle sliderRec = new Rectangle (80, 250, 240, 34);
		   Valuator slider = new Valuator (sliderRec
						      ,Color.white
						      ,Color.green
						      ,display
						      ,system
						      ,"device1.attrib1"
						      );
		   slider.setRange (0, 50);
		   display.addItem(slider);

		} catch (Exception e) {}

		system.flush();   // flush all pending transactions
	}


}   // end nonParserDemo class


References

  1. Greg Paula; "Process control takes to the Net"; Mechanical Engineering; December 1996 Vol. 118, No 12.

  2. Chip Watson, Jie Chen, Danjin Wu, Walt Akers; "Introduction to CDEV - Overview of the Control Device Interface"; Version 1.4, October 24, 1996; TJNAF - Thomas Jefferson National Accelerator Facility. http://www.cebaf.gov/cdev/doc_1.4/cdevIntroduction.html.

  3. Chip Watson, Jie Chen, Danjin Wu, Walt Akers; "CDEV Reference Guide"; Version 1.4, October 24, 1996; TJNAF - Thomas Jefferson National Accelerator Facility. http://www.cebaf.gov/cdev/doc_1.4/cdevReference.html.

  4. Chip Watson, Jie Chen, Danjin Wu, Walt Akers; "CDEV Tutorial - Techniques for using the Control Device Interface"; Version 1.4, October 24, 1996; TJNAF - Thomas Jefferson National Accelerator Facility. http://www.cebaf.gov/cdev/doc_1.4/cdevTutorial.html.

  5. D.C.Schmidt, "The ADAPTIVE Communication Environment: Object-Oriented Network Programming Components for Developing Client/Server Applications", Proceedings of the 12th Annual Sun Users Group Conference, (San Francisco, Ca), pp. 214-225, SUG, June 1994.

  6. Anderson, Mark; "MEDM Motif-based Editor/Display Manager, Operator's Manual"; Argonne National Lab; March 1, 1994.

  7. Srinivasan, R.; "XDR: Externa Data Representation Standard"; Network Working Group, Request For Comment (RFC) 1832; 1996. http://andrew2.andrew.cmu.edu/rfc/rfc1832.html.

  8. Walt Akers, Chip Watson, Jie Chen; "The CDEV Generic Server - A CDEV Extension Library for Building Client/Server Systems"; Version 1.0, October 17, 1996; TJNAF - Thomas Jefferson National Accelerator Facility. http://www.cebaf.gov/cdev/doc_1.4/cdevGenericServer.html.

  9. Walt Akers, Chip Watson, and Jie Chen; "The CDEV Linear Internet Protocol Definition - Structure and Syntax of CDEV Client/Server Network Transmissions"; September 19, 1996; TJNAF - Thomas Jefferson National Accelerator Facility. http://www.cebaf.gov/cdev/doc_1.4/cdevProtocol.html.

  10. "JIT Compiler Results." http://www.webfayre.com/pendragon/jpr/jpr0596-article4.html. Pendragon Software. (May, 1996)

  11. "Java JIT Compiler Performance." http://www.eu.sun.com/workshop/java/jit/performance.html. Sun Microsystems Inc.

  12. "Sun Microelectronics' picoJavaTM I Posts Outstanding Performance." http://www.sun.com/sparc/whitepapers/wpr-0015-01. (18, Nov. 1996)




Cuong C. Quach (aka Patrick)

Last modified: Mon Sep 15 11:05:30 EDT