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; | ||||
|     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()); | ||||
| 
 | ||||
|             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 | ||||
|             if (functionNames == null) try { | ||||
|                 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) { | ||||
| 	            // 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) {} | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue