From fdf3915d9ec17e65da8db20c81c763c6ad890e98 Mon Sep 17 00:00:00 2001 From: hns Date: Fri, 25 Mar 2005 00:12:59 +0000 Subject: [PATCH] Move TypeManager.updatePrototype(Prototype) to Prototype.checkForUpdates(). Additionally, the inner workings of the Prototype update logic were vastly simplified. --- src/helma/framework/core/Application.java | 4 +- src/helma/framework/core/Prototype.java | 124 ++++++++++++++-------- src/helma/framework/core/TypeManager.java | 121 ++------------------- src/helma/scripting/rhino/RhinoCore.java | 6 +- 4 files changed, 95 insertions(+), 160 deletions(-) diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index 9acff1d3..8de33ae6 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -1743,7 +1743,9 @@ public final class Application implements IPathElement, Runnable { * change, too. */ public long getChecksum() { - return starttime + typemgr.lastCodeUpdate() + props.getChecksum(); + return starttime + + typemgr.getLastCodeUpdate() + + props.getChecksum(); } /** diff --git a/src/helma/framework/core/Prototype.java b/src/helma/framework/core/Prototype.java index 46cd2bde..dd75753f 100644 --- a/src/helma/framework/core/Prototype.java +++ b/src/helma/framework/core/Prototype.java @@ -33,19 +33,21 @@ import java.util.*; * relational database table. */ public final class Prototype { + // the app this prototype belongs to Application app; + // this prototype's name in natural and lower case String name; String lowerCaseName; + // this prototype's resources Resource[] resources; - long lastResourceListing; - // lastCheck is the time the prototype's files were last checked - long lastChecksum; - long newChecksum; - // lastUpdate is the time at which any of the prototype's files were found updated the last time - long lastCodeUpdate; + // tells us the checksum of the repositories at the time we last updated them + long lastChecksum = 0; + + // the time at which any of the prototype's files were found updated the last time + long lastCodeUpdate = 0; TreeSet code; TreeSet skins; @@ -103,7 +105,6 @@ public final class Prototype { skinMap = new HashMap(); isJavaPrototype = app.isJavaPrototype(name); - lastCodeUpdate = lastChecksum = 0; } /** @@ -125,13 +126,73 @@ public final class Prototype { } /** - * Returns the list of resources in this prototype's repositories + * Check a prototype for new or updated resources. After this has been + * called the code and skins collections of this prototype should be + * up-to-date and the lastCodeUpdate be set if there has been any changes. */ - public Resource[] getResources() { - long resourceListing = getChecksum(); + public void checkForUpdates() { - if (resources == null || resourceListing != lastResourceListing) { - lastResourceListing = resourceListing; + boolean updatedResources = false; + + // check if any resource the prototype knows about has changed or gone + for (Iterator i = trackers.values().iterator(); i.hasNext();) { + ResourceTracker tracker = (ResourceTracker) i.next(); + + try { + if (tracker.hasChanged()) { + updatedResources = true; + tracker.markClean(); + if (!tracker.getResource().exists()) { + i.remove(); + String name = tracker.getResource().getName(); + if (name.endsWith(TypeManager.skinExtension)) { + skins.remove(tracker.getResource()); + } else { + code.remove(tracker.getResource()); + } + } + } + } catch (IOException iox) { + iox.printStackTrace(); + } + } + + // next we check if resources have been created or removed + Resource[] resources = getResources(); + + for (int i = 0; i < resources.length; i++) { + String name = resources[i].getName(); + if (!trackers.containsKey(name)) { + if (name.endsWith(TypeManager.templateExtension) || + name.endsWith(TypeManager.scriptExtension) || + name.endsWith(TypeManager.actionExtension) || + name.endsWith(TypeManager.skinExtension)) { + + if (name.endsWith(TypeManager.skinExtension)) { + addSkinResource(resources[i]); + } else { + addCodeResource(resources[i]); + } + } + } + } + + if (updatedResources) { + // mark prototype as dirty and the code as updated + lastCodeUpdate = System.currentTimeMillis(); + app.typemgr.setLastCodeUpdate(lastCodeUpdate); + } + } + + + /** + * Returns the list of resources in this prototype's repositories. Used + * by checkForUpdates() to see whether there is anything new. + */ + Resource[] getResources() { + long checksum = getRepositoryChecksum(); + // reload resources if the repositories checksum has changed + if (checksum != lastChecksum) { ArrayList list = new ArrayList(); Iterator iterator = repositories.iterator(); @@ -144,15 +205,16 @@ public final class Prototype { } resources = (Resource[]) list.toArray(new Resource[list.size()]); + lastChecksum = checksum; } - return resources; } /** - * Get a checksum over this prototype's sources + * Get a checksum over this prototype's repositories. This tells us + * if any resources were added or removed. */ - public long getChecksum() { + long getRepositoryChecksum() { long checksum = 0; Iterator iterator = repositories.iterator(); @@ -164,20 +226,9 @@ public final class Prototype { } } - newChecksum = checksum; return checksum; } - /** - * - * - * @return ... - */ - public boolean isUpToDate() { - return (newChecksum == 0 && lastChecksum == 0) ? - false : newChecksum == lastChecksum; - } - /** * Set the parent prototype of this prototype, i.e. the prototype this * prototype inherits from. @@ -241,18 +292,14 @@ public final class Prototype { } /** - * - * - * @param dbmap ... + * Set the DbMapping associated with this prototype */ protected void setDbMapping(DbMapping dbmap) { this.dbmap = dbmap; } /** - * - * - * @return ... + * Get the DbMapping associated with this prototype */ public DbMapping getDbMapping() { return dbmap; @@ -316,15 +363,6 @@ public final class Prototype { lastCodeUpdate = System.currentTimeMillis(); } - /** - * Signal that the prototype's scripts have been checked for - * changes. - */ - public void markChecked() { - // lastCheck = System.currentTimeMillis (); - lastChecksum = newChecksum; - } - /** * Return a clone of this prototype's actions container. Synchronized * to not return a map in a transient state where it is just being @@ -483,10 +521,6 @@ public final class Prototype { } private void checkForUpdates() { - if (!isUpToDate()) { - app.typemgr.updatePrototype(Prototype.this); - } - if (lastCodeUpdate > lastSkinmapLoad) { load(); } diff --git a/src/helma/framework/core/TypeManager.java b/src/helma/framework/core/TypeManager.java index b1b3b8ce..bf9c16c9 100644 --- a/src/helma/framework/core/TypeManager.java +++ b/src/helma/framework/core/TypeManager.java @@ -19,7 +19,6 @@ package helma.framework.core; import helma.objectmodel.db.DbMapping; import helma.framework.repository.Resource; import helma.framework.repository.Repository; -import helma.framework.repository.ResourceTracker; import java.io.*; import java.net.URL; @@ -212,13 +211,20 @@ public final class TypeManager { } /** - * Return a checksum over all files in all prototypes in this application. - * The checksum can be used to find out quickly if any file has changed. + * Returns the last time any resource in this app was modified. + * This can be used to find out quickly if any file has changed. */ - public long lastCodeUpdate() { + public long getLastCodeUpdate() { return lastCodeUpdate; } + /** + * Set the last time any resource in this app was modified. + */ + public void setLastCodeUpdate(long update) { + lastCodeUpdate = update; + } + /** * Return the class loader used by this application. * @@ -264,111 +270,4 @@ public final class TypeManager { return proto; } - /** - * Check a prototype for new or updated resources. - */ - public void updatePrototype(Prototype proto) { - - synchronized (proto) { - // check again because another thread may have checked the - // prototype while we were waiting for access to the synchronized section - - boolean updatedResources = false; - List createdResources = null; - - // our plan is to do as little as possible, so first check if - // anything the prototype knows about has changed on disk - for (Iterator i = proto.trackers.values().iterator(); i.hasNext();) { - ResourceTracker tracker = (ResourceTracker) i.next(); - - try { - if (tracker.hasChanged()) { - updatedResources = true; - tracker.markClean(); - } - } catch (IOException iox) { - iox.printStackTrace(); - } - } - - // next we check if files have been created or removed since last update - Resource[] resources = proto.getResources(); - - for (int i = 0; i < resources.length; i++) { - String name = resources[i].getName(); - if (!proto.trackers.containsKey(name)) { - if (name.endsWith(templateExtension) || - name.endsWith(scriptExtension) || - name.endsWith(actionExtension) || - name.endsWith(skinExtension)) { - if (createdResources == null) { - createdResources = new ArrayList(); - } - - createdResources.add(resources[i]); - } - } - } - - // if nothing needs to be updated, mark prototype as checked and return - if (!updatedResources && createdResources == null) { - proto.markChecked(); - - return; - } - - // first go through new files and create new items - if (createdResources != null) { - Resource[] newResources = new Resource[createdResources.size()]; - createdResources.toArray(newResources); - - for (int i = 0; i < newResources.length; i++) { - String resourceName = newResources[i].getName(); - if (resourceName.endsWith(templateExtension) || - resourceName.endsWith(scriptExtension) || - resourceName.endsWith(actionExtension)) { - try { - proto.addCodeResource(newResources[i]); - } catch (Throwable x) { - app.logEvent("Error updating prototype: " + x); - } - } else if (resourceName.endsWith(skinExtension)) { - try { - proto.addSkinResource(newResources[i]); - } catch (Throwable x) { - app.logEvent("Error updating prototype: " + x); - } - } - } - } - - // next go through existing updatables - if (updatedResources) { - /* - for (Iterator i = updateSet.iterator(); i.hasNext();) { - Updatable upd = (Updatable) i.next(); - - try { - upd.update(); - } catch (Exception x) { - if (upd instanceof DbMapping) { - app.logEvent("Error updating db mapping for type " + - proto.getName() + ": " + x); - } else { - app.logEvent("Error updating " + upd + " of prototye type " + - proto.getName() + ": " + x); - } - } - } - */ - } - - // mark prototype as checked and updated. - proto.markChecked(); - proto.markUpdated(); - lastCodeUpdate = proto.lastCodeUpdate(); - - } // end of synchronized (proto) - } - } diff --git a/src/helma/scripting/rhino/RhinoCore.java b/src/helma/scripting/rhino/RhinoCore.java index 392ba961..be3c4089 100644 --- a/src/helma/scripting/rhino/RhinoCore.java +++ b/src/helma/scripting/rhino/RhinoCore.java @@ -376,8 +376,8 @@ public final class RhinoCore implements ScopeProvider { updatePrototype(type.getParentType(), checked); } - // let the type manager scan the prototype's directory - app.typemgr.updatePrototype(type.frameworkProto); + // let the prototype check if its resources have changed + type.frameworkProto.checkForUpdates(); // and re-evaluate if necessary if (type.needsUpdate()) { @@ -428,7 +428,7 @@ public final class RhinoCore implements ScopeProvider { // otherwise, it has already been evaluated for this request by updatePrototypes(), // which is called before a request is handled. if ((type != null) && (type.lastUpdate == -1)) { - app.typemgr.updatePrototype(type.frameworkProto); + type.frameworkProto.checkForUpdates(); if (type.needsUpdate()) { evaluatePrototype(type);