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;
File file;
long lastmod;
// a set of funcion names defined by this file. We keep this to be able to
// remove them once the file should get removed
HashSet functionNames;
HashSet declaredProps;
long declaredPropsTimestamp;
public FunctionFile (File file, String name, Prototype proto) {
this.prototype = proto;
@ -54,13 +56,15 @@ public class FunctionFile implements Updatable {
} else {
lastmod = file.lastModified ();
functionNames = null;
// 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) {}
}
}
@ -72,23 +76,40 @@ public class FunctionFile implements Updatable {
EvaluationSource es = new FileEvaluationSource(file.getPath(), null);
FileReader fr = null;
HashMap priorProps = new HashMap ();
ObjectPrototype op = null;
HashMap priorProps = null;
HashSet newProps = null;
try {
op = reval.getPrototype (prototype.getName());
// remember properties before evaluation, so we can tell what's new afterwards
if (functionNames == null) try {
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
String prop = (String) en.nextElement ();
priorProps.put (prop, op.getProperty (prop, prop.hashCode()));
}
} catch (Exception ignore) {}
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
try {
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
String prop = (String) en.nextElement ();
priorProps.put (prop, op.getProperty (prop, prop.hashCode()));
}
} catch (Exception ignore) {}
}
// do the update, evaluating the file
fr = new FileReader(file);
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) {
app.logEvent ("Error parsing function file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+e);
} catch (EcmaScriptException e) {
@ -100,44 +121,64 @@ public class FunctionFile implements Updatable {
} catch (IOException ignore) {}
}
// check
if (functionNames == null && op != null) try {
functionNames = 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))
functionNames.add (prop);
// now remove the props that were not refreshed, and set declared props to new collection
if (declaredPropsTimestamp != lastmod) {
declaredPropsTimestamp = lastmod;
if (declaredProps != null) {
declaredProps.removeAll (newProps);
removeProperties (declaredProps);
}
} catch (Exception ignore) {}
}
declaredProps = newProps;
// System.err.println ("DECLAREDPROPS = "+declaredProps);
}
}
}
void remove () {
prototype.functions.remove (name);
prototype.updatables.remove (file.getName());
// if we did not add anything to any evaluator, we're done
if (functionNames == null)
if (declaredProps == null || declaredProps.size() == 0)
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 ();
while (evals.hasNext ()) {
try {
RequestEvaluator reval = (RequestEvaluator) evals.next ();
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 ();
ESValue esv = op.getProperty (fname, fname.hashCode());
if (esv instanceof ConstructedFunctionObject) {
op.deleteProperty (fname, fname.hashCode());
}
// check if this property has been declared by some other function file in the meantime
if (otherFiles.contains (fname))
continue;
op.deleteProperty (fname, fname.hashCode());
// System.err.println ("REMOVING PROP: "+fname);
}
} catch (Exception ignore) {}
}
}
}

View file

@ -37,6 +37,14 @@ public class TypeManager implements Runnable {
// } 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) {
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) {
// there have been changes @ DbMappings
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.
// (10 secs are reached after 30 minutes of idle state)
// the above is all false.
long sleeptime = 1500 + Math.min (idleSeconds*30, 3500);
long sleeptime = 1000 + Math.min (idleSeconds*30, 4000);
typechecker.sleep (sleeptime);
} catch (InterruptedException x) {
// app.logEvent ("Typechecker interrupted");