|Presentation||User guide||Token API||Active naming||Extensions||Implementation||Token implementation|
Token API and Active Naming Implementation|
This document presents the implementation of the Token API, measurement facility and Active Naming in PageBox for Java.
Programmers who want:
PageBox implements a token ring using the PageBox Web services:
The implementation uses the mechanism presented on the Token API page. It is designed as a set of components with very few interactions with the rest of PageBox, which means that
The DeployIF interface extends a TokenIF interface defined like this:
This TokenIF interface defines a frameSend method that sends a frame to the next PageBox on the ring or to the Repository when the PageBox is the last PageBox on the ring. This method takes one parameter, which is the frame to send.
The frame is an object of TokenFrame class:
The TokenFrame class implements methods that we describe later. Here we only present its data, which are:
The order of the PageBoxes in the adjacency list is the order of the PageBoxes on the ring:
The PageBoxInfo class is defined like this:
The TokenMsg class is defined like this:
The TokenMsg class implements methods that we describe later. Here we only present its data, which are:
The Message class is defined like this:
The DeployIF Web service is implemented in the DeployImpl class. DeployImpl extends a TokenImpl class that implements the TokenIF methods.
The RepoQueryIF interface extends a RepoTokenIF interface defined like this:
This RepoTokenIF interface extends the TokenIF interface described above and defines two additional methods:
In this case the TokenIF method, frameSend, sends a frame to the first PageBox on the ring.
The RepoQueryIF Web service is implemented in the RepoQueryImpl class. RepoQueryImpl extends a RepoTokenImpl class that implements the RepoTokenIF methods.
As described in the token API user guide PageBoxAPI implements two methods:
The actual implementation of PageBoxAPI is in the APIImpl class. This class contains a member of type TokenCallbackImpl. PageBoxAPI.registerCallback calls the registerCallback method of this object and PageBoxAPI.unregisterCallback calls the unregisterCallback method of this object.
These classes are used on the Repository as well as on the PageBox agent. These classes are:
TokenCallbackImpl has two members of interest:
RepositoryReg is a class embedded in TokenCallbackImpl that has two functions:
TokenCallbackImpl also imbeds a Sender class that implements the TokenSendIF. Its send method adds the message passed in parameter to the msgs map of the proper TokenMsg. If this TokenMsg doesn’t exist send creates a new TokenMsg and adds it to msgList.
This method gets called when a Web archive calls the homonymous method of PageBoxAPI. However the registerCallback method of TokenCallbackImpl has a second parameter, the name of the Web archive. This parameter was set up by PageBoxAPI.
If a RepositoryReg instance doesn’t exist yet for the Repository where the Web archive was downloaded in the callbacks map registerCallback:
Otherwise registerCallback retrieves the RepositoryReg instance from the callbacks map.
Then registerCallback sets the TokenCallbackIF object of the archive in RepositoryReg.callbacks and creates a Sender object.
This method gets called when a Web archive calls the homonymous method of PageBoxAPI. However the unregisterCallback method of TokenCallbackImpl has a parameter, the name of the Web archive. This parameter was set up by PageBoxAPI.
unregisterCallback removes the archive from the RepositoryReg.callbacks map. If then RepositoryReg.callbacks is empty (if there is not anymore Web applications handling messages on this PageBox) unregisterCallback calls the unregister method of RepositoryReg to remove the PageBox from the Repository ring.
processFrame is called by TokenImpl to handle frames received by the PageBox.
processFrame enumerates the callbacks map of the RepositoryReg instance that manages the frame Repository. For each archive (Web application) found processFrame retrieves its TokenCallbackIF instance, calls the processResponse and processMessage methods of the frame and the poll method of the TokenCallbackIF instance.
Then processFrame calls a cleanup method of the frame to remove messages that came back to their issuer and adds messages in msgList to the frame.
TokenImpl implements the TokenIF method of the DeployIF Web service, frameSend.
The context of TokenImpl is stored in a TokenImpl.Context object defined like this:
frameSend calls the processFrame method of TokenCallbackImpl to handle message whose target was this PageBox and to add messages sent by this PageBox, queues the updated frame and notifies the TokenThread instance that there is a new frame to process.
TokenThread extends Thread. In this thread TokenThread dequeues and forwards the frames queued by the frameSend method to the next PageBox on the ring.
The run method is the main method of the TokenThread thread. It waits for a notification or for a timeout. If it was notified by frameSend it calls the frameForward method to send the updated frame to the next PageBox on the ring. In case of timeout run checks if the repository is alive by sending it a special "ping" frame. If the repository is dead run calls a generateToken method.
generateToken wait for a random amount of time to:
frameForward finds the next PageBox in the adjacency list and calls its DeployIF Web service to send the frame. In case of failure it calls the DeployIF Web service of the next PageBox up to the time it succeeds (finds a running PageBox). When there is no more PageBox frameForward calls the RepoQueryIF Web service of the Repository.
In both the run and the frameForward methods failed PageBoxes are removed from the adjacency list and the RepoQueryIF.tokenUnregister method of the Repository is called to remove the failed PageBoxes from the ring.
TokenFrame implements trace methods and three methods called by the processFrame method of TokenCallbackImpl:
processMessage retrieves from the frame msgList the TokenMsg objects whose archive is the archive passed in parameter and target is this PageBox or null (broadcast).
processMessage enumerates the Message instances in the msgs map of these TokenMsg objects. For each Message processMessage invokes the call method of the Web application’s TokenCallbackIF object.
processResponse retrieves from the frame msgList the TokenMsg objects whose archive is the archive passed in parameter and origin is this PageBox.
processResponse enumerates the Message instances in the msgs map of these TokenMsg objects. For each Message processResponse invokes the response method of the Web application’s TokenCallbackIF object.
There are two versions of the cleanup method:
RepoTokenImpl is the Repository equivalent of TokenImpl.
RepoTokenImpl implements the RepoTokenIF methods of the RepoQueryIF Web service. Because RepoTokenIF extends TokenIF RepoTokenImpl implements frameSend. Therefore like TokenImpl RepoTokenImpl and creates a separate RepoTokenThread thread that forwards the updated frame to the first PageBox on the ring. RepoTokenImpl also implements two methods of RepoTokenIF, tokenRegister and tokenUnregister.
The context of RepoTokenImpl is stored in a RepoTokenImpl.Context object defined like this:
If master is null (if a first PageBox joins the ring) tokenRegister instantiates a new TokenFrame with the PageBox in the adjacency list and queues this frame to the RepoTokenImpl thread for sending the frame. Otherwise tokenRegister adds the PageBox to the master adjacency list.
tokenUnregister removes the PageBox from the master’s adjacency list. If this PageBox was the last PageBox on the ring tokenUnregister ends the RepoTokenImpl thread and unreferences the master.
RepoTokenThread extends Thread. In this thread RepoTokenThread dequeues and forwards the frames queued by the frameSend method to the first PageBox on the ring.
The run method is the main method of the RepoTokenThread thread. It waits for a notification or for a timeout. If it was notified by frameSend or tokenRegister run sends the frame to the first running PageBox and calls TokenUnregister to remove the non-running PageBoxes before the first running PageBox from the ring.
In case of timeout run issues a new token (sends a new frame). It addresses the case where the token was lost but also ensures that there are enough tokens on the ring to handle messages fast enough.
When it receives the token earlier than half timeout + the time when it sent this token on the ring, run waits in order for two subsequent frame sends to be separated by half timeout.
TokenSerializer addresses a class resolution problem. The Token API allows sending and receiving objects of any Serializable type known by the Web application class loader. TokenFrame that handles messages and responses in its processMessage and processResponse methods is loaded by a different class loader, the PageBoxLib class loader.
To serialize and un-serialize messages the processMessage and processResponse methods load the TokenSerializer class with the Web application class loader, create a TokenSerializer object and use the reflection to invoke the processMessage and processResponse methods of this TokenSerializer object.
TokenSerializer implements three methods for Token handling:
TokenSerializer implements three other methods for Active Naming:
The measurement facility measures:
of a PageBox host.
This facility is modular and extensible to allow supporting new Operating Systems or making better measurements. We describe in the Porting guide how to extend the facility. Collected data are stored in a ResourceUsage class that extends a MemUsage class. Operating system dependent probes are responsible for making measurements. PageBox 0.0.13 embeds a probe for Linux, called LinuxUsageProbe and a probe for Windows NT, 2000 and XP, called WindowsUsageProbe. Probes are instantiated by a UsageFactory class and implement a UsageIF interface defined like this:
ResourceUsage is just a placeholder for CPU-related data normally set by the probes.
MemUsage is a placeholder for memory and network related data but it also implements an init method.
This init method takes one parameter, netTime, which is the time spent to send a frame to the next station on the ring and sets the MemUsage members in the following way:
APIImpl.getResourceUsage calls the init method after it has called the collect method of the probe.
UsageFactory has a getUsageProbe static method that instantiates the appropriate probe depending on the Operating System. UsageFactory.getUsageProbe is called by APIImpl.getResourceUsage.
LinuxUsageProbe implements the collect method of the UsageIF interface. Its collect method reads the /proc/stat file and parses its cpu line.
WindowsUsageProbe implements the collect method of the UsageIF interface. Its collect method loads a WindowsCPU dll and calls its getCPU native method. getCPU calls a GetCpuUsage usage method implemented in a GetCpuUsage.cpp file. We didn’t develop this code. We found it on http://www.codeproject.com/system/cpuusage.asp where it is credited to Dudi Avramov. We only added the JNI stuff and converted the exe into a dll.
PageBox implements Active Naming using the Token API and the measurement facility.
The implementation uses the mechanism presented on the Active Naming page. It has no interaction with the rest of PageBox except the Token implementation.
As described in the Active Naming user guide the PageBoxAPI implements seven methods:
The actual implementation of PageBoxAPI is in the APIImpl class. This class contains a member of type ActiveNaming. PageBoxAPI.ActiveNamingLogon calls the logon method of this object, PageBoxAPI.ActiveNamingLogoff calls the logoff method of this object, PageBoxAPI.getEntries calls the getEntries method of this object, PageBoxAPI.getCandidate calls the getCandidate method of this object, PageBoxAPI.addEntry calls the addEntry method of this object, PageBoxAPI.removeEntry calls the removeEntry method of this object and PageBoxAPI.clearEntries calls the clearEntries method of this object.
APIImpl also contains a getResourceUsage that uses the measurement facility to return a populated ResourceUsage object that describes resource usage on a PageBox host.
Active Naming is implemented in the Active Naming class.
Four other classes store data:
Active Naming also contains an ActiveComparable interface.
ActiveEntry is defined like this:
ActiveEntry describes a service instance. url is the page or Web service URL. must is the imperative matching object serialized by TokenSerializer. niceif is the nice if match object serialized by TokenSerializer.
ActiveEntry objects are inserted in ActiveMessage objects, which are themselves inserted in Token ring frames. Therefore ActiveEntry implements Serializable.
ActiveMessage is defined like this:
ActiveMessage is the token ring message used to send Active Naming data. Because ActiveMessage objects are inserted in Token ring frames ActiveMessage implements Serializable. entries is a map whose keys are entry names and values are ActiveEntry objects.
MatchingEntry is defined like this:
distance is the distance between the service instance and a niceif object passed by the getCandidate method. This distance is setup by the niceifActive method of TokenSerializer.
MatchingEntry is used by ActiveNaming.getCandidate to communicate with TokenSerializer.
ActiveResult is used by the mustActive and niceifActive methods of TokenSerializer to return their response. ActiveResult is defined like this:
ActiveComparable is the interface that nice if match object must implement. These objects must be serializable because nice if match objects must be serialized into ActiveEntry.niceif and implement a compareTo method to measure the distance between two nice if match objects. Therefore ActiveComparable is defined like this:
ActiveNaming has three members of interest:
ActiveNaming may register on the ring for two reasons:
Therefore logon checks if localEntries is empty. When it is the case logon registers its ActiveNaming instance as a Token API callback with the registerCallback method of the PageBox API.
The Token API allows only one callback per archive. To allow using the Active Naming and the Token API at the same time Active Naming registers a pseudo archive name made of the actual archive suffixed by ".an".
logoff unregisters from the ring only if localEntries is empty (if the Web application has no more service instances to advertise).
getEntries enumerates foreignEntries to build a list of logical names of entry points.
getCandidate is called with three parameters:
addEntry adds a new ActiveEntry object to the localEntries map. If the localEntries was empty before and if logon had not been called (isRegistered == false) addEntry registers its ActiveNaming instance as a Token API callback with the registerCallback method of the PageBox API.
To populate the ActiveEntry object addEntry creates a TokenSerializer instance with the "must" class loader to serialize the "must" parameter and creates a TokenSerializer instance with the "niceif" class loader to serialize the "niceif" parameter.
removeEntry removes the service instance identified by the logical name of entry point from the localEntries map. If then localEntries is empty and if logon had not been called (isRegistered == false) removeEntry un-registers its ActiveNaming instance with the unregisterCallback method of the PageBox API.
clearEntries clears the localEntries map. Then if logon had not been called (isRegistered == false) clearEntries un-registers its ActiveNaming instance with the unregisterCallback method of the PageBox API.
From each remote instance call receives an ActiveMessage and adds this object to the foreignEntries map.
poll build an ActiveMessage with the localEntries map and the ResourceUsage returned by APIImpl.getResourceUsage and sends this ActiveMessage to remote instances.