Scheduled destruction is a more elaborate form of resource lifecycle management, as it allows us to specify exactly when we want the resource to be destroyed. The main application of scheduled destruction is to perform lease-based lifecycle management, where we initially set the destruction time of a resource some time in the future (for example, 5 minutes). This is called the lease. Our application must periodically renew the lease (setting the destruction time another 5 minutes in the future), or the resource will eventually be destroyed. This will allow our application to purge resources that for some reason (network failure, programmer errors, etc.) have become unavailable (and therefore can't receive the lease renewal).
Using scheduled destruction requires adding more code that immediate destruction because the standard WSRF portType that provides scheduled destruction not only adds a new operation (SetTerminationTime
) but also two new resource properties: TerminationTime
and CurrentTime
. TerminationTime
specifies when the resource is set to be destroyed, and the value of CurrentTime
must always be the time in the machine that hosts the resource. This means that, not only will we have to modify the WSDL file, we will also have to make sure those two new resource properties are properly implemented in our resource class.
So, let's start with the easy part. To use scheduled resource termination, our portType must extend from the ScheduledResourceTermination
portType:
<portType name="MathPortType"
wsdlpp:extends="wsrpw:GetResourceProperty
wsrlw:ScheduledResourceTermination"
wsrp:ResourceProperties="tns:MathResourceProperties">
<operation name="add">
<input message="tns:AddInputMessage"/>
<output message="tns:AddOutputMessage"/>
</operation>
<operation name="subtract">
<input message="tns:SubtractInputMessage"/>
<output message="tns:SubtractOutputMessage"/>
</operation>
</portType>
As seen in immediate destruction, we mustn't forget to declare the WS-ResourceLifetime namespace ( |
Next, we have to implement the ResourceLifetime
interface in our resource class. This interface requires that we provide get/set methods for the TerminationTime
and CurrentTime
RPs.
public class MathResource implements Resource, ResourceIdentifier,
ResourceProperties, ResourceLifetime
So, we'll start by adding a terminationTime
attribute of type Calendar
to our class to represent the resource's termination time. We don't need to add a currentTime
attribute because that RP's get method will always return the system's time (which, as we'll see, we can easily obtain using the Java API).
/* Resource properties */
private int value;
private String lastOp;
private Calendar terminationTime;
Now, we have to make sure we add the two RPs to our resource's RP set:
/* Initializes RPs and returns a unique identifier for this resource */
public Object initialize() throws Exception {
this.key = new Integer(hashCode());
this.propSet = new SimpleResourcePropertySet(
MathQNames.RESOURCE_PROPERTIES);
try {
ResourceProperty valueRP = new ReflectionResourceProperty(
MathQNames.RP_VALUE, "Value", this);
this.propSet.add(valueRP);
setValue(0);
ResourceProperty lastOpRP = new ReflectionResourceProperty(
MathQNames.RP_LASTOP, "LastOp", this);
this.propSet.add(lastOpRP);
setLastOp("NONE");
ResourceProperty termTimeRP = new ReflectionResourceProperty(
SimpleResourcePropertyMetaData.TERMINATION_TIME, this);
this.propSet.add(termTimeRP);
ResourceProperty currTimeRP = new ReflectionResourceProperty(
SimpleResourcePropertyMetaData.CURRENT_TIME, this);
this.propSet.add(currTimeRP);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return key;
}
Notice we use a Globus-supplied SimpleResourcePropertyMetaData
class which includes information on the TerminationTime
and CurrentTime
RPs. We must make sure we import this class:
import org.globus.wsrf.impl.SimpleResourcePropertyMetaData;
Finally, the last thing needed in the resource implementation is to add a get
and set
method for the TerminationTime
RP, and a get
method for the CurrentTime
RP (we can't 'set' the current time). Notice how we return the current time using an instance of the Java Calendar
class.
/* Required by interface ResourceLifetime */ public Calendar getCurrentTime() { return Calendar.getInstance(); } public Calendar getTerminationTime() { return this.terminationTime; } public void setTerminationTime(Calendar terminationTime) { this.terminationTime=terminationTime; }
This is part of file
|
As we did in immediate destruction, we need to add a Globus-supplied operation provider, SetTerminationTimeProvider
, to the instance service. This provider implements the setTerminationTime
operation that will allow us to set the resource's termination time. Note that we cannot set the termination time by directly modifying the TerminationTime
RP (using, for example, the SetResourceProperties
operation). We must use the setTerminationTime
operation (this operation, as implemented in the Globus-supplied operation provider, does more than just update the RP).
<parameter name="providers" value="GetRPProvider SetTerminationTimeProvider"/>
This is part of file
|
We can also modify the JNDI deploy file to control how often the container will check if a resource is past its termination time. This is done with the sweeperDelay
parameter, specified in milliseconds. The default value is to check every one minute (60000 milliseconds). We will change this value to one second (1000 milliseconds) so our client will be able to observe how the resource does, in fact, expire.
<parameter> <name>sweeperDelay</name> <value>1000</value> </parameter>
This is part of file
|
Finally, build and deploy:
./globus-build-service.sh rl
globus-deploy-gar $EXAMPLES_DIR/org_globus_examples_services_core_rl.gar
We will test our service by creating a new resource, setting its termination 10 seconds in the future, and then checking every second to see if the resource is still 'alive'. When the resource is terminated, any call to the resource will produce an exception. Like the immediate destruction client, this client is similar to the simple client seen in Chapter 5, Multiple resources. The following is the code that we will run after the resource has been created:
Calendar termination = Calendar.getInstance(); termination.add(Calendar.SECOND, 10); SetTerminationTime request; SetTerminationTimeResponse response; request = new SetTerminationTime(termination); response = math.setTerminationTime(request); System.out.println("Current time " + response.getCurrentTime().getTime()); System.out.println("Requested termination time " + termination.getTime()); System.out.println("Scheduled termination time " + response.getNewTerminationTime().getTime()); boolean terminated = false; int seconds = 0; while (!terminated) { try { System.out.println("Second " + seconds); math.add(10); Thread.sleep(1000); seconds++; } catch (RemoteException e) { System.out.println("Resource has been destroyed"); terminated = true; } }
This is part of file
|
Compile and run the client:
javac \ -classpath ./build/stubs/classes/:$CLASSPATH \ org/globus/examples/clients/FactoryService_Math_rl/Client_sched.java
java \ -classpath ./build/stubs/classes/:$CLASSPATH \ org.globus.examples.clients.FactoryService_Math_rl.Client_sched \ http://127.0.0.1:8080/wsrf/services/examples/core/rl/MathFactoryService
If all goes well, you should see the following:
Created instance. Current time Sun Apr 03 00:54:29 CST 2005 Requested termination time Sun Apr 03 00:54:39 CST 2005 Scheduled termination time Sun Apr 03 00:54:39 CST 2005 Second 0 Second 1 Second 2 Second 3 Second 4 Second 5 Second 6 Second 7 Second 8 Second 9 Second 10 Resource has been destroyed