From b00e421f88379a16d5682f1182c59b124893964c Mon Sep 17 00:00:00 2001 From: hns Date: Thu, 18 Jan 2001 14:50:04 +0000 Subject: [PATCH] Changed evaluators and threads to be initialized only when needed. Phew! --- src/helma/framework/core/Action.java | 73 +++++++++++++++---- src/helma/framework/core/Application.java | 3 +- src/helma/framework/core/ESAppNode.java | 24 ++++-- src/helma/framework/core/FunctionFile.java | 10 ++- .../framework/core/RequestEvaluator.java | 4 +- src/helma/framework/core/Template.java | 17 ++++- src/helma/framework/core/TypeManager.java | 50 +++++-------- 7 files changed, 123 insertions(+), 58 deletions(-) diff --git a/src/helma/framework/core/Action.java b/src/helma/framework/core/Action.java index e3d8bb99..0b35e313 100644 --- a/src/helma/framework/core/Action.java +++ b/src/helma/framework/core/Action.java @@ -27,13 +27,14 @@ import FESI.Exceptions.*; public class Action { String name; + String functionName; Prototype prototype; Application app; File file; long lastmod; - - ParsedFunction pfunc; + // this is the parsed function which can be easily applied to RequestEvaluator objects + TypeUpdater pfunc; public Action (File file, String name, Prototype proto) { @@ -70,15 +71,22 @@ public class Action { public void update (String content) throws Exception { // IServer.getLogger().log ("Reading text template " + name); - String fname = name+"_hop_action"; + functionName = name+"_hop_action"; try { - pfunc = parseFunction (fname, "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", content); + pfunc = parseFunction (functionName, "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", content); } catch (Exception x) { String message = x.getMessage (); - app.typemgr.generateErrorFeedback (fname, message, prototype.getName ()); + pfunc = new ErrorFeedback (functionName, message); } + Iterator evals = app.typemgr.getRegisteredRequestEvaluators (); + while (evals.hasNext ()) { + try { + RequestEvaluator reval = (RequestEvaluator) evals.next (); + updateRequestEvaluator (reval); + } catch (Exception ignore) {} + } } @@ -87,10 +95,16 @@ public class Action { } public String getFunctionName () { - return pfunc.functionName; + return functionName; } - protected ParsedFunction parseFunction (String funcname, String params, String body) throws EcmaScriptException { + + public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException { + if (pfunc != null) + pfunc.updateRequestEvaluator (reval); + } + + protected TypeUpdater parseFunction (String funcname, String params, String body) throws EcmaScriptException { // ESObject fp = app.eval.evaluator.getFunctionPrototype(); // ConstructedFunctionObject function = null; @@ -142,12 +156,7 @@ public class Action { return new ParsedFunction (fpl, sl, fes, fulltext, funcname); } - public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException { - if (pfunc != null) - pfunc.updateRequestEvaluator (reval); - } - - class ParsedFunction { + class ParsedFunction implements TypeUpdater { ASTFormalParameterList fpl = null; ASTStatementList sl = null; @@ -178,6 +187,44 @@ public class Action { } } + + class ErrorFeedback implements TypeUpdater { + + String functionName, errorMessage; + + public ErrorFeedback (String fname, String msg) { + functionName = fname; + errorMessage = msg; + } + + public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException { + + ObjectPrototype op = reval.getPrototype (prototype.getName ()); + + FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype (); + FunctionPrototype func = new ThrowException (functionName, reval.evaluator, fp, errorMessage); + op.putHiddenProperty (functionName, func); + + } + } + + class ThrowException extends BuiltinFunctionObject { + String message; + ThrowException (String name, Evaluator evaluator, FunctionPrototype fp, String message) { + super (fp, evaluator, name, 1); + this.message = message == null ? "No error message available" : message; + } + public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { + throw new EcmaScriptException (message); + } + public ESObject doConstruct (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { + throw new EcmaScriptException (message); + } + } + + interface TypeUpdater { + public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException; + } } diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index 81c24047..74242960 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -182,7 +182,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, Runn } protected boolean setNumberOfEvaluators (int n) { - if (n < 1 || n > 512) + if (n < 2 || n > 511) return false; int current = allThreads.size(); synchronized (allThreads) { @@ -199,6 +199,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, Runn try { RequestEvaluator re = (RequestEvaluator) freeThreads.pop (); allThreads.removeElement (re); + typemgr.unregisterRequestEvaluator (re); re.stopThread (); } catch (EmptyStackException empty) { return false; diff --git a/src/helma/framework/core/ESAppNode.java b/src/helma/framework/core/ESAppNode.java index 0d8b70e8..a842ccaf 100644 --- a/src/helma/framework/core/ESAppNode.java +++ b/src/helma/framework/core/ESAppNode.java @@ -23,10 +23,11 @@ public class ESAppNode extends ESNode { app = eval.app; createtime = new DatePrototype (eval.evaluator, node.created()); FunctionPrototype fp = (FunctionPrototype) eval.evaluator.getFunctionPrototype(); - putHiddenProperty("countEvaluators", new AppCountEvaluators ("countEvaluators", evaluator, fp)); - putHiddenProperty("countFreeEvaluators", new AppCountFreeEvaluators ("countFreeEvaluators", evaluator, fp)); - putHiddenProperty("countBusyEvaluators", new AppCountBusyEvaluators ("countBusyEvaluators", evaluator, fp)); - putHiddenProperty("setNumberOfEvaluators", new AppSetNumberOfEvaluators ("setNumberOfEvaluators", evaluator, fp)); + putHiddenProperty("getMaxThreads", new AppCountEvaluators ("getMaxThreads", evaluator, fp)); + putHiddenProperty("getFreeThreads", new AppCountFreeEvaluators ("getFreeThreads", evaluator, fp)); + putHiddenProperty("getActiveThreads", new AppCountBusyEvaluators ("getActiveThreads", evaluator, fp)); + putHiddenProperty("getMaxActiveThreads", new AppCountMaxBusyEvaluators ("getMaxActiveThreads", evaluator, fp)); + putHiddenProperty("setMaxThreads", new AppSetNumberOfEvaluators ("setMaxThreads", evaluator, fp)); } /** @@ -54,7 +55,7 @@ public class ESAppNode extends ESNode { super (fp, evaluator, name, 0); } public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.allThreads.size()); + return new ESNumber (app.allThreads.size()-1); } } @@ -72,7 +73,16 @@ public class ESAppNode extends ESNode { super (fp, evaluator, name, 0); } public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.allThreads.size() - app.freeThreads.size()); + return new ESNumber (app.allThreads.size() - app.freeThreads.size() -1); + } + } + + class AppCountMaxBusyEvaluators extends BuiltinFunctionObject { + AppCountMaxBusyEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) { + super (fp, evaluator, name, 0); + } + public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { + return new ESNumber (app.typemgr.countRegisteredRequestEvaluators () -1); } } @@ -84,7 +94,7 @@ public class ESAppNode extends ESNode { RequestEvaluator ev = new RequestEvaluator (app); if (arguments.length != 1) return ESBoolean.makeBoolean (false); - return ESBoolean.makeBoolean (app.setNumberOfEvaluators (arguments[0].toInt32())); + return ESBoolean.makeBoolean (app.setNumberOfEvaluators (1 + arguments[0].toInt32())); } } diff --git a/src/helma/framework/core/FunctionFile.java b/src/helma/framework/core/FunctionFile.java index d207c220..32337bb9 100644 --- a/src/helma/framework/core/FunctionFile.java +++ b/src/helma/framework/core/FunctionFile.java @@ -44,9 +44,17 @@ public class FunctionFile { lastmod = fmod; // app.typemgr.readFunctionFile (file, prototype.getName ()); + Iterator evals = app.typemgr.getRegisteredRequestEvaluators (); + while (evals.hasNext ()) { + try { + RequestEvaluator reval = (RequestEvaluator) evals.next (); + updateRequestEvaluator (reval); + } catch (Exception ignore) {} + } + } - public void updateRequestEvaluator (RequestEvaluator reval) { + public synchronized void updateRequestEvaluator (RequestEvaluator reval) { EvaluationSource es = new FileEvaluationSource(file.getPath(), null); FileReader fr = null; diff --git a/src/helma/framework/core/RequestEvaluator.java b/src/helma/framework/core/RequestEvaluator.java index 17555ac5..1937f7b4 100644 --- a/src/helma/framework/core/RequestEvaluator.java +++ b/src/helma/framework/core/RequestEvaluator.java @@ -28,6 +28,7 @@ public class RequestEvaluator implements Runnable { Application app; + protected boolean initialized; RequestTrans req; ResponseTrans res; @@ -86,6 +87,7 @@ public class RequestEvaluator implements Runnable { this.objectcache = new LruHashtable (100, .80f); this.prototypes = new Hashtable (); initEvaluator (); + initialized = false; // startThread (); } @@ -132,7 +134,7 @@ public class RequestEvaluator implements Runnable { int txcount = 0; - if (prototypes.size() == 0) + if (!initialized) app.typemgr.initRequestEvaluator (this); do { diff --git a/src/helma/framework/core/Template.java b/src/helma/framework/core/Template.java index 4e199444..2165504f 100644 --- a/src/helma/framework/core/Template.java +++ b/src/helma/framework/core/Template.java @@ -23,7 +23,8 @@ import FESI.Exceptions.*; public class Template extends Action { - ParsedFunction psfunc; + // this is the *_as_string function, which is in addition to the normal one + TypeUpdater psfunc; public Template (File file, String name, Prototype proto) { @@ -132,6 +133,7 @@ public class Template extends Action { } // templateBody.append ("\r\nreturn null;\r\n"); + functionName = name; String fname = name+"_as_string"; String body = templateBody.toString (); @@ -141,7 +143,7 @@ public class Template extends Action { body+"\r\nreturn null;\r\n"); } catch (Exception x) { String message = x.getMessage (); - app.typemgr.generateErrorFeedback (name, message, prototype.getName ()); + pfunc = new ErrorFeedback (name, message); } try { psfunc = parseFunction (fname, @@ -149,12 +151,19 @@ public class Template extends Action { "res.pushStringBuffer(); "+body+"\r\nreturn res.popStringBuffer();\r\n"); } catch (Exception x) { String message = x.getMessage (); - app.typemgr.generateErrorFeedback (fname, message, prototype.getName ()); + psfunc = new ErrorFeedback (fname, message); } + Iterator evals = app.typemgr.getRegisteredRequestEvaluators (); + while (evals.hasNext ()) { + try { + RequestEvaluator reval = (RequestEvaluator) evals.next (); + updateRequestEvaluator (reval); + } catch (Exception ignore) {} + } } - public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException { + public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException { if (pfunc != null) pfunc.updateRequestEvaluator (reval); if (psfunc != null) diff --git a/src/helma/framework/core/TypeManager.java b/src/helma/framework/core/TypeManager.java index d5d5ee62..022fc5bf 100644 --- a/src/helma/framework/core/TypeManager.java +++ b/src/helma/framework/core/TypeManager.java @@ -31,6 +31,10 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants { long idleSeconds = 120; // if idle for longer than 5 minutes, slow down boolean rewire; + // this contains only those evaluatores which have already been initialized + // and thus need to get updates + List registeredEvaluators; + Thread typechecker; // The http broadcaster for pushing out parser output @@ -55,6 +59,7 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants { if (!f.exists()) f.mkdir (); prototypes = new Hashtable (); + registeredEvaluators = Collections.synchronizedList (new ArrayList (30)); nodeProto = null; } @@ -277,38 +282,9 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants { - protected void generateErrorFeedback (String funcname, String message, String protoname) - throws EcmaScriptException { - int size = app.allThreads.size (); - - for (int i=0; i