New files for worklet transfer optimization project.

aib7 [2002-12-13 02:48:56]
New files for worklet transfer optimization project.
WorkletTest4.java is a test driver that demonstrates
how to use junction transfer as byte arrays.
Files are named based on the functionality of the classes
Filename
WorkletByteCodeCache.java
WorkletClassLoader.java
WorkletIdEntry.java
WorkletTest4.java
diff --git a/WorkletByteCodeCache.java b/WorkletByteCodeCache.java
new file mode 100644
index 0000000..e0844f6
--- /dev/null
+++ b/WorkletByteCodeCache.java
@@ -0,0 +1,121 @@
+package psl.worklets;
+
+import java.util.*;
+
+// stores worklet specific class loaders along with
+// byte code for required classes
+
+public class WorkletByteCodeCache{
+    private static final Hashtable wklSpecificHash = new Hashtable();
+    public WorkletByteCodeCache(){
+    }
+
+    public void put(String name, WorkletClassLoader wklLoader){
+	if (!wklSpecificHash.containsKey(name)){
+	    wklSpecificHash.put(name,wklLoader);
+	}
+	Enumeration e = wklSpecificHash.keys();
+	while(e.hasMoreElements()){
+	    String s = (String)e.nextElement();
+	    // System.out.println("KEY: " + s);
+	}
+    }
+
+    public WorkletClassLoader get(String name){
+	return (WorkletClassLoader)wklSpecificHash.get(name);
+    }
+
+    public static boolean containsKey(String  name) {
+	Enumeration e = wklSpecificHash.keys();
+	while(e.hasMoreElements()){
+	    String s = (String)e.nextElement();
+	    // System.out.println("KEY: " + s);
+	}
+	return wklSpecificHash.containsKey(name);
+    }
+
+    public void putByteCode(String wkltName,String name, byte[] bc){
+	if(wklSpecificHash.containsKey(wkltName)){
+	    WorkletClassLoader _ldr = (WorkletClassLoader)wklSpecificHash.get(wkltName);
+	    _ldr.putByteCode(name,bc);
+	}
+    }
+    public boolean containsKey(String wkltName,String key){
+	if(wklSpecificHash.containsKey(wkltName)){
+	    WorkletClassLoader _ldr = (WorkletClassLoader)wklSpecificHash.get(wkltName);
+	    return _ldr.containsKey(key);
+	}
+	return false;
+    }
+    public byte[] get(String wkltName,String name){
+	if(wklSpecificHash.containsKey(wkltName)){
+	    WorkletClassLoader _ldr = (WorkletClassLoader)wklSpecificHash.get(wkltName);
+	    return _ldr.get(name);
+	}
+	return null;
+    }
+
+
+
+}
+
+/*
+    public void put(String wklName,String name,byte []code){
+	if (wklSpecificHash.containsKey(name)) {
+	    byteCodeEntry bce = (byteCodeEntry)wklSpecificHash.get(wklName);
+	    bce.put(name, bytecode);
+	} else {
+	     byteCodeEntry bce = new byteCodeEntry(wklName);
+	     bce.put(name,code);
+	     wklSpecificHash.put(wklName,bce);
+	}
+    }
+
+    public static byte[] get(String wklName,String name) {
+	if (wklSpecificHash.containsKey(wklName)) {
+	    byteCodeEntry bce = (byteCodeEntry)wklSpecificHash.get(wklName);
+	    return ((byte[]) bce.get(name));
+	}
+	return null;
+    }
+    public static boolean containsKey(String wklName,String name) {
+	if (wklSpecificHash.containsKey(name)) {
+	    byteCodeEntry bce = (byteCodeEntry)wklSpecificHash.get(wklName);
+	    return bce.containsKey(name);
+	} else {
+	    return false;
+	}
+    }
+
+    public void removeWorklet(String wklName){
+	wklSpecificHash.remove(wklName);
+    }
+
+
+    class byteCodeEntry{
+	private String workletId;
+	private WorkletClassLoader wklLoader;
+	//	private final Hashtable byteCodeHash;// = new Hashtable();
+
+	byteCodeEntry(String wklId){
+	    workletId = new String(wklId);
+	    byteCodeHash = new Hashtable();
+	    wklLoader = ldr;
+	}
+
+	public void put(String name,byte []code){
+	    if (! bytecodeHash.containsKey(name)) {
+		bytecodeCache.put(name, bytecode);
+	    }
+	}
+
+	public  byte[] get(String name) {
+	    return ((byte[]) bytecodeHash.get(name));
+	}
+	public boolean containsKey(String name) {
+	    return (bytecodeHash.containsKey(name));
+	}
+    }
+
+
+}*/
diff --git a/WorkletClassLoader.java b/WorkletClassLoader.java
new file mode 100644
index 0000000..0d2366f
--- /dev/null
+++ b/WorkletClassLoader.java
@@ -0,0 +1,283 @@
+/*
+ * @(#)WVM_ClassLoader.java
+ *
+ * Copyright (c) 2001: The Trustees of Columbia University in the City of New York.  All Rights Reserved
+ *
+ * Copyright (c) 2001: @author Gaurav S. Kc
+ * Last modified by: Dan Phung (dp2041@cs.columbia.edu)
+ *
+ * CVS version control block - do not edit manually
+ *  $RCSfile$
+ *  $Revision$
+ *  $Date$
+ *  $Source$
+ */
+
+package psl.worklets;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.net.ssl.*;
+import psl.worklets.http.ClassServer;
+
+/** {@link WVM} associated Class Loader */
+public class WorkletClassLoader extends URLClassLoader{
+  /** <code>URLSet</code> holding the list of <code>URL</code>s*/
+  private final URLSet _urlSet;
+  /** socket factory to use, if not null */
+  private WVM_SSLSocketFactory _WVM_sf;
+
+    // associated worklet's id
+    private String workletId;
+    // stores byte code for required classes
+    private byteCodeStore bcs;
+
+    //this is false when junction for this wvm is sent as byte array
+    // so that class server does not pre-send byte code to other wvm's
+    private boolean sendWId = true;
+
+  /**
+   * Creates a plain WVM_ClassLoader to load the given <code>URL</code>s
+   *
+   * @param urls: array of <code>URL</code>s to load
+   */
+  public WorkletClassLoader (URL[] urls,String wid) {
+    this(urls, null,wid);
+  }
+
+  /**
+   * Creates a WVM_ClassLoader to load the given <code>URL</code>s
+   * with the given SocketFactory
+   *
+   * @param urls: array of <code>URL</code>s to load
+   * @param wvm_sf: socket factory to use
+   */
+  public WorkletClassLoader (URL[] urls, WVM_SSLSocketFactory wvm_sf,String wid) {
+    super(urls);
+
+    _WVM_sf = wvm_sf;
+    // store these urls into our private ordered, data structure
+    _urlSet = new URLSet();
+    _urlSet.add(urls);
+    workletId = new String(wid);
+    bcs = new byteCodeStore(wid);
+  }
+
+    public void sendWorkletId(){
+	sendWId = true;
+    }
+    public void dontSendWorkletId(){
+	sendWId = false;
+    }
+
+
+  /**
+   * Finds the given class
+   *
+   * @param name: Name of the class we want to find
+   * @throws ClassNotFoundException if the given class could not be found
+   * @return the Class, if found
+   */
+  public Class findClass(String name) throws ClassNotFoundException {
+
+      // System.out.println("WORKLETClassLoader: findClass " + name + " " + workletId);
+    // WVM.out.println(WVM.time() + "WVM_ClassLoader asked to findClass(" + name + ")");
+    byte bytecode[] = null;
+GOOD_BLOCK:
+    if (bcs.containsKey(name)) {
+	//found byte code in cache
+      bytecode = bcs.get(name);
+    } else {
+      Enumeration e = _urlSet.elements();
+
+      while (e.hasMoreElements()) {
+        try {
+	    String s = new String(e.nextElement() + name + ".class");
+	    if(sendWId){
+		s = s+"?" +workletId;
+	    }
+	    URL url = new URL(s);
+	    //  System.out.println("TRYING TO GET URL: " + url.toString());
+	    // WVM.out.println("PRINT URL: " +url);
+	    URLConnection urlCon = url.openConnection();;
+
+	    String urlProtocol = url.getProtocol();
+	    if (urlProtocol.equals("https") && _WVM_sf != null){
+		((HttpsURLConnection) urlCon).setSSLSocketFactory(_WVM_sf.getSSLSocketFactory());
+		((HttpsURLConnection) urlCon).setHostnameVerifier(new WVM_HostnameVerifier());
+	    }
+	    urlCon.connect();
+	    InputStream is = urlCon.getInputStream();
+	    // WVM.out.println("checking on data stream @ " + WVM.time());
+	    // int size = is.available();
+	    int size = urlCon.getContentLength();
+	    // if (size == 0) continue;
+	    bytecode = new byte[size];
+
+	    int total = 0;
+	    while (total < size) {
+		int actual;
+		actual = is.read(bytecode, total, size-total);
+		total += actual;
+	    }
+
+	    is.close();
+	    if (url.getProtocol().equals("http") || url.getProtocol().equals("https"))
+		((HttpURLConnection) urlCon).disconnect();
+
+	    // add bytecode to local Webserver cache
+	    ClassServer.put(name, bytecode);
+	    // Upgrade url in _urlSet
+	    break GOOD_BLOCK;
+        } catch (IOException ioe) {
+	    // this Exception could be because the HostnameVerifier
+	    // refused the remote host.
+	    // WVM.err.println("Caught IOException: " + ioe);
+	    //ioe.printStackTrace();
+        }
+      }
+      throw (new ClassNotFoundException("Class: " + name + " not found in URLs"));
+    }
+    return defineClass(name, bytecode, 0, bytecode.length);
+  }
+
+  /**
+   * Finds the URL of the given resource
+   *
+   * @param name: Name of the resource we want to find
+   * @return <code>URL</code> of the resource
+   */
+  public URL findResource(String name) {
+      System.out.println("WVMClassLoader: findResource");
+    // WVM.out.println(WVM.time() + "WVM_ClassLoader asked to findResource(" + name + ")");
+    byte binary[] = null;
+    if (! ClassServer.containsKey(name)) {
+      Enumeration e = _urlSet.elements();
+      while (e.hasMoreElements()) {
+        try {
+          URL url = new URL(e.nextElement() + name);
+	  // WVM.out.println("fndResource testing URL: " + url);
+	  URLConnection urlCon = url.openConnection();
+
+	  String urlProtocol = url.getProtocol();
+	  if (urlProtocol.equals("https") && _WVM_sf != null){
+	    ((HttpsURLConnection) urlCon).setSSLSocketFactory(_WVM_sf.getSSLSocketFactory());
+	    ((HttpsURLConnection) urlCon).setHostnameVerifier(new WVM_HostnameVerifier());
+	  }
+          urlCon.connect();
+          InputStream is = urlCon.getInputStream();
+          // WVM.out.println("checking on data stream @ " + WVM.time());
+          // int size = is.available();
+          int size = urlCon.getContentLength();
+          // if (size == 0) continue;
+          binary = new byte[size];
+
+          int total = 0;
+          while (total < size) {
+            int actual;
+            actual = is.read(binary, total, size-total);
+            total += actual;
+            // WVM.out.println("Got " + total + " bytes from ClassServer for class: " + name);
+          }
+
+          is.close();
+	  if (urlProtocol.equals("http") || urlProtocol.equals("https"))
+	    ((HttpURLConnection) urlCon).disconnect();
+
+          // add binary to local Webserver cache
+          ClassServer.put(name, binary);
+
+          // Upgrade url in _urlSet
+          // WVM.out.println("findResource returning URL: " + url);
+          return url;
+        } catch (IOException ioe) {
+          ioe.printStackTrace();
+        }
+      }
+    }
+    return super.findResource(name);
+  }
+
+  /**
+   * Adds the given array of <code>URL</code>s to the codebase
+   *
+   * @param urls: <code>URL</code>s to add to the codebase
+   */
+  public void addCodebase(URL[] urls) {
+      // System.out.println("WORKLETClassLoader: addCodeBase");
+    _urlSet.add(urls);
+  }
+
+    public void addTopCodebase(URL u){
+	_urlSet.add(0,u);
+    }
+
+  /** Container to hold the ClassLoader's <code>URL</code>s */
+  private class URLSet extends Vector {
+
+      /** Adds the given <code>URL</code> */
+    void add(URL url) {
+      if (url!= null && !contains(url)) {
+        // WVM.out.println("Adding URL at top: " + url);
+        // insertElementAt(url, 0);
+        addElement(url);
+      }
+    }
+
+    /** Adds the given array of <code>URL</code>s */
+    void add(URL[] urls) {
+      for (int i=0; i<urls.length; i++) {
+        add(urls[i]);
+      }
+    }
+
+    /** @return an String-ified enumeration of the <code>URL</code>s */
+    public String toString() {
+     StringBuffer sb = new StringBuffer();
+      for (Enumeration e = elements(); e.hasMoreElements(); ) {
+        sb.append(" " + e.nextElement().toString());
+      }
+      return sb.toString();
+    }
+  }
+
+
+    public void putByteCode(String name, byte[] bc){
+	bcs.put(name,bc);
+    }
+    public boolean containsKey(String key){
+	return bcs.containsKey(key);
+    }
+    public byte[] get(String name){
+	return bcs.get(name);
+    }
+
+
+    class byteCodeStore{
+	private String workletId;
+	private final Hashtable byteCodeHash;// = new Hashtable();
+
+	byteCodeStore(String wklId){
+	    workletId = new String(wklId);
+	    byteCodeHash = new Hashtable();
+	    //  wklLoader = ldr;
+	}
+
+	public void put(String name,byte []code){
+	    if (! byteCodeHash.containsKey(name)) {
+		byteCodeHash.put(name, code);
+	    }
+	}
+
+	public  byte[] get(String name) {
+	    return ((byte[]) byteCodeHash.get(name));
+	}
+	public boolean containsKey(String name) {
+	    return (byteCodeHash.containsKey(name));
+	}
+    }
+
+
+
+}
diff --git a/WorkletIdEntry.java b/WorkletIdEntry.java
new file mode 100644
index 0000000..8206692
--- /dev/null
+++ b/WorkletIdEntry.java
@@ -0,0 +1,25 @@
+package psl.worklets;
+
+import java.util.*;
+
+
+public class WorkletIdEntry{
+    String wid;
+    String codebase;
+    Integer index;
+    Timer t;
+    public WorkletIdEntry(String id, String cb,Integer i){
+	wid = id;
+	codebase = cb;
+	index = i;
+	t = new Timer();
+	t.schedule(new TimerTask(){
+		public void run(){
+		    //remove this entry from hashtable
+		   WVM_RMI_Transporter.wkltIds.remove(index);
+		   this.cancel();
+		   t.cancel();
+		}
+	    },30000);
+    }
+}
diff --git a/WorkletTest4.java b/WorkletTest4.java
new file mode 100644
index 0000000..ad8bce4
--- /dev/null
+++ b/WorkletTest4.java
@@ -0,0 +1,205 @@
+/**
+ *@author: Peter Davis
+ *ptd7@cs.columbia.edu
+ *
+ *Modification of psl.worklets.SystemDispatch.java
+ *
+ *This class was made from SystemDispatch.java (author: Gaurav Kc, gskc@cs.columbia.edu)
+ *except that modifications have been made to handle multiple junctions.
+
+ *This program deploys worklets to multiple junctions,
+ *as a demonstration of multiple junction capability
+ *
+ *
+ *Testing:
+ *Worklet containing java program called Test.java (Test.java simply prints something to stdout)
+ *sent from diamond.cs.columbia.edu
+  to:
+  disco.cs.columbia.edu
+  dynamo.cs.columbia.edu
+  dynasty.cs.columbia.edu
+  *status:
+  *8/7/2001:
+  *2:30 p.m.
+
+
+  *works for  config file of:
+Test,dynamo.cs.columbia.edu,WVM1,9101
+Test,disco.cs.columbia.edu,WVM1,9101
+Test,dynasty.cs.columbia.edu,WVM1,910
+
+  setup:
+  WorkletTest run on diamond.cs
+  psl.worklets.WVM run on {disco.cs,dynamo.cs,dynasty.cs}.columbia.edu
+  Application successfully sent to all three hosts through sockets.
+  RMI did not work for all three hosts.
+
+  *
+  *
+  */
+
+package psl.worklets;
+
+import java.io.*;
+import java.net.*;
+import psl.worklets.*;
+import java.util.*;
+
+public class WorkletTest4 implements Serializable {
+
+    private static final int DEFAULT_PORT = 9100;
+
+    public static void main(String args[]) {
+	WorkletTest4 wt = new WorkletTest4();
+    }
+
+    private WorkletTest4() {
+
+	System.out.println("WORKLET TEST 4 , ALL WORKLET JUNCTIONS ARE KEPT AS BYTE ARRAYS UNTIL TARGET");
+	/*****modification, ptd7***/
+	try{
+	      	    WVM wvm = new WVM(new Object(), InetAddress.getLocalHost().getHostAddress(),
+				      "WorkletTest_4");
+	  	    Worklet wkl = new Worklet(null);
+
+		    String App = null;
+		    String rHost = null;
+		    String rName = null;
+		    int rPort = 0;
+
+		    FileHandle fh = new FileHandle("config.txt",FileHandle.IN);
+		    String input_info =null;
+
+		    while((input_info = fh.readln()) != null){
+			StringTokenizer reader = new StringTokenizer(input_info,",");
+			if(reader.countTokens() >=4){
+
+			    //System.out.println("input from cfg file is: " + input_info);
+			    if(input_info.charAt(0) != '#' && input_info.charAt(0) != ' '){
+				/**make sure that it is valid input**/
+				/**input must be of form: <app>,<host>,<name>,<port>**/
+				App = reader.nextToken();
+				rHost = reader.nextToken();
+				rName = reader.nextToken();
+				try{
+				    rPort = Integer.parseInt(reader.nextToken());
+				}catch(NumberFormatException e){
+				    System.out.println("error parsing port. . . setting to "
+						       + DEFAULT_PORT +" . . .");
+				    rPort = DEFAULT_PORT;
+				}
+				/*************add new junctions********************/
+				/****testing***/
+
+				/****end testing***/
+			       	final Class appClass = Class.forName(App);
+				//  	    // final Class appClass = Class.forName("gskc.TicTacToe");
+
+
+
+				try{
+				    ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
+				    ObjectOutputStream ooStream = new ObjectOutputStream(baoStream);
+
+				    //create byte array out of actual junction to use first
+				    ooStream.writeObject(new WorkletJunction(rHost, rName, rPort,App,wkl.wid) {
+					public void init(Object system, WVM wvm) {
+					    System.out.println("ORIGINAL JUNCTION"); }
+					public void execute() {
+					    WVM.out.println("\t --- Totally New Component ---");
+					    try {
+						//	System.out.println("Calling the loader here somewhere");
+						//	System.out.println("Declaring class: " + appClass.getDeclaringClass().getNa
+
+						// final Class appClass = Class.forName(appName);
+
+						System.out.println(appClass.getClassLoader().getClass().getName());
+						appClass.newInstance();
+					    } catch (InstantiationException e) {
+						WVM.out.println("Exception: " + e.getMessage());
+						e.printStackTrace();
+					    } catch (IllegalAccessException e) {
+						WVM.out.println("Exception: " + e.getMessage());
+						e.printStackTrace();
+					    } catch (Exception e) {
+						e.printStackTrace();
+					    }
+					}
+				    });
+
+				    byte []wjbytes = baoStream.toByteArray();
+				    baoStream.close();
+
+				    String u = new String("http://"+java.net.InetAddress.getLocalHost().getHostAddress()+":"+wvm.transporter._webPort+"/");
+			  	//   System.out.println("\n\nSENDING URL: " + u);
+				    URL x = new URL(u);
+
+				    //add byte array along with dummy empty junction tht has only destination info
+				    wkl.addJunction(new WorkletJunction(rHost, rName, rPort,App,wkl.wid) {
+					public void init(Object system, WVM wvm) {}
+					public void execute() {}
+				    },wjbytes,x);
+
+				} catch (IOException ioe){
+				    ioe.printStackTrace();
+				    System.exit(-1);
+				}
+
+				/*	} else {
+					wkl.addJunction(new WorkletJunction(rHost, rName, rPort,App,wkl.wid) {
+					public void init(Object system, WVM wvm) { }
+					public void execute() {
+						WVM.out.println("\t --- Totally New Component ---");
+						try {
+						    //	System.out.println("Calling the loader here somewhere");
+						    //	System.out.println("Declaring class: " + appClass.getDeclaringClass().getNa
+
+						    // final Class appClass = Class.forName(appName);
+
+						    System.out.println(appClass.getClassLoader().getClass().getName());
+						    appClass.newInstance();
+						} catch (InstantiationException e) {
+						    WVM.out.println("Exception: " + e.getMessage());
+						    e.printStackTrace();
+						} catch (IllegalAccessException e) {
+						    WVM.out.println("Exception: " + e.getMessage());
+						    e.printStackTrace();
+						} catch (Exception e) {
+						    e.printStackTrace();
+						}
+					    }
+					});
+				}*/
+
+
+
+				System.out.println("just added a junction at: ");
+				System.out.println("App: " + App+ " rHost: " + rHost
+						   + "  rName: " + rName + " rPort: " + rPort );
+
+                               /***********end, add new junctions*****************/
+			    }
+			}
+		    }
+		    fh.close();
+
+
+		    /*****end modification, ptd7***/
+		    System.out.println("about to deploy worklet");
+		    wkl.deployWorklet(wvm); //deploy worklet, with junctions from config file
+		    System.out.println("just deployed worklet");
+
+	} catch (UnknownHostException e) {
+	    WVM.out.println("Exception: " + e.getMessage());
+	    e.printStackTrace();
+	    System.exit(0);
+	} catch (ClassNotFoundException e) {
+	    WVM.out.println("Exception: " + e.getMessage());
+	    e.printStackTrace();
+	    System.exit(0);
+	}
+    }
+}
+
+
+