Get serious about skin caching

This commit is contained in:
hns 2001-08-23 14:02:56 +00:00
parent c2605e72b6
commit 6a1aaaea58
2 changed files with 56 additions and 24 deletions

View file

@ -15,12 +15,7 @@ import helma.util.*;
import FESI.Data.*; import FESI.Data.*;
import FESI.Interpreter.*; import FESI.Interpreter.*;
import com.sleepycat.db.DbException; import com.sleepycat.db.DbException;
import java.util.Hashtable; import java.util.*;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Stack;
import java.util.EmptyStackException;
import java.util.StringTokenizer;
/** /**
* The central class of a HOP application. This class keeps a pool of so-called * The central class of a HOP application. This class keeps a pool of so-called
@ -85,6 +80,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
private CryptFile pwfile; private CryptFile pwfile;
CacheMap skincache = new CacheMap (100, 0.75f);
public Application () throws RemoteException { public Application () throws RemoteException {
super (); super ();

View file

@ -3,17 +3,14 @@
package helma.framework.core; package helma.framework.core;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.*; import helma.objectmodel.db.*;
import helma.framework.*; import helma.framework.*;
import helma.framework.extensions.*; import helma.framework.extensions.*;
import helma.xmlrpc.fesi.*; import helma.xmlrpc.fesi.*;
import helma.util.*; import helma.util.*;
import java.util.*;
import java.io.*;
import Acme.LruHashtable; import Acme.LruHashtable;
import FESI.Data.*; import FESI.Data.*;
import FESI.Interpreter.*; import FESI.Interpreter.*;
@ -49,6 +46,9 @@ public class RequestEvaluator implements Runnable {
protected ArrayPrototype reqPath; protected ArrayPrototype reqPath;
private ESRequestData reqData; private ESRequestData reqData;
// Used to cache skins within one request evaluation
HashMap skincache;
// vars for FESI EcmaScript support // vars for FESI EcmaScript support
protected Evaluator evaluator; protected Evaluator evaluator;
protected ObjectPrototype esNodePrototype; protected ObjectPrototype esNodePrototype;
@ -87,8 +87,9 @@ public class RequestEvaluator implements Runnable {
*/ */
public RequestEvaluator (Application app) { public RequestEvaluator (Application app) {
this.app = app; this.app = app;
this.objectcache = new LruHashtable (100, .80f); objectcache = new LruHashtable (100, .80f);
this.prototypes = new Hashtable (); prototypes = new Hashtable ();
skincache = new HashMap ();
initEvaluator (); initEvaluator ();
initialized = false; initialized = false;
// startThread (); // startThread ();
@ -144,6 +145,7 @@ public class RequestEvaluator implements Runnable {
IPathElement root, currentElement; IPathElement root, currentElement;
// reset skinManager // reset skinManager
skinmanagers = null; skinmanagers = null;
skincache.clear ();
switch (reqtype) { switch (reqtype) {
case HTTP: case HTTP:
@ -748,19 +750,30 @@ public class RequestEvaluator implements Runnable {
public Skin getSkin (Prototype proto, String skinname) { public Skin getSkin (Prototype proto, String skinname) {
if (proto == null) if (proto == null)
return null; return null;
// First check if the skin has been already used within the execution of this request
CompositeKey key = new CompositeKey (proto.getName(), skinname);
Skin skin = (Skin) skincache.get (key);
if (skin != null) {
return skin;
}
// Skin skin = null;
if (skinmanagers == null) if (skinmanagers == null)
getSkinManagers (); getSkinManagers ();
do { do {
for (int i=0; i<skinmanagers.length; i++) { for (int i=0; i<skinmanagers.length; i++) {
Skin skin = getSkinFromNode (skinmanagers[i], proto.getName (), skinname); skin = getSkinFromNode (skinmanagers[i], proto.getName (), skinname);
if (skin != null) if (skin != null) {
skincache.put (key, skin);
return skin; return skin;
}
} }
// not found in node managers for this prototype. // not found in node managers for this prototype.
// the next step is to look if it is defined as skin file for this prototype // the next step is to look if it is defined as skin file for this prototype
Skin skin = proto.getSkin (skinname); skin = proto.getSkin (skinname);
if (skin != null) if (skin != null) {
skincache.put (key, skin);
return skin; return skin;
}
// still not found. See if there is a parent prototype which might define the skin // still not found. See if there is a parent prototype which might define the skin
proto = proto.getPrototype (); proto = proto.getPrototype ();
} while (proto != null); } while (proto != null);
@ -777,18 +790,20 @@ public class RequestEvaluator implements Runnable {
n = n.getNode (skinname, false); n = n.getNode (skinname, false);
if (n != null) { if (n != null) {
String skin = n.getString ("skin", false); String skin = n.getString ("skin", false);
if (skin != null) if (skin != null) {
return new Skin (skin, app); Skin s = (Skin) app.skincache.get (skin);
if (s == null) {
s = new Skin (skin, app);
app.skincache.put (skin, s);
}
return s;
}
} }
} }
// if this is not for the global prototype, also check hopobject
// NOT! inheritance is taken care of in the above getSkin method. // Inheritance is taken care of in the above getSkin method.
// the sequence is prototype.skin-from-db, prototype.skin-from-file, parent.from-db, parent.from-file etc. // the sequence is prototype.skin-from-db, prototype.skin-from-file, parent.from-db, parent.from-file etc.
// if (!"global".equalsIgnoreCase (prototype) && !"hopobject".equalsIgnoreCase (prototype)) {
// return getSkinFromNode (node, "hopobject", skinname);
// }
return null; return null;
} }
@ -917,6 +932,27 @@ public class RequestEvaluator implements Runnable {
prototypes.put (protoName, op); prototypes.put (protoName, op);
} }
final class CompositeKey {
final String first, second;
public CompositeKey (String first, String second) {
this.first = first;
this.second = second;
}
public boolean equals (Object other) {
try {
CompositeKey key = (CompositeKey) other;
return first.equals (key.first) && second.equals (key.second);
} catch (Exception x) {
return false;
}
}
public int hashCode () {
return first.hashCode () + second.hashCode ();
}
}
} }