Threads and evaluators are now started in lazy mode - only when needed. Halleluja!

This commit is contained in:
hns 2001-01-16 22:31:08 +00:00
parent 73bcc24ffc
commit 6d0491e2de
12 changed files with 396 additions and 235 deletions

View file

@ -8,6 +8,13 @@ import java.io.*;
import helma.framework.*;
import helma.objectmodel.IServer;
import FESI.Data.*;
import FESI.Parser.*;
import FESI.AST.ASTFormalParameterList;
import FESI.AST.ASTStatementList;
import FESI.AST.EcmaScriptTreeConstants;
import FESI.Interpreter.*;
import FESI.Exceptions.*;
/**
@ -20,34 +27,40 @@ import FESI.Data.*;
public class Action {
String name;
String functionName;
Prototype prototype;
Application app;
File file;
long lastmod;
ParsedFunction pfunc;
public Action (File file, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.app;
this.name = name;
this.file = file;
update (file);
}
public void update (File f) {
long fmod = f.lastModified ();
this.file = f;
long fmod = file.lastModified ();
if (lastmod == fmod)
return;
try {
FileReader reader = new FileReader (f);
char cbuf[] = new char[(int)f.length ()];
FileReader reader = new FileReader (file);
char cbuf[] = new char[(int) file.length ()];
reader.read (cbuf);
reader.close ();
String content = new String (cbuf);
update (content);
} catch (Exception filex) {
IServer.getLogger().log ("*** Error reading template file "+f+": "+filex);
IServer.getLogger().log ("*** Error reading action file "+file+": "+filex);
}
lastmod = fmod;
}
@ -57,13 +70,13 @@ public class Action {
public void update (String content) throws Exception {
// IServer.getLogger().log ("Reading text template " + name);
functionName = name+"_hop_action";
String fname = name+"_hop_action";
try {
app.typemgr.readFunction (functionName, "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", content, prototype.getName ());
pfunc = parseFunction (fname, "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", content);
} catch (Exception x) {
String message = x.getMessage ();
app.typemgr.generateErrorFeedback (functionName, message, prototype.getName ());
app.typemgr.generateErrorFeedback (fname, message, prototype.getName ());
}
}
@ -74,9 +87,97 @@ public class Action {
}
public String getFunctionName () {
return functionName;
return pfunc.functionName;
}
protected ParsedFunction parseFunction (String funcname, String params, String body) throws EcmaScriptException {
// ESObject fp = app.eval.evaluator.getFunctionPrototype();
// ConstructedFunctionObject function = null;
ASTFormalParameterList fpl = null;
ASTStatementList sl = null;
FunctionEvaluationSource fes = null;
if (body == null || "".equals (body.trim()))
body = ";\r\n";
else
body = body + "\r\n";
if (params == null) params = "";
else params = params.trim ();
String fulltext = "function "+funcname+" (" + params + ") {\n" + body + "\n}";
EcmaScript parser;
StringReader is;
// Special case for empty parameters
if (params.length()==0) {
fpl = new ASTFormalParameterList(EcmaScriptTreeConstants.JJTFORMALPARAMETERLIST);
} else {
is = new java.io.StringReader(params);
parser = new EcmaScript(is);
try {
fpl = (ASTFormalParameterList) parser.FormalParameterList();
is.close();
} catch (ParseException x) {
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
}
}
// this is very very very strange: without the toString, lots of obscure exceptions
// deep inside the parser...
is = new java.io.StringReader(body.toString ());
try {
parser = new EcmaScript (is);
sl = (ASTStatementList) parser.StatementList();
is.close();
} catch (ParseException x) {
IServer.getLogger().log ("Error parsing file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+x);
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
} catch (Exception x) {
IServer.getLogger().log ("Error parsing file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+x);
throw new RuntimeException (x.getMessage ());
}
fes = new FunctionEvaluationSource (new StringEvaluationSource(fulltext, null), funcname);
return new ParsedFunction (fpl, sl, fes, fulltext, funcname);
}
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
if (pfunc != null)
pfunc.updateRequestEvaluator (reval);
}
class ParsedFunction {
ASTFormalParameterList fpl = null;
ASTStatementList sl = null;
FunctionEvaluationSource fes = null;
String fullFunctionText = null;
String functionName;
public ParsedFunction (ASTFormalParameterList fpl, ASTStatementList sl, FunctionEvaluationSource fes,
String fullFunctionText, String functionName) {
this.fpl = fpl;
this.sl = sl;
this.fes = fes;
this.fullFunctionText = fullFunctionText;
this.functionName = functionName;
}
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
ObjectPrototype op = reval.getPrototype (prototype.getName());
EcmaScriptVariableVisitor vdvisitor = reval.evaluator.getVarDeclarationVisitor();
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction (
reval.evaluator, functionName, fes,
fullFunctionText, fpl.getArguments(), vnames, sl);
op.putHiddenProperty (functionName, fp);
}
}
}

View file

@ -38,7 +38,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, Runn
TypeManager typemgr;
RequestEvaluator eval;
private Stack freeThreads;
protected Stack freeThreads;
protected Vector allThreads;
Hashtable sessions;
@ -154,7 +154,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, Runn
if (allThreads != null) {
for (Enumeration e=allThreads.elements (); e.hasMoreElements (); ) {
RequestEvaluator ev = (RequestEvaluator) e.nextElement ();
ev.stop ();
ev.stopThread ();
}
}
allThreads.removeAllElements ();
@ -166,20 +166,49 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, Runn
}
}
public synchronized RequestEvaluator getEvaluator () {
protected RequestEvaluator getEvaluator () {
if (freeThreads == null)
throw new ApplicationStoppedException ();
if (freeThreads.empty ())
try {
return (RequestEvaluator) freeThreads.pop ();
} catch (EmptyStackException nothreads) {
throw new RuntimeException ("Maximum Thread count reached.");
RequestEvaluator ev = (RequestEvaluator) freeThreads.pop ();
return ev;
}
}
public synchronized void releaseEvaluator (RequestEvaluator ev) {
protected void releaseEvaluator (RequestEvaluator ev) {
if (ev != null)
freeThreads.push (ev);
}
protected boolean setNumberOfEvaluators (int n) {
if (n < 1 || n > 512)
return false;
int current = allThreads.size();
synchronized (allThreads) {
if (n > current) {
int toBeCreated = n - current;
for (int i=0; i<toBeCreated; i++) {
RequestEvaluator ev = new RequestEvaluator (this);
freeThreads.push (ev);
allThreads.addElement (ev);
}
} else if (n < current) {
int toBeDestroyed = current - n;
for (int i=0; i<toBeDestroyed; i++) {
try {
RequestEvaluator re = (RequestEvaluator) freeThreads.pop ();
allThreads.removeElement (re);
re.stopThread ();
} catch (EmptyStackException empty) {
return false;
}
}
}
}
return true;
}
public ResponseTrans execute (RequestTrans req) {
requestCount += 1;
@ -243,8 +272,6 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, Runn
}
public Prototype getPrototype (String str) {
if (debug)
IServer.getLogger().log ("retrieving prototype for name "+str);
return typemgr.getPrototype (str);
}

View file

@ -6,6 +6,7 @@ package helma.framework.core;
import helma.objectmodel.*;
import FESI.Exceptions.*;
import FESI.Data.*;
import FESI.Interpreter.Evaluator;
/**
* ESApp represents the app node of an application, providing an app-wide transient shared
@ -17,10 +18,15 @@ public class ESAppNode extends ESNode {
private Application app;
private DatePrototype createtime;
public ESAppNode (INode node, RequestEvaluator eval) {
public ESAppNode (INode node, RequestEvaluator eval) throws EcmaScriptException {
super (eval.esNodePrototype, eval.evaluator, node, eval);
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));
}
/**
@ -43,6 +49,47 @@ public class ESAppNode extends ESNode {
}
class AppCountEvaluators extends BuiltinFunctionObject {
AppCountEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
super (fp, evaluator, name, 0);
}
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
return new ESNumber (app.allThreads.size());
}
}
class AppCountFreeEvaluators extends BuiltinFunctionObject {
AppCountFreeEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
super (fp, evaluator, name, 0);
}
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
return new ESNumber (app.freeThreads.size());
}
}
class AppCountBusyEvaluators extends BuiltinFunctionObject {
AppCountBusyEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
super (fp, evaluator, name, 0);
}
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
return new ESNumber (app.allThreads.size() - app.freeThreads.size());
}
}
class AppSetNumberOfEvaluators extends BuiltinFunctionObject {
AppSetNumberOfEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) {
super (fp, evaluator, name, 1);
}
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
RequestEvaluator ev = new RequestEvaluator (app);
if (arguments.length != 1)
return ESBoolean.makeBoolean (false);
return ESBoolean.makeBoolean (app.setNumberOfEvaluators (arguments[0].toInt32()));
}
}
public String toString () {
return ("AppNode "+node.getNameOrID ());
}

View file

@ -6,6 +6,10 @@ package helma.framework.core;
import java.util.*;
import java.io.*;
import helma.framework.*;
import helma.objectmodel.IServer;
import FESI.Data.ObjectPrototype;
import FESI.Exceptions.EcmaScriptException;
import FESI.Interpreter.*;
/**
@ -18,24 +22,51 @@ public class FunctionFile {
String name;
Prototype prototype;
Application app;
File file;
long lastmod;
public FunctionFile (File file, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.app;
this.name = name;
this.file = file;
update (file);
}
public void update (File f) {
long fmod = f.lastModified ();
this.file = f;
long fmod = file.lastModified ();
if (lastmod == fmod)
return;
lastmod = fmod;
app.typemgr.readFunctionFile (f, prototype.getName ());
// app.typemgr.readFunctionFile (file, prototype.getName ());
}
public void updateRequestEvaluator (RequestEvaluator reval) {
EvaluationSource es = new FileEvaluationSource(file.getPath(), null);
FileReader fr = null;
try {
fr = new FileReader(file);
ObjectPrototype op = reval.getPrototype (prototype.getName());
reval.evaluator.evaluate(fr, op, es, false);
} catch (IOException e) {
IServer.getLogger().log ("Error parsing function file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+e);
} catch (EcmaScriptException e) {
IServer.getLogger().log ("Error parsing function file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+e);
} finally {
if (fr!=null) {
try {
fr.close();
} catch (IOException ignore) {}
}
}
}

View file

@ -7,6 +7,7 @@ import java.util.*;
import java.io.*;
import helma.framework.*;
import helma.objectmodel.*;
import FESI.Exceptions.EcmaScriptException;
/**
@ -119,6 +120,24 @@ public class Prototype {
}
public void initRequestEvaluator (RequestEvaluator reval) {
for (Enumeration en = functions.elements(); en.hasMoreElements(); ) {
FunctionFile ff = (FunctionFile) en.nextElement ();
ff.updateRequestEvaluator (reval);
}
for (Enumeration en = templates.elements(); en.hasMoreElements(); ) {
Template tmp = (Template) en.nextElement ();
try {
tmp.updateRequestEvaluator (reval);
} catch (EcmaScriptException ignore) {}
}
for (Enumeration en = actions.elements(); en.hasMoreElements(); ) {
Action act = (Action) en.nextElement ();
try {
act.updateRequestEvaluator (reval);
} catch (EcmaScriptException ignore) {}
}
}
}

View file

@ -86,7 +86,7 @@ public class RequestEvaluator implements Runnable {
this.objectcache = new LruHashtable (100, .80f);
this.prototypes = new Hashtable ();
initEvaluator ();
startThread ();
// startThread ();
}
@ -119,30 +119,25 @@ public class RequestEvaluator implements Runnable {
}
private void startThread () {
/* private void startThread () {
rtx = new Transactor (this, app.nmgr);
evaluator.thread = rtx;
rtx.start ();
// yield to make sure the transactor thread reaches waiting status before the first
// invocation request comes in
Thread.yield ();
}
} */
public void run () {
int txcount = 0;
while (evaluator.thread == Thread.currentThread () && evaluator.thread == rtx) {
if (prototypes.size() == 0)
app.typemgr.initRequestEvaluator (this);
synchronized (this) {
notifyAll ();
try {
wait ();
} catch (InterruptedException ir) {
Thread.currentThread().interrupt();
}
}
do {
// make sure there is only one thread running per instance of this class
if (Thread.currentThread () != rtx)
return;
@ -166,11 +161,6 @@ public class RequestEvaluator implements Runnable {
rtx.timer.beginEvent (requestPath+" init");
rtx.begin (requestPath);
if (app.debug) {
IServer.getLogger().log ("request transactor = "+this);
IServer.getLogger().log ("user = "+user);
}
Action action = null;
root = app.getDataRoot ();
@ -187,11 +177,6 @@ public class RequestEvaluator implements Runnable {
reqData.setData (req.getReqData());
req.data = reqData;
if (app.debug) {
IServer.getLogger().log ("root = "+root);
IServer.getLogger().log ("usernode = "+esu);
}
try {
if (req.path == null || "".equals (req.path.trim ())) {
@ -454,33 +439,35 @@ public class RequestEvaluator implements Runnable {
// create a new Thread every 1000 requests. The current one will fade out
if (txcount++ > 1000) {
rtx.cleanup (); // close sql connections held by this thread
startThread ();
stopThread (); // stop thread - a new one will be created when needed
break;
}
}
// IServer.getLogger().log (this+ " exiting.");
synchronized (this) {
notifyAll ();
try {
wait ();
} catch (InterruptedException ir) {
Thread.currentThread ().interrupt ();
}
}
} while (evaluator.thread == Thread.currentThread () && evaluator.thread == rtx);
}
public synchronized ResponseTrans invoke (RequestTrans req, User user) throws Exception {
checkThread ();
this.reqtype = HTTP;
this.req = req;
this.user = user;
this.res = new ResponseTrans ();
notifyAll ();
checkThread ();
wait (app.requestTimeout);
if (reqtype > 0) {
IServer.getLogger().log ("Stopping Thread for Request "+app.getName()+"/"+req.path);
evaluator.thread = null;
rtx.kill ();
stopThread ();
res.reset ();
res.write ("<b>Error in application '"+app.getName()+"':</b> <br><br><pre>Request timed out.</pre>");
rtx = new Transactor (this, app.nmgr);
evaluator.thread = rtx;
rtx.start ();
Thread.yield ();
}
return res;
@ -488,7 +475,6 @@ public class RequestEvaluator implements Runnable {
public synchronized Object invokeXmlRpc (String method, Vector args) throws Exception {
checkThread ();
this.reqtype = XMLRPC;
this.user = null;
this.method = method;
@ -496,16 +482,10 @@ public class RequestEvaluator implements Runnable {
result = null;
exception = null;
notifyAll ();
checkThread ();
wait (app.requestTimeout);
if (reqtype > 0) {
IServer.getLogger().log ("Stopping Thread");
evaluator.thread = null;
rtx.kill ();
rtx = new Transactor (this, app.nmgr);
evaluator.thread = rtx;
rtx.start ();
Thread.yield ();
stopThread ();
}
if (exception != null)
@ -525,7 +505,6 @@ public class RequestEvaluator implements Runnable {
public synchronized ESValue invokeFunction (ESObject obj, String functionName, ESValue[] args)
throws Exception {
checkThread ();
this.reqtype = INTERNAL;
this.user = null;
this.current = obj;
@ -534,17 +513,11 @@ public class RequestEvaluator implements Runnable {
esresult = ESNull.theNull;
exception = null;
notifyAll ();
checkThread ();
wait (60000l*15); // give internal call more time (15 minutes) to complete
if (reqtype > 0) {
IServer.getLogger().log ("Stopping Thread");
evaluator.thread = null;
rtx.kill ();
rtx = new Transactor (this, app.nmgr);
evaluator.thread = rtx;
rtx.start ();
Thread.yield ();
stopThread ();
}
if (exception != null)
@ -554,7 +527,6 @@ public class RequestEvaluator implements Runnable {
public synchronized ESValue invokeFunction (User user, String functionName, ESValue[] args)
throws Exception {
checkThread ();
this.reqtype = INTERNAL;
this.user = user;
this.current = null;
@ -563,17 +535,11 @@ public class RequestEvaluator implements Runnable {
esresult = ESNull.theNull;
exception = null;
notifyAll ();
checkThread ();
wait (app.requestTimeout);
if (reqtype > 0) {
IServer.getLogger().log ("Stopping Thread");
evaluator.thread = null;
rtx.kill ();
rtx = new Transactor (this, app.nmgr);
evaluator.thread = rtx;
rtx.start ();
Thread.yield ();
stopThread ();
}
if (exception != null)
@ -583,24 +549,32 @@ public class RequestEvaluator implements Runnable {
/**
* Stop this request evaluator. If currently active kill the request, otherwise just
* Stop this request evaluator's current thread. If currently active kill the request, otherwise just
* notify.
*/
public synchronized void stop () {
public synchronized void stopThread () {
// IServer.getLogger().log ("Stopping Thread");
evaluator.thread = null;
if (reqtype != NONE) {
rtx.kill ();
} else {
notifyAll ();
Transactor t = rtx;
rtx = null;
if (t != null) {
if (reqtype != NONE) {
t.kill ();
} else {
notifyAll ();
}
t.cleanup ();
}
}
private void checkThread () {
private synchronized void checkThread () throws InterruptedException {
if (rtx == null || !rtx.isAlive()) {
// IServer.getLogger().log ("Starting Thread");
rtx = new Transactor (this, app.nmgr);
evaluator.thread = rtx;
rtx.start ();
Thread.yield ();
} else {
notifyAll ();
}
}

View file

@ -7,6 +7,7 @@ import java.util.*;
import java.io.*;
import helma.framework.*;
import FESI.Data.*;
import FESI.Exceptions.*;
/**
@ -22,6 +23,9 @@ import FESI.Data.*;
public class Template extends Action {
ParsedFunction psfunc;
public Template (File file, String name, Prototype proto) {
super (file, name, proto);
}
@ -128,25 +132,21 @@ public class Template extends Action {
}
// templateBody.append ("\r\nreturn null;\r\n");
functionName = name;
String fname = name+"_as_string";
String body = templateBody.toString ();
try {
app.typemgr.readFunction (name,
pfunc = parseFunction (name,
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
body+"\r\nreturn null;\r\n",
prototype.getName ());
body+"\r\nreturn null;\r\n");
} catch (Exception x) {
String message = x.getMessage ();
app.typemgr.generateErrorFeedback (name, message, prototype.getName ());
}
try {
app.typemgr.readFunction (fname,
psfunc = parseFunction (fname,
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
"res.pushStringBuffer(); "+body+"\r\nreturn res.popStringBuffer();\r\n",
prototype.getName ());
"res.pushStringBuffer(); "+body+"\r\nreturn res.popStringBuffer();\r\n");
} catch (Exception x) {
String message = x.getMessage ();
app.typemgr.generateErrorFeedback (fname, message, prototype.getName ());
@ -154,6 +154,12 @@ public class Template extends Action {
}
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
if (pfunc != null)
pfunc.updateRequestEvaluator (reval);
if (psfunc != null)
psfunc.updateRequestEvaluator (reval);
}
class Part {

View file

@ -151,34 +151,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
public void registerPrototype (String name, File dir, Prototype proto) {
// IServer.getLogger().log ("registering prototype "+name);
int size = app.allThreads.size ();
for (int i=0; i<size; i++) {
RequestEvaluator reval = (RequestEvaluator) app.allThreads.elementAt (i);
ObjectPrototype op = null;
if ("user".equalsIgnoreCase (name))
op = reval.esUserPrototype;
else if ("global".equalsIgnoreCase (name))
op = reval.global;
else if ("hopobject".equalsIgnoreCase (name))
op = reval.esNodePrototype;
else {
op = new ObjectPrototype (reval.esNodePrototype, reval.evaluator);
try {
op.putProperty ("prototypename", new ESString (name), "prototypename".hashCode ());
} catch (EcmaScriptException ignore) {}
}
reval.putPrototype (name, op);
// Register a constructor for all types except global.
// This will first create a node and then call the actual (scripted) constructor on it.
if (!"global".equalsIgnoreCase (name)) {
try {
FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype();
reval.global.putHiddenProperty (name, new NodeConstructor (name, fp, reval));
} catch (EcmaScriptException ignore) {}
}
}
// show the type checker thread that there has been type activity
idleSeconds = 0;
@ -202,7 +174,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
ntemp.put (tmpname, t);
} catch (Throwable x) {
IServer.getLogger().log ("Error creating prototype: "+x);
// broadcaster.broadcast ("Error creating prototype "+list[i]+":<br>"+x+"<br><hr>");
}
} else if (list[i].endsWith (app.scriptExtension) && tmpfile.length () > 0) {
@ -211,7 +182,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
nfunc.put (tmpname, ff);
} catch (Throwable x) {
IServer.getLogger().log ("Error creating prototype: "+x);
// broadcaster.broadcast ("Error creating prototype "+list[i]+":<br>"+x+"<br><hr>");
}
} else if (list[i].endsWith (app.actionExtension) && tmpfile.length () > 0) {
try {
@ -219,7 +189,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
nact.put (tmpname, af);
} catch (Throwable x) {
IServer.getLogger().log ("Error creating prototype: "+x);
// broadcaster.broadcast ("Error creating prototype "+list[i]+":<br>"+x+"<br><hr>");
}
}
}
@ -257,7 +226,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
}
} catch (Throwable x) {
IServer.getLogger().log ("Error updating prototype: "+x);
// broadcaster.broadcast ("Error updating prototype "+list[i]+":<br>"+x+"<br><hr>");
}
ntemp.put (tmpname, t);
@ -273,7 +241,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
}
} catch (Throwable x) {
IServer.getLogger().log ("Error updating prototype: "+x);
// broadcaster.broadcast ("Error updating prototype "+list[i]+":<br>"+x+"<br><hr>");
}
nfunc.put (tmpname, ff);
@ -289,7 +256,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
}
} catch (Throwable x) {
IServer.getLogger().log ("Error updating prototype: "+x);
// broadcaster.broadcast ("Error updating prototype "+list[i]+":<br>"+x+"<br><hr>");
}
nact.put (tmpname, af);
@ -309,100 +275,6 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
proto.actions = nact;
}
protected void readFunctionFile (File f, String protoname) {
EvaluationSource es = new FileEvaluationSource(f.getPath(), null);
FileReader fr = null;
int size = app.allThreads.size ();
for (int i=0; i<size; i++) {
RequestEvaluator reval = (RequestEvaluator) app.allThreads.elementAt (i);
try {
fr = new FileReader(f);
ObjectPrototype op = reval.getPrototype (protoname);
reval.evaluator.evaluate(fr, op, es, false);
} catch (IOException e) {
IServer.getLogger().log ("*** Error reading function file "+f+": "+e);
} catch (EcmaScriptException e) {
IServer.getLogger().log ("*** Error reading function file "+f+": "+e);
} finally {
if (fr!=null) {
try {
fr.close();
} catch (IOException ignore) {}
}
}
}
}
protected void readFunction (String funcname, String params, String body, String protoname)
throws EcmaScriptException {
// ESObject fp = app.eval.evaluator.getFunctionPrototype();
ConstructedFunctionObject function = null;
ASTFormalParameterList fpl = null;
ASTStatementList sl = null;
if (body == null || "".equals (body.trim()))
body = ";\r\n";
else
body = body + "\r\n";
if (params == null) params = "";
else params = params.trim ();
String fullFunctionText = "function "+funcname+" (" + params + ") {\n" + body + "\n}";
EcmaScript parser;
StringReader is;
// Special case for empty parameters
if (params.length()==0) {
fpl = new ASTFormalParameterList(JJTFORMALPARAMETERLIST);
} else {
is = new java.io.StringReader(params);
parser = new EcmaScript(is);
try {
fpl = (ASTFormalParameterList) parser.FormalParameterList();
is.close();
} catch (ParseException x) {
throw new EcmaScriptParseException (x, new StringEvaluationSource(fullFunctionText, null));
}
}
// this is very very very strange: without the toString, lots of obscure exceptions
// deep inside the parser...
is = new java.io.StringReader(body.toString ());
try {
parser = new EcmaScript (is);
sl = (ASTStatementList) parser.StatementList();
is.close();
} catch (ParseException x) {
x.printStackTrace ();
throw new EcmaScriptParseException (x, new StringEvaluationSource(fullFunctionText, null));
} catch (Exception x) {
x.printStackTrace ();
throw new RuntimeException (x.getMessage ());
}
FunctionEvaluationSource fes = new FunctionEvaluationSource (
new StringEvaluationSource(fullFunctionText,null), funcname);
DbMapping dbmap = null;
int size = app.allThreads.size ();
for (int i=0; i<size; i++) {
RequestEvaluator reval = (RequestEvaluator) app.allThreads.elementAt (i);
ObjectPrototype op = reval.getPrototype (protoname);
EcmaScriptVariableVisitor vdvisitor = reval.evaluator.getVarDeclarationVisitor();
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction(reval.evaluator, funcname, fes, fullFunctionText, fpl.getArguments(), vnames, sl);
op.putHiddenProperty (funcname, fp);
}
}
protected void generateErrorFeedback (String funcname, String message, String protoname)
@ -413,6 +285,7 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
RequestEvaluator reval = (RequestEvaluator) app.allThreads.elementAt (i);
ObjectPrototype op = reval.getPrototype (protoname);
if (op == null) return;
FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype ();
FunctionPrototype func = new ThrowException (funcname, reval.evaluator, fp, message);
@ -435,6 +308,38 @@ public class TypeManager implements Runnable, EcmaScriptTreeConstants {
}
}
public void initRequestEvaluator (RequestEvaluator reval) {
for (Enumeration en = prototypes.elements(); en.hasMoreElements(); ) {
Prototype p = (Prototype) en.nextElement ();
String name = p.getName ();
ObjectPrototype op = null;
if ("user".equalsIgnoreCase (name))
op = reval.esUserPrototype;
else if ("global".equalsIgnoreCase (name))
op = reval.global;
else if ("hopobject".equalsIgnoreCase (name))
op = reval.esNodePrototype;
else {
op = new ObjectPrototype (reval.esNodePrototype, reval.evaluator);
try {
op.putProperty ("prototypename", new ESString (name), "prototypename".hashCode ());
} catch (EcmaScriptException ignore) {}
}
reval.putPrototype (name, op);
// Register a constructor for all types except global.
// This will first create a node and then call the actual (scripted) constructor on it.
if (!"global".equalsIgnoreCase (name)) {
try {
FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype();
reval.global.putHiddenProperty (name, new NodeConstructor (name, fp, reval));
} catch (EcmaScriptException ignore) {}
}
p.initRequestEvaluator (reval);
}
}
}

View file

@ -201,7 +201,7 @@ public class Transactor extends Thread {
// The thread is told to stop by setting the thread flag in the EcmaScript
// evaluator, so we can hope that it stops without doing anything else.
try {
join (1000);
join (500);
} catch (InterruptedException ir) {
Thread.currentThread().interrupt();
}
@ -222,6 +222,7 @@ public class Transactor extends Thread {
}
public void cleanup () {
// IServer.getLogger().log("Cleaning up Transactor thread");
if (sqlCon != null) {
for (Iterator i=sqlCon.values().iterator(); i.hasNext(); ) {
try {

View file

@ -76,10 +76,6 @@ public class XmlRpcClient implements XmlRpcHandler {
return retval;
} finally {
worker.reset ();
if (workers < 20 && !worker.fault)
pool.push (worker);
else
workers -= 1;
}
}
@ -153,6 +149,8 @@ public class XmlRpcClient implements XmlRpcHandler {
} catch (Exception x) {
if (callback != null)
callback.handleError (x, url, method);
} finally {
reset ();
}
System.err.println ("GOT: "+result);
}
@ -255,6 +253,11 @@ public class XmlRpcClient implements XmlRpcHandler {
result = null;
params = null;
callback = null;
if (workers < 20 && !fault)
pool.push (this);
else
workers -= 1;
}
} // end of inner class Worker
@ -274,7 +277,7 @@ public class XmlRpcClient implements XmlRpcHandler {
} catch (NumberFormatException nfx) {
v.addElement (args[i]);
}
XmlRpcClient client = new XmlRpcClient (url);
XmlRpcClient client = new XmlRpcClientLite (url);
try {
/* System.err.println (*/client.executeAsync (method, v, null);
} catch (Exception ex) {

View file

@ -75,12 +75,15 @@ public class XmlRpcClientLite extends XmlRpcClient {
}
class Worker extends XmlRpc {
class Worker extends XmlRpc implements Runnable {
boolean fault;
Object result = null;
HttpClient client = null;
StringBuffer strbuf;
String method;
Vector params;
AsyncCallback callback = null;
public Worker () {
super ();
@ -88,6 +91,36 @@ public class XmlRpcClientLite extends XmlRpcClient {
public Object execute (String method, Vector params) throws XmlRpcException, IOException {
this.method = method;
this.params = params;
return executeCall ();
}
public void executeAsync (String method, Vector params, AsyncCallback callback) {
this.method = method;
this.params = params;
this.callback = callback;
Thread t = new Thread (this);
t.start ();
}
public void run () {
Object res = null;
try {
res = executeCall ();
// notify callback object
if (callback != null)
callback.handleResult (res, url, method);
} catch (Exception x) {
if (callback != null)
callback.handleError (x, url, method);
} finally {
reset ();
}
System.err.println ("GOT: "+result);
}
private Object executeCall () throws XmlRpcException, IOException {
long now = System.currentTimeMillis ();
fault = false;
try {
@ -196,6 +229,20 @@ public class XmlRpcClientLite extends XmlRpcClient {
super.startElement (name, atts);
}
/**
* Release possibly big per-call object references to allow them to be garbage collected
*/
public void reset () {
result = null;
params = null;
callback = null;
if (workers < 20 && !fault)
pool.push (this);
else
workers -= 1;
}
} // end of class Worker