more work to solve "shringking prototypes" problem

in FunctionFile
This commit is contained in:
hns 2001-03-07 16:49:11 +00:00
parent 20e8bb8987
commit 27d07e599c
2 changed files with 85 additions and 29 deletions

View file

@ -24,9 +24,11 @@ public class FunctionFile implements Updatable {
Application app; Application app;
File file; File file;
long lastmod; long lastmod;
// a set of funcion names defined by this file. We keep this to be able to // a set of funcion names defined by this file. We keep this to be able to
// remove them once the file should get removed // remove them once the file should get removed
HashSet functionNames; HashSet declaredProps;
long declaredPropsTimestamp;
public FunctionFile (File file, String name, Prototype proto) { public FunctionFile (File file, String name, Prototype proto) {
this.prototype = proto; this.prototype = proto;
@ -54,13 +56,15 @@ public class FunctionFile implements Updatable {
} else { } else {
lastmod = file.lastModified (); lastmod = file.lastModified ();
functionNames = null;
// app.typemgr.readFunctionFile (file, prototype.getName ()); // app.typemgr.readFunctionFile (file, prototype.getName ());
Iterator evals = app.typemgr.getRegisteredRequestEvaluators (); Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
while (evals.hasNext ()) { while (evals.hasNext ()) {
try { try {
RequestEvaluator reval = (RequestEvaluator) evals.next (); RequestEvaluator reval = (RequestEvaluator) evals.next ();
updateRequestEvaluator (reval); updateRequestEvaluator (reval);
} catch (Exception ignore) {} } catch (Exception ignore) {}
} }
} }
@ -72,23 +76,40 @@ public class FunctionFile implements Updatable {
EvaluationSource es = new FileEvaluationSource(file.getPath(), null); EvaluationSource es = new FileEvaluationSource(file.getPath(), null);
FileReader fr = null; FileReader fr = null;
HashMap priorProps = new HashMap (); HashMap priorProps = null;
ObjectPrototype op = null; HashSet newProps = null;
try { try {
op = reval.getPrototype (prototype.getName());
ObjectPrototype op = reval.getPrototype (prototype.getName());
// extract all properties from prototype _before_ evaluation, so we can compare afterwards
// but only do this is declaredProps is not up to date yet
if (declaredPropsTimestamp != lastmod) {
priorProps = new HashMap ();
// remember properties before evaluation, so we can tell what's new afterwards // remember properties before evaluation, so we can tell what's new afterwards
if (functionNames == null) try { try {
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) { for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
String prop = (String) en.nextElement (); String prop = (String) en.nextElement ();
priorProps.put (prop, op.getProperty (prop, prop.hashCode())); priorProps.put (prop, op.getProperty (prop, prop.hashCode()));
} }
} catch (Exception ignore) {} } catch (Exception ignore) {}
}
// do the update, evaluating the file
fr = new FileReader(file); fr = new FileReader(file);
reval.evaluator.evaluate(fr, op, es, false); reval.evaluator.evaluate(fr, op, es, false);
// check what's new
if (declaredPropsTimestamp != lastmod) try {
newProps = new HashSet ();
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
String prop = (String) en.nextElement ();
if (priorProps.get (prop) == null || op.getProperty (prop, prop.hashCode()) != priorProps.get (prop))
newProps.add (prop);
}
} catch (Exception ignore) {}
} catch (IOException e) { } catch (IOException e) {
app.logEvent ("Error parsing function file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+e); app.logEvent ("Error parsing function file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+e);
} catch (EcmaScriptException e) { } catch (EcmaScriptException e) {
@ -100,44 +121,64 @@ public class FunctionFile implements Updatable {
} catch (IOException ignore) {} } catch (IOException ignore) {}
} }
// check // now remove the props that were not refreshed, and set declared props to new collection
if (functionNames == null && op != null) try { if (declaredPropsTimestamp != lastmod) {
functionNames = new HashSet (); declaredPropsTimestamp = lastmod;
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) { if (declaredProps != null) {
String prop = (String) en.nextElement (); declaredProps.removeAll (newProps);
if (priorProps.get (prop) == null || op.getProperty (prop, prop.hashCode()) != priorProps.get (prop)) removeProperties (declaredProps);
functionNames.add (prop);
} }
} catch (Exception ignore) {} declaredProps = newProps;
// System.err.println ("DECLAREDPROPS = "+declaredProps);
} }
} }
}
void remove () { void remove () {
prototype.functions.remove (name); prototype.functions.remove (name);
prototype.updatables.remove (file.getName()); prototype.updatables.remove (file.getName());
// if we did not add anything to any evaluator, we're done // if we did not add anything to any evaluator, we're done
if (functionNames == null) if (declaredProps == null || declaredProps.size() == 0)
return; return;
removeProperties (declaredProps);
}
/**
* Remove the properties in the HashMap iff they're still the same as declared by this file.
* This method is called by remove() with the latest props, and by update with the prior props
* after the file has been reevaluated.
*/
void removeProperties (HashSet props) {
// first loop through other function files in this prototype to make a set of properties
// owned by other files.
HashSet otherFiles = new HashSet ();
for (Iterator it=prototype.functions.values ().iterator (); it.hasNext (); ) {
FunctionFile other = (FunctionFile) it.next ();
if (other != this && other.declaredProps != null)
otherFiles.addAll (other.declaredProps);
}
Iterator evals = app.typemgr.getRegisteredRequestEvaluators (); Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
while (evals.hasNext ()) { while (evals.hasNext ()) {
try { try {
RequestEvaluator reval = (RequestEvaluator) evals.next (); RequestEvaluator reval = (RequestEvaluator) evals.next ();
ObjectPrototype op = reval.getPrototype (prototype.getName()); ObjectPrototype op = reval.getPrototype (prototype.getName());
for (Iterator it=functionNames.iterator(); it.hasNext(); ) { for (Iterator it = props.iterator (); it.hasNext (); ) {
String fname = (String) it.next (); String fname = (String) it.next ();
ESValue esv = op.getProperty (fname, fname.hashCode()); // check if this property has been declared by some other function file in the meantime
if (esv instanceof ConstructedFunctionObject) { if (otherFiles.contains (fname))
continue;
op.deleteProperty (fname, fname.hashCode()); op.deleteProperty (fname, fname.hashCode());
} // System.err.println ("REMOVING PROP: "+fname);
} }
} catch (Exception ignore) {} } catch (Exception ignore) {}
} }
} }
} }

View file

@ -37,6 +37,14 @@ public class TypeManager implements Runnable {
// } catch (IOException ignore) {} // } catch (IOException ignore) {}
// } // }
static HashSet standardTypes;
static {
standardTypes = new HashSet ();
standardTypes.add ("user");
standardTypes.add ("global");
standardTypes.add ("root");
standardTypes.add ("hopobject");
}
public TypeManager (Application app) { public TypeManager (Application app) {
this.app = app; this.app = app;
@ -87,6 +95,13 @@ public class TypeManager implements Runnable {
} }
} }
/* for (Iterator it=prototypes.values ().iterator (); it.hasNext (); ) {
Prototype proto = (Prototype) it.next ();
if (!proto.getCodeDir ().exists ()) {
app.logEvent ("TypeManager: Can't remove prototype from running application. Restart for changes to take effect.");
}
} */
if (rewire) { if (rewire) {
// there have been changes @ DbMappings // there have been changes @ DbMappings
app.rewireDbMappings (); app.rewireDbMappings ();
@ -134,7 +149,7 @@ public class TypeManager implements Runnable {
// for each idle minute, add 300 ms to sleeptime until 5 secs are reached. // for each idle minute, add 300 ms to sleeptime until 5 secs are reached.
// (10 secs are reached after 30 minutes of idle state) // (10 secs are reached after 30 minutes of idle state)
// the above is all false. // the above is all false.
long sleeptime = 1500 + Math.min (idleSeconds*30, 3500); long sleeptime = 1000 + Math.min (idleSeconds*30, 4000);
typechecker.sleep (sleeptime); typechecker.sleep (sleeptime);
} catch (InterruptedException x) { } catch (InterruptedException x) {
// app.logEvent ("Typechecker interrupted"); // app.logEvent ("Typechecker interrupted");