Learn more about Platform products at http://www.platform.com



Tutorial 5: Modify Resources Based on Load Information

This tutorial describes how to create a registered EGO client that modifies resources in accordance with changes in resource loading. A minimum of two resources is required.

Using this tutorial, you will ...


Step 1: Import class references

Import the necessary classes and interfaces that are required by the client to invoke the Web Service.


Step 2: Retrieve cluster information

Refer to Tutorial 1: Step 2: Retrieve cluster information.


Step 3: Check that the cluster has enough resources

Pass null as an argument to the resourceInfo() method to retrieve all resources in the cluster. For this sample, we need at least two resources.

	 Resource [] resources = client.resourceInfo(null);
	 	 int num = 0;
	 	 int needed = 2;
	 	 if(resources != null) {
	 	   num = resources.length;
	 	 }
	 	 if (num < needed) {
	 	   System.err.println("Cluster Requirement: Should be run on a cluster with at
 least " + 

	 needed + " resources, it has only "+num);
	 notification.stop();
	 return;
	 	 }


Step 4: Register the client

Refer to Tutorial 2: Step 3: Register the client.


Step 5: Make a resource allocation request

Refer to Tutorial 3: Step 4: Make a resource allocation request. In this sample, we make an allocation request for one resource.


Step 6: Check for notification of resource allocation

Refer to Tutorial 3: Step 5: Check the allocation status.


Step 7: Create an activity that will run on a requested resource

Refer to Tutorial 3: Step 6: Create and start an activity on a resource. In this sample, we create 10 activities on a single resource.


Step 8: Check the resource loading

Wait 40 seconds and pass the activity ID to the getActivityResourceLoad() method. This method collects the resource names associated with the activity ID. Pass the resource names array to the calculateAcvtivityLoad() method, which cycles through the array and retrieves the load attribute index associated with each resource. The getLoadAttributeIndex() method cycles through the list of resource attributes looking for the r1m load index. (The r1m load index represents the average number of processes ready to use the CPU during a one-minute interval.) This method returns the attribute array index corresponding to load index r1m. The value for r1m is retrieved and converted to a double data type. This value is stored in a variable (total), which is used as an accumulator. The total sum is then divided by the number of resources to yield the average load index value of r1m. The activity ID and the average load index value are printed out.


Step 9: Modify the resources

Pass the activity ID, delta, loadThreshold, and hysteresis variables as arguments to the modifyActivity() method. The delta value represents the number of resources to be added or released based on the load. However if the load is within the hysteresis range, no change is made; this is to prevent oscillatory behaviour.

Call the getActivityResourceLoad() method to determine the average load on resources; see description for the getActivityResourceLoad() method in Step 8: Check the resource loading. Retrieve the allocation ID from the ActivityResources object (activityResources).

Check if the average load exceeds the load threshold plus the hysteresis value. If the average load exceeds the threshold, call the modifyResources() method to add another resource to the activity allocation; if it doesn't, call the modifyResources() method to drop a resource from the activity allocation.

public void modifyActivity(String activityId, int delta, double loadThreshold, 
double hysterisys)
	 {
	 	 // for any resource that this activity is running on
        // find load, how do you define activity load? on a specefic resource
	 	 double load = getActivityResourceLoad(activityId);

        ActivityResources activityResources =
 activityidToResourcesMap.get(activityId);
        String allocationId = activityResources.getAllocationId();
        
	 	 // if greater than loadThreshold + hysterisys/2, release specific resources,
 blklist?
        if(load > (loadThreshold + hysterisys/2)) {
        	 // load on the resources is high, need to add resources to activity
 allocation
        	 modifyResources(allocationId, delta, true);
        }
        
	 	 // if less    than loadThreshold - hysterisis/2, add resources
        if(load < (loadThreshold + hysterisys/2)) {
        	 // resources are lightly loaded, can drop resources from allocation
        	 modifyResources(allocationId, delta, false);
        }
	 }

In the modifyResources() method, check if the client can connect to the AllocationPortType endpoint. If successful, create a resource specification (resSpec). If a resource needs to be added to the allocation, set the resSpec object so that the minimum and maximum resources is increased by one; otherwise, decrease the minimum and maximum resources by one.

Create an allocation specification (alocSpec). This allocation specification describes a request to Platform EGO for an allocation of resources. The only required variables for the allocation specification are the consumer name to charge this allocation to, and the resource specification (resSpec) of what is being requested.

Create a modify allocation request object (malocReq) and link it with the client name, allocation ID, and allocation specification (alocSpec). Create the security document and the modify allocation response (malocRes).

Call the ModifyAllocation() method with the modify allocation request document (malocReqDoc) and the logon document (logonDoc) as input arguments. This method is used to modify the parameters of an existing allocation. If an error occurs, release the resources associated with the allocation ID by calling the releaseResources() method.

public void modifyResources(String allocationId, int delta, boolean add)
	 {
	 	 if (allocPort == null) {
	 	 	 try {
	 	 	 	 allocPort = new AllocationPortTypeStub();
	 	 	 } catch (Exception e) {
	 	 	 	 e.printStackTrace();
	 	 	 	 return;
	 	 	 }
	 	 }
	 	 // release resources
	 	 // another possibility is to release specific resources that are loaded
	 	 ResourceSpecification[] resSpecs = new ResourceSpecification[1];
	 	 ResourceSpecification resSpec = ResourceSpecification.Factory.newInstance();
	 	 if (!add) {
	 	 	 resSpec.setMaxResources(new BigInteger(Integer.toString(-delta)));
	 	 	 resSpec.setMinResources(new BigInteger(Integer.toString(-delta)));
	 	 } else {
	 	 	 resSpec.setMaxResources(new BigInteger(Integer.toString(delta)));
	 	 	 resSpec.setMinResources(new BigInteger(Integer.toString(delta)));
	 	 }
	 	 resSpec.setResourceGroupName("ComputeHosts");
	 	 resSpec.setResourceRequirement("LINUX86"); // NTX86
	 	 // TODO "EGO_ALLOC_EXCLUSIVE"
	 	 resSpecs[0] = resSpec;
	 	 AllocationSpecificationDocument alocSpecDoc =
 AllocationSpecificationDocument.Factory.newInstance();
	 	 AllocationSpecification alocSpec =
 alocSpecDoc.addNewAllocationSpecification();
	 	 alocSpec.setAllocationName("Sample3Allocation");
	 	 alocSpec.setConsumerName("/SampleApplications/EclipseSamples");
	 	 alocSpec.setResourceSpecificationArray(resSpecs);
	 	 // alocSpec.setOptionArray(new String[]{"EGO_ALLOC_EXCLUSIVE"}); //TODO
	 	 ModifyAllocationRequestDocument malocReqDoc =
 ModifyAllocationRequestDocument.Factory.newInstance();
	 	 ModifyAllocationRequest malocReq =
 malocReqDoc.addNewModifyAllocationRequest();

	 	 malocReq.setClientName(clientId);
	 	 malocReq.setAllocationID(allocationId);
	 	 malocReq.setAllocationSpecification(alocSpec);
	 	 malocReq.setOptionArray(new String[] { "EGO_REALLOC_DELTA" });
	 	 ModifyAllocationResponseDocument malocResDoc;
	 	 ModifyAllocationResponse malocRes;

	 boolean release = false;
	 	 try {
	 	 	 malocResDoc = allocPort.ModifyAllocation(malocReqDoc, logonDoc);
	 	 	 malocRes = malocResDoc.getModifyAllocationResponse();
	 	 	 // TODO what is the response?
	 	 } catch (RemoteException rex) {
	 	 	 // this could be because we cannot shrink below already allocated
	 	 	 // release the resource explicitly in that case or 
	 	 	 releaseResources(allocationId, delta);
	 	 	 release = true;

            // another alternative is to cancel allocation
	 	 	 // return;
	 	 }
	 	 int changes = 0;
	 	 if (add) {
	 	 	   while (changes < delta){
	 	 	 // TODO start a new thread to wait for Resource notification
	 	 	 changes += checkAddResourceNotification();
	 	 	 createActivity(alocIds.get(0), changes);
	 	   } 
	 	 }
	 	 
	 	 return;
	 }

Create an AllocatedResources object (allocatedResources) and associate it with the allocation ID.

Create a release resource request object (rrreq) and link it with the client name, allocation ID, and the resource entries for all resources. The resource entry consists of one or more elements describing which resources to remove from the allocation. They must be part of the existing allocation to be released.

Create the security documents and the release resource response (rrres)

Call the ReleaseResource() method with the release resource response document (rrreqDoc), the logon document (logonDoc), and two security documents as input arguments. This method is used to release resources from an existing allocation. In this sample, one resource is released since this was the value of delta, which represents the number of resources to add or release.

	 public void releaseResources(String allocationId, int delta)
	 {
	 	 AllocatedResources allocatedResources =
 allocidToResourcesMap.get(allocationId);
	 	 Resource [] resources = allocatedResources.getResourcesToRelease(delta);
	 	 
	 	 if (resources == null || resources.length ==0) {
	 	 	 return;
	 	 }
	 	 
	 	 ReleaseResourceRequestDocument rrreqDoc =
 ReleaseResourceRequestDocument.Factory.newInstance();
	 	 ReleaseResourceRequest rrreq = rrreqDoc.addNewReleaseResourceRequest();
	 	 rrreq.setAllocationID(allocationId);
	 	 rrreq.setClientName(clientId);
	 	 ResourceEntry [] resourceEntries = new ResourceEntry[resources.length];
	 	 for(int i=0; i<resources.length; i++){
	 	 	 ResourceEntry entry = ResourceEntry.Factory.newInstance();
	 	 	 entry.setResourceName(resources[i].getResourceName());
	 	 	 entry.setResourceType(resources[i].getResourceType());
	 	 	 resourceEntries[i] = entry;
	 	 }
	 	 rrreq.setResourceEntryArray(resourceEntries);
	 	 rrreq.setOptionArray(new String[]{"EGO_RELEASE_AUTOADJ"});
	 	 if(allocPort == null) {
	 	 	 System.err.println("Could not release resource");
	 	 	 return;
	 	 }
	 	 SecurityDocument sdoc2 = SecurityDocument.Factory.newInstance();
	 	 SecurityHeaderType sec2 = sdoc2.addNewSecurity();
	 	 SecurityDocument sdoc3 = SecurityDocument.Factory.newInstance();
	 	 SecurityHeaderType sec3 = sdoc3.addNewSecurity();
	 	 
	 	 ReleaseResourceResponseDocument rrresDoc;
	 	 ReleaseResourceResponse rrres; 
	 	 try {
	 	   rrresDoc = allocPort.ReleaseResource(rrreqDoc, logonDoc, sdoc2, sdoc3);
	 	   rrres = rrresDoc.getReleaseResourceResponse();
	 	   //TODO what does the response contain?
	 	 } catch (RemoteException rex) {
	 	 	 rex.printStackTrace();
	 	 	 return;
	 	 }
	 }


Step 10: Locate the client

Refer to Tutorial 2: Step 4: Locate the client.


Step 11: Unregister the client

Refer to Tutorial 2: Step 5: Unregister the client.


Run the client application

  1. Select Run > Run.

    The Run dialog appears.

  2. In the Configurations list, either select a Java Application or click New for a new configuration.

    For a new configuration, enter the configuration name.

  3. Enter the project name and Main class.
  4. Click the Arguments tab and enter the following arguments in the given order:
    1. URL of the web service gateway
    2. Port number (string) for the notification interface
    3. Client ID (string)
    4. Client description (string).
      note:   

      Arguments must be separated by a space.

  5. Click Apply and then Run.

Sample Output

[ Top ]


[ Platform Documentation ]


      Date Modified: July 12, 2006
Platform Computing: www.platform.com

Platform Support: support@platform.com
Platform Information Development: doc@platform.com

Copyright © 1994-2006 Platform Computing Corporation. All rights reserved.