diff --git a/src/helma/xmlrpc/Benchmark.java b/src/helma/xmlrpc/Benchmark.java index a39642ca..c64b3833 100644 --- a/src/helma/xmlrpc/Benchmark.java +++ b/src/helma/xmlrpc/Benchmark.java @@ -11,15 +11,15 @@ public class Benchmark implements Runnable { XmlRpcClient client; static String url; - static int clients = 8; - static int loops = 200; + static int clients = 16; + static int loops = 100; int gCalls = 0, gErrors = 0; Date date; public Benchmark () throws Exception { - client = new XmlRpcClient (url); + client = new XmlRpcClientLite (url); Vector args = new Vector (); // Some JITs (Symantec, IBM) have problems with several Threads diff --git a/src/helma/xmlrpc/XmlRpc.java b/src/helma/xmlrpc/XmlRpc.java index d9ca8989..d1c72459 100644 --- a/src/helma/xmlrpc/XmlRpc.java +++ b/src/helma/xmlrpc/XmlRpc.java @@ -239,7 +239,7 @@ public abstract class XmlRpc extends HandlerBase { /** * Writes the XML representation of a supported Java object to the XML writer. */ - void writeObject (Object what, XmlWriter writer) { + void writeObject (Object what, XmlWriter writer) throws XmlRpcException { writer.startElement ("value"); if (what == null) { // try sending experimental element @@ -295,7 +295,7 @@ public abstract class XmlRpc extends HandlerBase { } writer.endElement ("struct"); } else - throw new RuntimeException ("unsupported Java type: " + what.getClass ()); + throw new XmlRpcException (0, "Java class not supported in XML-RPC: " + what.getClass ()); writer.endElement ("value"); } @@ -542,6 +542,7 @@ public abstract class XmlRpc extends HandlerBase { public XmlWriter (StringBuffer buf, String enc) { this.buf = buf; + buf.setLength (0); this.enc = enc; // get name of encoding for XML prolog String encName = encodings.getProperty (enc, enc); diff --git a/src/helma/xmlrpc/XmlRpcClient.java b/src/helma/xmlrpc/XmlRpcClient.java index e8c208b8..1b1bf149 100644 --- a/src/helma/xmlrpc/XmlRpcClient.java +++ b/src/helma/xmlrpc/XmlRpcClient.java @@ -24,6 +24,8 @@ public class XmlRpcClient implements XmlRpcHandler { // pool of worker instances Stack pool = new Stack (); int workers = 0; + int asyncWorkers = 0; + // average roundtrip of this method call. This is used to decide if // additional threads are needed or not in async mode @@ -82,7 +84,7 @@ public class XmlRpcClient implements XmlRpcHandler { * @exception IOException: If the call could not be made because of lower level problems. */ public Object execute (String method, Vector params) throws XmlRpcException, IOException { - Worker worker = getWorker (); + Worker worker = getWorker (false); long start = System.currentTimeMillis (); try { Object retval = worker.execute (method, params); @@ -90,7 +92,7 @@ public class XmlRpcClient implements XmlRpcHandler { roundtrip = (int) ((roundtrip*4)+(end-start))/5; return retval; } finally { - releaseWorker (worker); + releaseWorker (worker, false); } } @@ -101,13 +103,13 @@ public class XmlRpcClient implements XmlRpcHandler { * */ public void executeAsync (String method, Vector params, AsyncCallback callback) { - if (workers > 2) { + if (asyncWorkers > 2) { enqueue (method, params, callback); return; } Worker worker = null; try { - worker = getWorker (); + worker = getWorker (true); worker.executeAsync (method, params, callback); } catch (IOException iox) { // make a queued worker that doesn't run immediately @@ -116,14 +118,20 @@ public class XmlRpcClient implements XmlRpcHandler { } - synchronized Worker getWorker () throws IOException { + synchronized Worker getWorker (boolean async) throws IOException { try { Worker w = (Worker) pool.pop (); - workers += 1; + if (async) + asyncWorkers += 1; + else + workers += 1; return w; } catch (EmptyStackException x) { if (workers < maxThreads) { - workers += 1; + if (async) + asyncWorkers += 1; + else + workers += 1; return new Worker (); } throw new IOException ("XML-RPC System overload"); @@ -133,12 +141,15 @@ public class XmlRpcClient implements XmlRpcHandler { /** * Release possibly big per-call object references to allow them to be garbage collected */ - synchronized void releaseWorker (Worker w) { + synchronized void releaseWorker (Worker w, boolean async) { w.result = null; w.call = null; if (pool.size() < 20 && !w.fault) pool.push (w); - workers -= 1; + if (async) + asyncWorkers -= 1; + else + workers -= 1; } @@ -155,8 +166,8 @@ public class XmlRpcClient implements XmlRpcHandler { synchronized CallData dequeue () { if (first == null) return null; - // if (workers > 2 && workers*4 > roundtrip) - // return null; + if (asyncWorkers > 4 && asyncWorkers*4 > roundtrip) + return null; CallData call = first; if (first == last) first = last = null; @@ -187,11 +198,9 @@ public class XmlRpcClient implements XmlRpcHandler { public void run () { while (call != null) { runAsync (call.method, call.params, call.callback); -// System.err.println (workers+" ---- "+ roundtrip); call = dequeue (); - // if (call != null) System.err.print ("."); } - releaseWorker (this); + releaseWorker (this, false); } void runAsync (String method, Vector params, AsyncCallback callback) { @@ -203,8 +212,9 @@ public class XmlRpcClient implements XmlRpcHandler { if (callback != null) callback.handleResult (res, url, method); } catch (Exception x) { - if (callback != null) + if (callback != null) try { callback.handleError (x, url, method); + } catch (Exception ignore) {} } long end = System.currentTimeMillis (); roundtrip = (int) ((roundtrip*4)+(end-start))/5; @@ -218,8 +228,7 @@ public class XmlRpcClient implements XmlRpcHandler { if (strbuf == null) strbuf = new StringBuffer (); - else - strbuf.setLength (0); + XmlWriter writer = new XmlWriter (strbuf); writeRequest (writer, method, params); byte[] request = writer.getBytes(); @@ -272,7 +281,7 @@ public class XmlRpcClient implements XmlRpcHandler { /** * Generate an XML-RPC request from a method name and a parameter vector. */ - void writeRequest (XmlWriter writer, String method, Vector params) throws IOException { + void writeRequest (XmlWriter writer, String method, Vector params) throws IOException, XmlRpcException { writer.startElement ("methodCall"); writer.startElement ("methodName"); diff --git a/src/helma/xmlrpc/XmlRpcClientLite.java b/src/helma/xmlrpc/XmlRpcClientLite.java index 669c97e6..7dced08b 100644 --- a/src/helma/xmlrpc/XmlRpcClientLite.java +++ b/src/helma/xmlrpc/XmlRpcClientLite.java @@ -41,14 +41,20 @@ public class XmlRpcClientLite extends XmlRpcClient { } - synchronized Worker getWorker () throws IOException { + synchronized Worker getWorker (boolean async) throws IOException { try { Worker w = (Worker) pool.pop (); - workers += 1; + if (async) + asyncWorkers += 1; + else + workers += 1; return w; } catch (EmptyStackException x) { if (workers < maxThreads) { - workers += 1; + if (async) + asyncWorkers += 1; + else + workers += 1; return new LiteWorker (); } throw new IOException ("XML-RPC System overload"); diff --git a/src/helma/xmlrpc/XmlRpcServer.java b/src/helma/xmlrpc/XmlRpcServer.java index 0d347ee1..e8d52adb 100644 --- a/src/helma/xmlrpc/XmlRpcServer.java +++ b/src/helma/xmlrpc/XmlRpcServer.java @@ -96,8 +96,7 @@ public class XmlRpcServer { inParams = new Vector (); if (strbuf == null) strbuf = new StringBuffer (); - else - strbuf.setLength (0); + long now = System.currentTimeMillis (); try { @@ -150,7 +149,11 @@ public class XmlRpcServer { String message = x.toString (); // check if XmlRpcException was thrown so we can get an error code int code = x instanceof XmlRpcException ? ((XmlRpcException) x).code : 0; - writeError (code, message, writer); + try { + writeError (code, message, writer); + } catch (XmlRpcException xrx) { + // won't happen, we just sent a struct with an int and a string + } try { result = writer.getBytes (); } catch (UnsupportedEncodingException encx) { @@ -173,7 +176,7 @@ public class XmlRpcServer { /** * Writes an XML-RPC response to the XML writer. */ - void writeResponse (Object param, XmlWriter writer) { + void writeResponse (Object param, XmlWriter writer) throws XmlRpcException { writer.startElement ("methodResponse"); // if (param == null) param = ""; // workaround for Frontier bug writer.startElement ("params"); @@ -187,7 +190,7 @@ public class XmlRpcServer { /** * Writes an XML-RPC error response to the XML writer. */ - void writeError (int code, String message, XmlWriter writer) { + void writeError (int code, String message, XmlWriter writer) throws XmlRpcException { // System.err.println ("error: "+message); Hashtable h = new Hashtable (); h.put ("faultCode", new Integer (code));