This system's major drawbacks are as follows:
Starting Up the PackageFirst, choose a collection of machines that will perform work for the users of this package. These machines will merge conceptually into your metacomputer - a self-balancing computer of much greater computational power than the individual machines.
Step 1: System Setup
Step 2: Compute Engines
[start] java -cp
/files/jini1_0/lib/jini-core.jar:
/files/jini1_0/lib/jini-ext.jar:
/files/jini1_0/lib/sun-util.jar:
/files/Frugal/FrugalResource.jar
-Xmx32m
-Djava.rmi.server.codebase=http://yourname.com/Frugal/FrugalResource-dl.jar
-Djava.security.manager=java.rmi.RMISecurityManager
-Djava.security.policy=/files/Frugal/yourpolicy
edu.jhu.cnds.Frugal.FrugalResourceServer
[-f] /files/Frugal/FrugalResource3State [&]
Use [start] on Windows machines, [-f] the first time you use this
compute engine, and [&] on UNIX machines.
Each time you run this, a Frugal Resource appears on the local lookup service.
After a short initialization period, it can perform work for other machines.
It cannot accurately assess its own cost.
Step 3: Frugal ManagerImportant Note: A Frugal Manager automatically "manages" every Frugal Resource it finds on the lookup services/groups it connects to. You can safely have two Frugal Managers managing identical groups of machines, for redundancy in case of machine crash. You can safely have two Frugal Managers managing non-intersecting groups of machines. However, it's not a good idea to have two Frugal Managers managing overlapping but non-identical groups of machines. The Frugal Managers will function correctly, but the Frugal Resources will publicly display the wrong costs to a lookup browser. More importantly, the theory does not guarantee good behavior in this case.
[start] java -cp
/files/jini1_0/lib/jini-core.jar:
/files/jini1_0/lib/jini-ext.jar:
/files/jini1_0/lib/sun-util.jar:
/files/jini1_0/lib/mahalo.jar:
/files/jini1_0/lib/reggie.jar:
/files/Frugal/FrugalManager.jar
-Djava.rmi.server.codebase=http://yourname.com/Frugal/FrugalManager-dl.jar
-Djava.security.manager=java.rmi.RMISecurityManager
-Djava.security.policy=/files/Frugal/yourpolicy
edu.jhu.cnds.Frugal.FrugalManagerServer
[-f] /files/Frugal/FrugalManagerState [&]
As before, use [start] on Windows machines, [-f] the first time
you use this Frugal Manager, and [&] on UNIX machines.
A Frugal Manager now appears on the local lookup service. The role of the
Frugal Manager is to select the most appropriate compute engine for a
metacomputer client. As long as most clients ask the Frugal Manager for a
Frugal Resource rather than finding one on their own, the Manager acts to
balance CPU and memory loads. It balances loads relative to the
strength of the machines, so slow or low-memory machines do not become
overloaded. After a short initialization period, the Frugal Manager is ready
to perform this service.Every 60 seconds, the Frugal Manager also tells the Frugal Resources the global metacomputer state. This includes a count of Frugal Resources in the metacomputer and the highest load that the metacomputer has seen. This information allows the Resources to accurately display their "cost" to a lookup browser user. This is a unitless numeric cost to the metacomputer to put a job on that machine. To the extent that that cost remains accurate in the 60 seconds between updates, the Frugal Manager will place a new job on the machine with the lowest cost. When that job increases that machine's load, that machine's cost increases.
Step 4: Lookup BrowserWe have slightly modified the lookup browser from W. Keith Edwards' "Core Jini" to display Frugal Resource Beans on our test systems in a natural fashion. You can download this revised browser from the same location as the Frugal package. Run it with the appropriate variation on:
[start] java -cp
/files/jini1_0/lib/jini-core.jar:
/files/jini1_0/lib/jini-ext.jar:
/files/jini1_0/lib/sun-util.jar:
/files/Frugal/FrugalBrowser.jar:
/files/Frugal/FrugalBrowser-dl.jar
-Djava.rmi.server.codebase=http://yourname.com/Frugal/Browser-dl.jar
-Djava.security.manager=java.rmi.RMISecurityManager
-Djava.security.policy=/files/Frugal/yourpolicy
edu.jhu.cnds.corejini.chapter9.Browser [&]
Once this is up and running, click on your local lookup service to display
active services. Click on a Frugal Resource service to display its EntryBeans,
including memory usage, CPU speed (as measured by our speed/load tester),
and current cost.
Step 5: Sample ApplicationWe have bundled a very simple application with this package. It locates a Frugal Manager, uses the Frugal Manager to find a compute engine, and then requests that that compute engine perform a job: computing the factorial of 20. Finally, it returns the answer. Optionally, start this application, as with:
[start] java -cp
/files/jini1_0/lib/jini-core.jar:
/files/jini1_0/lib/jini-ext.jar:
/files/jini1_0/lib/sun-util.jar:
/files/Frugal/FrugalClient.jar
-Djava.rmi.server.codebase=http://yourname.com/Frugal/FrugalClient.jar
-Djava.security.manager=java.rmi.RMISecurityManager
-Djava.security.policy=/files/Frugal/yourpolicy
edu.jhu.cnds.FrugalTest.FrugalClient [&]
Step 6: Complex Sample ApplicationWe have constructed a more complex sample application, which you may find in the FrugalDemo package.
Using the Package to Optimize your Computing PowerFinding a Frugal ManagerYou can find a Frugal Manager by looking for the Class edu.jhu.cnds.Frugal.FrugalManager. Alternately, you can look for the Entrynew Name("FrugalManager") This
returns a Frugal Manager object if one is connected to the lookup service. It
implements the interface FrugalManagerRemote.For example:
FrugalManagerRemote smartFinder = null;
public void discovered(DiscoveryEvent evt) {
ServiceRegistrar[] lookupRegistrars = evt.getRegistrars();
Class[] desiredClass = new Class[1];
try {
desiredClass[0] = Class.forName("edu.jhu.cnds.Frugal.FrugalManager");
} catch (ClassNotFoundException e) {
System.err.println("Class not found.");
System.exit(1);
}
Entry[] searchEntries = new Entry[] { new Name("FrugalManager") };
ServiceTemplate searchDescription =
new ServiceTemplate(null, desiredClass, searchEntries);
for (int i = 0; i < lookupRegistrars.length; i++) {
System.out.println("Service found.");
ServiceRegistrar singleRegistrar = lookupRegistrars[i];
try {
smartFinder =
(FrugalManagerRemote) singleRegistrar.lookup(searchDescription);
} catch (java.rmi.RemoteException e) {
e.printStackTrace();
System.exit(2);
}
}
}
Using the Frugal Manager to Find a Frugal ResourceThe Frugal Manager interface specifies a key method:public FrugalResourceRemote getFrugalResource(). This returns a Frugal Resource implementing the FrugalResourceRemote interface. For example:
FrugalResourceRemote computeEngine;
[...]
try {
computeEngine = smartFinder.getFrugalResource();
} catch (java.rmi.RemoteException e) {
e.printStackTrace();
System.exit(1);
}
Using the Frugal Resource to Perform WorkThe classes that perform work remotely must implement the Projectable interface. You can find this interface in the FrugalResource Jarfile. This interface specifies a Object[] main(Object[] argv) method. When you ship a Projectable class to a Frugal Resource, it runs this method with the arguments provided.
The Frugal Resource interface specifies the key compute engine method: This runs the main routine of the submitted class, with argv[] as its input. For example:
try {
Object[] result = computeEngine.run((Projectable) (new workClass()),
new Object[] {"Argument String", (int)2, new inputClass()});
} catch (java.rmi.RemoteException e) {
e.printStackTrace();
System.exit(1);
}
Applications Programming with the Frugal PackageThe more you parallelize your Jini code, the greater the benefit you receive from the Frugal package. In particular, Frugal combines well with JavaSpaces-based distributed programming.The FrugalEars class in FrugalUtilities.jar listens to discovery and remote events and maintains a reference to the local Frugal Manager(s). This is a Hashtable named FrugalManagers, containing ServiceItems. You can locate a Frugal Manager using this class or using the method above. Here's how to initialize an "adjutant" FrugalEars class.
Class[] desiredClass = new Class[1];
try {
desiredClass[0] = Class.forName("edu.jhu.cnds.Frugal.FrugalManager");
} catch (ClassNotFoundException e) {
System.err.println("Frugal Class not found; check classpath.");
System.exit(1);
}
Entry[] redundantParameter = new Entry[] { new Name("FrugalManager") };
adjutant.searchDescription =
new ServiceTemplate(null, desiredClass, redundantParameter);
try {
adjutant.scout =
new LookupDiscoveryManager(new String[] { "", "Frugal" }, null, null);
} catch (Exception e) {
System.out.println("Couldn't send out a discovery.\n");
System.err.println(e.toString());
System.exit(1);
}
adjutant.scout.addDiscoveryListener(adjutant);"JavaSpaces(TM) Principles, Patterns, and Practice" describes generic workers, that pull a small amount of work from a JavaSpace, perform the work, and return the results to the space. These workers can be chained together to perform complex distributed applications. Instead of running the task's execute routine, build the task as a Projectable class and run it with:
machineFinder = adjutant.getManager();
if (machineFinder != null)
computeServer = machineFinder.getFrugalResource();
Object[] args = new Object[1];
args[0] = space;
Object[] result = computeServer.run((Projectable) task, args);
if (result != null)
entryResult = (Entry) result[0];
|