more work to solve "shringking prototypes" problem
in FunctionFile
This commit is contained in:
parent
20e8bb8987
commit
27d07e599c
2 changed files with 85 additions and 29 deletions
|
@ -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) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Add table
Reference in a new issue