|
|||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
How to Use the JRMSTest harness.
See:
Description
Interface Summary | |
CallProduct | Defines all functions found in CallGDImpl.java |
Class Summary | |
CallGDImpl | Implements all RMI functions. |
CallGDServer | Starts the registry on port 1099, loads all functions contained in CallGDImpl.java |
GDManager | Manages the parsing of bytes and time for Graphing. |
GraphManager | This is a wrapper for PerfMon and RatePerfMon. |
HostNameManager | Used to create a Hashtable for storing hostnames found int the hostnames.txt file. |
JRMSTest | Main class that runs the JRMSTest harness. |
LogFileManager | Parses through all log and logbak files checking for succeeded and passed. |
PacketReceiver | uses rmi to call MCTestQA over the network. |
PerfMon | Basic class for creating bytes/time graph, although PerfMonCanvas does most of the work. |
PerfMonCanvas | PerfMonCanvas receives the GraphData objects from all the receivers, throws it into a GraphData vector and paints the Graph. |
PerfObservable | Used to Notify graph when a window has been placed on top, so a repaint can be called. |
PropManager | Manages properties file and stores properties. |
RatePerfMon | Basic class for creating rate/time graph, although RatePerfMonCanvas does most of the work. |
RatePerfMonCanvas | RateGraph Engine receives the GraphData objects from all the receivers, throws it into a GraphData vector and paints the Graph. |
ResetGDManager | Used to keep track of when the graph should be reset. |
SelectVM | Determines whether or not a machine is capable of running exact VM |
StreamReceiver | Kicks off the SimpleTesterQA.class using rsh |
TestReceiver | Parent Class for PacketReceiver and StreamReceiver. |
How to Use the JRMSTest harness.
Open a new shell window and type restart.pl to delete any old JDK processes you have and to start the RMI registry on each machine. Machines are ready when you see Waiting for invocation from clients... appear for each one. Next open another shell and type: JRMSTest.sh To see usage type: java JRMSTest -help
JRMSTest performs the following tasks:
#socket can be either packet or stream
#rverbose and must be true for graphing to work
#check with your net admin for a multicast ip address
# At bcn we can use 224.148.74.001 - 224.148.74.255
CLASSPATH=/net/bcn.east/files3/home/henryw/jrms/version0.8/classes
#used in the event that a machine cannot run exact vm.
java1.2fcs=/net/labeast.east/files3/tools/jdk1.2fcs/bin/java
testtools=com.sun.multicast.reliable.applications.testtools
simple=com.sun.multicast.reliable.simple
#number of bytes (or ints) to send before ending test.
#For multiple hosts receivers should equal 1
hostfile=/home/henryw/jrms/version0.8/reliable/sample_code/testtools/hostnames.txt
#you should be logged into the server host before starting JRMSTest
java.security.policy=client.policy
#whether or not to skew the graph
#javahome below can be used when you don't
#want to run with servers default java VM
This implementation is based on sample source code found in core JAVA Volume II-Advanced Features by Cay S. Horstmann and Gary Cornell Chapter 5 Remote Objects
I started by creating an interface with the following method prototypes.
package com.sun.multicast.reliable.applications.testtools;
import java.rmi.*;
import java.util.*;
import java.lang.*;
public interface CallProduct extends Remote {
void callMCTestQA(String commandline) throws RemoteException;
void startPerfMon() throws RemoteException;
void drawGraph(GraphData gd) throws RemoteException;
void printGraph() throws RemoteException;
boolean selectVM(String host) throws RemoteException;
void setReset(boolean set) throws RemoteException;
boolean getReset() throws RemoteException;
void testResetHash() throws RemoteException;
void setHost(String hostname) throws RemoteException;
}
Note that each method must throw RemoteException.
Next I wrote the body or implementation for these methods. We will go into the exact implementation of these methods at another time. Right now it's only important to see that there was one interface written above, and then the body of these methods appearing below in a complementing "Impl" class file:
package com.sun.multicast.reliable.applications.testtools;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import java.net.*;
public class CallGDImpl
extends UnicastRemoteObject
implements CallProduct {
private GraphData gd;
private int Counter = 0;
private GraphManager gm;
private SelectVM svm;
private HostNameManager hnm;
private ResetGDManager rgdm;
public CallGDImpl()
throws RemoteException {
}
public boolean selectVM(String host)
throws RemoteException {
svm = new SelectVM(host);
return svm.getExactVM();
}
public void startPerfMon()
throws RemoteException {
rgdm = ResetGDManager.getResetGDManager();
gm = GraphManager.getGraphManager();
gm.resetGData();
gm.resetRateGData();
gm.resetHostnames();
gm.resetRateHostnames();
gm.showGraph();
gm.showRateGraph();
}
public void drawGraph(GraphData gd)
throws RemoteException {
gm.drawGraph(gd);
gm.drawRateGraph(gd);
}
public void setReset(boolean set)
throws RemoteException {
rgdm.setReset(set);
}
public boolean getReset()
throws RemoteException {
return rgdm.getReset();
}
public void testResetHash()
throws RemoteException {
rgdm.testResetHash();
}
public void setHost(String hostname)
throws RemoteException {
rgdm.setHost(hostname);
}
public void printGraph()
throws RemoteException {
gm = GraphManager.getGraphManager();
gm.printGData();
}
public void callMCTestQA(String commandline)
throws RemoteException {
try {
Runtime runtime = Runtime.getRuntime();
System.out.println("runtime.exec(" + commandline + ")");
runtime.exec(commandline);
} catch(java.io.IOException e) {
System.out.println("Error: " + e);
}
}
}
Next I created a way for these methods to be distributed across the network. RMI uses naming and rebinding to accomplish this. This allows us to put these methods into the RMI registry across the network. Where does the rmi registry come from? It is supplied by JAVA.
package com.sun.multicast.reliable.applications.testtools;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
public class CallGDServer {
public static void main(String args[]) {
try {
System.out.println("Constructing callback " +
"server implementations...");
CallGDImpl cgi1 =
new CallGDImpl();
System.out.println(
"Binding call server implementations to registry...");
Naming.rebind("CallMCTest", cgi1);
System.out.println(
"Waiting for invocation from clients...");
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
That's all the written code that is necessary to make these methods available for the application. Now we have to compile, then compile again using rmic in order to create CallGDImpl_Stub.class.
I put that in the Makefile:CLASSPATH=$(CLASSPATH) rmic -v1.2 -d $(CLASSPATH) com.sun.multicast.reliable.applications.testtools.CallGDImpl
Finally you must start the RMI registry on each machine that you want these methods available.
rmiregistry&
And last you make java run the CallGDServer.class on each machine. Remember the CallGDServer.class was created to use naming.rebind to put these methods into the registry.
java com.sun.multicast.reliable.applications.testtools.CallGDServer&
Now that everything is up and running I only need to demonstrate how, these rmi object methods are called from the application.
First you create a variable of type CallProduct. Remember that CallProduct is an interface.
private CallProduct cp1;
Next you lookup the name that was bound to the registry:
url = "rmi://" + hostname + "/";
cp1 = (CallProduct)Naming.lookup(url +
"CallMCTest");
Notice that you must cast whatever object the Naming.lookup finds to the CallProduct interface.
Last you simply call the object method of your choice.
cp1.startPerfMon();
Finally, the compiler will tell you to put these rmi calls inside a try catch that includes...
} catch(java.rmi.RemoteException e) {
System.out.println("Error: " + e);
} catch(java.rmi.NotBoundException e) {
System.out.println("Error: " + e);
} catch(java.net.MalformedURLException e) {
System.out.println("Error: " + e);
}
}
JAVA2 forces RMI to use a security policy file. This file is defined in the java.security.policy key of any Properties file. I have named the security policy file
client.policy
You can restrict many things with the policy file for JAVA2. Info on this can be found in Chapter 9 of core JAVA 2 Volume II-Advanced Features
I decided to take the simplest route for now, and not restrict anything. This is what my
policy file looks like:
grant
{ permission java.security.AllPermission;
};
To include this in any running code, I use the (-D) option for java. -D will set a system property. Here is an example in the code:
java -D java.security.policy=client.policy ...
The Graph Nitty Gritty
OK let's get into the nitty gritty.
The Graphs are instantiated from the CallGDImpl.java file in the following method.
public void startPerfMon()
throws RemoteException {
rgdm = ResetGDManager.getResetGDManager();
gm = GraphManager.getGraphManager();
gm.resetGData();
gm.resetRateGData();
gm.resetHostnames();
gm.resetRateHostnames();
gm.showGraph();
gm.showRateGraph();
}
The first two important classes used here are the two singletons - Graph Manager.java and ResetGDManager.java, so lets take a look at those.
They are basically wrappers around the two files that actually are in charge of displaying the Performance and Rate Graphs, PerfMon.java and RatePerfMon.java I wanted to use inheritance on PerfMon.java and RatePerfMon.java since they have so much in common, but have not gotten around to that yet. The wrapper was needed because PerfMon.java already extends Frame and I needed it to also extend Observable, so the graph would redraw after another window came in front of it.
First lets look at GraphManager.java
package com.sun.multicast.reliable.applications.testtools;
import java.util.*;
public class GraphManager extends Observable {
private static GraphManager graphmanager;
private Observable notifier = new PerfObservable();
private PerfMon Graph;
private RatePerfMon RateGraph;
private GraphManager() {
Graph = new PerfMon(notifier,0,0);
RateGraph = new RatePerfMon(notifier,0,500);
}
public static GraphManager getGraphManager() {
if (graphmanager == null) {
graphmanager = new GraphManager();
}
return graphmanager;
}
public void drawGraph(GraphData gd) {
Graph.setData(gd);
Graph.customPaint();
}
public void drawRateGraph(GraphData gd) {
RateGraph.setData(gd);
RateGraph.customPaint();
}
public void printGData() {
Graph.printGData();
}
public void showGraph() {
Graph.show();
}
public void showRateGraph() {
RateGraph.show();
}
public void resetGData() {
Graph.resetGData();
}
public void resetRateGData() {
RateGraph.resetGData();
}
public void resetHostnames() {
Graph.resetHostnames();
}
public void resetRateHostnames() {
RateGraph.resetHostnames();
}
}
Then just for a reference lets look at PerfMon.java as well:
package com.sun.multicast.reliable.applications.testtools;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
class PerfMonCanvas extends Canvas implements Observer {
private Observable notifier;
private int i=0;
private Vector GData = new Vector();
private Enumeration e;
private Enumeration htkeys;
private GraphData gd;
private HostNameManager hnm;
private Hashtable ht;
private Color colors[] = {Color.blue, Color.red, Color.green,
Color.magenta, Color.orange, Color.black};
PerfMonCanvas(Observable notifier) {
notifier.addObserver(this);
this.notifier = notifier;
hnm = HostNameManager.getHostNameManager();
ht = hnm.getHashHosts();
}
public void paint(Graphics g) {
htkeys = ht.keys();
GraphData paintgd;
e = GData.elements();
Dimension d = getSize();
int cx = d.width;
int cy = d.height;
String hostname = "";
int value = 0;
while (htkeys.hasMoreElements()) {
hostname = (String)htkeys.nextElement();
value = ((Integer)ht.get(hostname)).intValue();
if (!hostname.equals("reset")) {
g.setColor(colors[value]);
g.fillOval(10,10 + (15*value),6,6);
g.drawString(hostname,25,17 + (15*value));
}
}
g.setColor(Color.black);
g.drawRect(3,3,125,10 + (5 + (15*(ht.size()-1))));
while(e.hasMoreElements()) {
paintgd = (GraphData)e.nextElement();
drawlines(g, paintgd, cy);
}
}
public void printGData() {
e = GData.elements();
Dimension d = getSize();
int counter = 0;
GraphData printgd;
while(e.hasMoreElements()) {
printgd = (GraphData)e.nextElement();
System.out.println(counter++);
System.out.println("Bytes: " + printgd.getBytes());
System.out.println("Time: " + printgd.getTime());
System.out.println("Host: " + printgd.getHost());
}
}
public synchronized void customPaint() {
Dimension d = getSize();
int cx = d.width;
int cy = d.height;
Integer line;
Graphics g = this.getGraphics();
if (g != null) {
drawlines(g, gd, cy);
}
}
public void setGData(GraphData gd) {
this.gd = gd;
GData.addElement(gd);
}
public void resetGData() {
GData.removeAllElements();
repaint();
}
public void resetHostnames() {
hnm = HostNameManager.getHostNameManager();
ht = hnm.getHashHosts();
}
private void drawlines(Graphics g, GraphData gd, int cy) {
try {
Integer line;
if (gd != null) {
line = (Integer)ht.get(gd.getHost());
switch(line.intValue()) {
case 0:
g.setColor(Color.blue);
g.drawLine((gd.getTime()/150)+5,
(int)((float)cy-gd.getBytes()/10000),
(gd.getTime()/150)+7,
(int)((float)cy-gd.getBytes()/10000));
break;
case 1:
g.setColor(Color.red);
g.drawLine((gd.getTime()/150) + 25,
(int)((float)cy-gd.getBytes()/10000),
(gd.getTime()/150)+27,
(int)((float)cy-gd.getBytes()/10000));
break;
case 2:
g.setColor(Color.green);
g.drawLine((gd.getTime()/150) + 45,
(int)((float)cy-gd.getBytes()/10000),
(gd.getTime()/150) + 47,
(int)((float)cy-gd.getBytes()/10000));
break;
case 3:
g.setColor(Color.magenta);
g.drawLine((gd.getTime()/150) + 65,
(int)((float)cy-gd.getBytes()/10000),
(gd.getTime()/150) + 67,
(int)((float)cy-gd.getBytes()/10000));
break;
case 4:
g.setColor(Color.orange);
g.drawLine((gd.getTime()/150) + 85,
(int)((float)cy-gd.getBytes()/10000),
(gd.getTime()/150) + 87,
(int)((float)cy-gd.getBytes()/10000));
break;
case 5:
g.setColor(Color.black);
g.drawLine((gd.getTime()/150) + 105,
(int)((float)cy-gd.getBytes()/10000),
(gd.getTime()/150) + 107,
(int)((float)cy-gd.getBytes()/10000));
break;
case 99: //This is reserved for resetting the Vector
GData.removeAllElements();
repaint();
default:
break;
}
}
} catch (NoSuchElementException e) {
}
}
public void update(Observable o, Object arg) {
paint(this.getGraphics());
}
}
public class PerfMon extends Frame {
private Vector GData = new Vector();
private PerfMonCanvas pmc;
public PerfMon(Observable notifier, int x, int y) {
super("Bytes/Time Performance Monitor");
addWindowListener(new DWAdapter());
setBackground(Color.white);
setLayout( new BorderLayout());
setResizable(true);
pmc = new PerfMonCanvas(notifier);
// ScrollPane sp = new ScrollPane();
// sp.add("Center", pmc);
// add(sp);
add("Center", pmc);
// setSize(640, 480);
setBounds(x, y, 640, 480);
// setSize(1280, 960);
// setSize(2560,1920);
setVisible(true);
show();
}
public void setData(GraphData gd) {
pmc.setGData(gd);
}
public void customPaint() {
pmc.customPaint();
}
public void printGData() {
pmc.printGData();
}
public void resetGData() {
pmc.resetGData();
}
public void resetHostnames() {
pmc.resetHostnames();
}
class DWAdapter extends WindowAdapter {
public void windowClosing(WindowEvent event) {
//System.exit(0);
closeWindow();
}
}
public void closeWindow() {
this.dispose();
}
public static void main(String[] args) {
Observable notifier = new PerfObservable();
PerfMon f = new PerfMon(notifier,0,0);
}
}
|
|||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
JavaTM Reliable MulticastTM Service version 1.1
Copyright (c) 2001, Sun Microsystems Laboratories, All rights reserved.