The list of files belonging to a prototype is now managed by the prototype itself.

The prototype also keeps a checksum over its files which allows it to recognize
changes in any of the files quickly and easily.
This commit is contained in:
hns 2002-10-29 17:27:19 +00:00
parent 24dece80bb
commit f4002ac605
2 changed files with 85 additions and 35 deletions

View file

@ -24,6 +24,11 @@ public final class Prototype {
String name;
Application app;
File directory;
File [] files;
long lastDirectoryListing;
long checksum;
HashMap code, zippedCode;
HashMap skins, zippedSkins;
@ -36,7 +41,7 @@ public final class Prototype {
DbMapping dbmap;
// lastCheck is the time the prototype's files were last checked
private long lastCheck;
private long lastChecksum;
// lastUpdate is the time at which any of the prototype's files were
// found updated the last time
private long lastUpdate;
@ -47,10 +52,11 @@ public final class Prototype {
// as opposed to a Helma objectmodel node object.
boolean isJavaPrototype;
public Prototype (String name, Application app) {
public Prototype (String name, File dir, Application app) {
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
this.app = app;
this.name = name;
this.directory = dir;
code = new HashMap ();
zippedCode = new HashMap ();
@ -61,7 +67,7 @@ public final class Prototype {
skinMap = new SkinMap ();
isJavaPrototype = app.isJavaPrototype (name);
lastUpdate = lastCheck = 0;
lastUpdate = lastChecksum = 0;
}
/**
@ -71,6 +77,43 @@ public final class Prototype {
return app;
}
/**
* Return this prototype's directory.
*/
public File getDirectory () {
return directory;
}
/**
* Get the list of files in this prototype's directory
*/
public File[] getFiles () {
if (files == null || directory.lastModified() != lastDirectoryListing) {
lastDirectoryListing = directory.lastModified ();
files = directory.listFiles();
if (files == null)
files = new File[0];
}
return files;
}
/**
* Get a checksum over the files in this prototype's directory
*/
public long getChecksum () {
// long start = System.currentTimeMillis();
File[] f = getFiles ();
long c = 0;
for (int i=0; i<f.length; i++)
c += f[i].lastModified();
checksum = c;
// System.err.println ("CHECKSUM "+name+": "+(System.currentTimeMillis()-start));
return checksum;
}
public boolean isUpToDate () {
return checksum == lastChecksum;
}
/**
* Set the parent prototype of this prototype, i.e. the prototype this
@ -130,17 +173,6 @@ public final class Prototype {
return name;
}
/* Updatable[] upd = null;
public Updatable[] getUpdatables () {
if (upd == null) {
upd = new Updatable[updatables.size()];
int i = 0;
for (Iterator it = updatables.values().iterator(); it.hasNext(); ) {
upd[i++] = (Updatable) it.next();
}
}
return upd;
} */
/**
* Get the last time any script has been re-read for this prototype.
@ -162,18 +194,20 @@ public final class Prototype {
* Get the time at which this prototype's scripts were checked
* for changes for the last time.
*/
public long getLastCheck () {
/* public long getLastCheck () {
return lastCheck;
}
} */
/**
* Signal that the prototype's scripts have been checked for
* changes.
*/
public void markChecked () {
lastCheck = System.currentTimeMillis ();
// lastCheck = System.currentTimeMillis ();
lastChecksum = checksum;
}
/**
* Return a clone of this prototype's actions container. Synchronized
* to not return a map in a transient state where it is just being
@ -381,7 +415,7 @@ public final class Prototype {
private void checkForUpdates () {
if (lastCheck < System.currentTimeMillis()- 2000l)
if (/* lastCheck < System.currentTimeMillis()- 2000l*/ !isUpToDate())
app.typemgr.updatePrototype (Prototype.this);
if (lastUpdate > lastSkinmapLoad)
load ();

View file

@ -24,6 +24,8 @@ public final class TypeManager {
HashMap zipfiles;
long lastCheck = 0;
long appDirMod = 0;
// a checksum that changes whenever something in the application files changes.
long checksum;
// the hopobject prototype
Prototype hopobjectProto;
@ -123,12 +125,16 @@ public final class TypeManager {
}
}
// calculate this app's checksum by adding all checksums from all prototypes
long newChecksum = 0;
// loop through zip files to check for updates
for (Iterator it=zipfiles.values ().iterator (); it.hasNext (); ) {
ZippedAppFile zipped = (ZippedAppFile) it.next ();
if (zipped.needsUpdate ()) {
zipped.update ();
}
newChecksum += zipped.lastmod;
}
// loop through prototypes and check if type.properties needs updates
@ -136,6 +142,8 @@ public final class TypeManager {
// have been created in the previous loop.
for (Iterator i=prototypes.values().iterator(); i.hasNext(); ) {
Prototype proto = (Prototype) i.next ();
// calculate this app's type checksum
newChecksum += proto.getChecksum();
// update prototype's type mapping
DbMapping dbmap = proto.getDbMapping ();
if (dbmap != null && dbmap.needsUpdate ()) {
@ -150,7 +158,7 @@ public final class TypeManager {
}
}
}
checksum = newChecksum;
}
protected void removeZipFile (String zipname) {
@ -175,6 +183,14 @@ public final class TypeManager {
return true;
}
/**
* 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.
*/
public long getChecksum () {
return checksum;
}
/**
* Get a prototype defined for this application
*/
@ -184,7 +200,7 @@ public final class TypeManager {
/**
* Get a prototype, creating it if it doesn't already exist. Note
* that it doesn't create a DbMapping - this is left to the
* that it doesn't create a DbMapping - this is left to the
* caller (e.g. ZippedAppFile).
*/
public Prototype createPrototype (String typename) {
@ -196,7 +212,7 @@ public final class TypeManager {
* Create a prototype from a directory containing scripts and other stuff
*/
public Prototype createPrototype (String typename, File dir) {
Prototype proto = new Prototype (typename, app);
Prototype proto = new Prototype (typename, dir, app);
// Create and register type properties file
File propfile = new File (dir, "type.properties");
SystemProperties props = new SystemProperties (propfile.getAbsolutePath ());
@ -224,16 +240,16 @@ public final class TypeManager {
* Update a prototype to the files in the prototype directory.
*/
public void updatePrototype (Prototype proto) {
if (proto == null)
if (proto == null || proto.isUpToDate())
return;
synchronized (proto) {
// check again because another thread may have checked the
// prototype while we were waiting for access to the synchronized section
if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
return;
/* if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
return; */
File dir = new File (appDir, proto.getName());
File dir = proto.getDirectory ();
HashSet updateSet = null;
HashSet createSet = null;
@ -249,10 +265,10 @@ public final class TypeManager {
}
// next we check if files have been created or removed since last update
if (proto.getLastCheck() < dir.lastModified ()) {
String[] list = dir.list();
// if (proto.getLastCheck() < dir.lastModified ()) {
File[] list = proto.getFiles();
for (int i=0; i<list.length; i++) {
String fn = list[i];
String fn = list[i].getName();
if (!proto.updatables.containsKey (fn)) {
if (fn.endsWith (templateExtension) ||
fn.endsWith (scriptExtension) ||
@ -266,7 +282,7 @@ public final class TypeManager {
}
}
}
}
// }
// if nothing needs to be updated, mark prototype as checked and return
if (updateSet == null && createSet == null) {
@ -278,34 +294,34 @@ public final class TypeManager {
if (createSet != null) {
Object[] newFiles = createSet.toArray ();
for (int i=0; i<newFiles.length; i++) {
String filename = (String) newFiles[i];
File file = (File) newFiles[i];
String filename = file.getName ();
int dot = filename.lastIndexOf (".");
String tmpname = filename.substring(0, dot);
File tmpfile = new File (dir, filename);
if (filename.endsWith (templateExtension)) {
try {
Template t = new Template (tmpfile, tmpname, proto);
Template t = new Template (file, tmpname, proto);
proto.addTemplate (t);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (filename.endsWith (scriptExtension)) {
try {
FunctionFile ff = new FunctionFile (tmpfile, proto);
FunctionFile ff = new FunctionFile (file, proto);
proto.addFunctionFile (ff);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (filename.endsWith (actionExtension)) {
try {
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
ActionFile af = new ActionFile (file, tmpname, proto);
proto.addActionFile (af);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (filename.endsWith (skinExtension)) {
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
SkinFile sf = new SkinFile (file, tmpname, proto);
proto.addSkinFile (sf);
}
}