costin 01/06/07 20:08:26
Modified: src/share/org/apache/tomcat/modules/mappers
SimpleMapper1.java
Log:
Added PrefixMapper as an internal class, it is very specific to
SimpleMapper ( and not used in other modules ). It is also ugly and
quite slow, so we'll need a new mapper ( now that many things are tuned
we can see smaller spots ). In any case PrefixMapper doesn't deserve to
be in tomcat_util.jar.
Revision Changes Path
1.4 +180 -1
jakarta-tomcat/src/share/org/apache/tomcat/modules/mappers/SimpleMapper1.java
Index: SimpleMapper1.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/mappers/SimpleMapper1.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SimpleMapper1.java 2001/05/26 17:54:50 1.3
+++ SimpleMapper1.java 2001/06/08 03:08:23 1.4
@@ -62,7 +62,7 @@
import org.apache.tomcat.core.*;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.io.FileUtil;
-import org.apache.tomcat.util.PrefixMapper;
+//import org.apache.tomcat.util.PrefixMapper;
import org.apache.tomcat.util.collections.*;
import java.util.*;
@@ -425,3 +425,182 @@
}
+
+/** Prefix and exact mapping alghoritm.
+ *XXX finish factoring out the creation of the map ( right now direct field access
is
+ * used, since the code was just cut out from SimpleMapper).
+ * XXX make sure the code is useable as a general path mapper - or at least a
bridge
+ * can be created between SimpleMapper and a patern matcher like the one in XPath
+ *
+ * @author [EMAIL PROTECTED]
+ */
+class PrefixMapper {
+ // host -> PrefixMapper for virtual hosts
+ // hosts are stored in lower case ( the "common" case )
+ SimpleHashtable vhostMaps=new SimpleHashtable();
+
+
+ SimpleHashtable prefixMappedServlets;
+ SimpleHashtable exactMappedServlets;
+
+ // Cache the most recent mappings
+ // Disabled by default ( since we haven't implemented
+ // capacity and remove ).
+ SimpleHashtable mapCache;
+ // By using TreeMap instead of SimpleMap you go from 143 to 161 RPS
+ // ( at least on my machine )
+ // Interesting - even if SimpleHashtable is faster than Hashtable
+ // most of the time, the average is very close for both - it seems
+ // that while the synchronization in Hashtable is locking, GC have
+ // a chance to work, while in SimpleHashtable case GC creates big
+ // peeks. That will go away with more reuse, so we should use SH.
+
+ // An alternative to explore after everything works is to use specialized
+ // mappers ( extending this one for example ) using 1.2 collections
+ // TreeMap mapCache;
+ boolean mapCacheEnabled=false;
+
+
+ public PrefixMapper() {
+ prefixMappedServlets=new SimpleHashtable();
+ exactMappedServlets=new SimpleHashtable();
+ mapCache=new SimpleHashtable();
+ }
+
+ public void setMapCache( boolean v ) {
+ mapCacheEnabled=v;
+ }
+
+ /** Remove all mappings matching path
+ */
+ public void removeAllMappings( String host, String path ) {
+ PrefixMapper vmap=this;
+ if( host!=null ) {
+ host=host.toLowerCase();
+ vmap=(PrefixMapper)vhostMaps.get(host);
+ }
+
+ // remove all paths starting with path
+ Enumeration en=vmap.prefixMappedServlets.keys();
+ while( en.hasMoreElements() ) {
+ String s=(String)en.nextElement();
+ if( s.startsWith( path ))
+ vmap.prefixMappedServlets.remove( s );
+ }
+
+ en=vmap.exactMappedServlets.keys();
+ while( en.hasMoreElements() ) {
+ String s=(String)en.nextElement();
+ if( s.startsWith( path ))
+ vmap.exactMappedServlets.remove( s );
+ }
+ // reset the cache
+ mapCache=new SimpleHashtable();
+
+ }
+
+ /**
+ */
+ void addMapping( String path, Object target ) {
+ prefixMappedServlets.put( path, target);
+ }
+
+ /**
+ */
+ void addExactMapping( String path, Object target ) {
+ exactMappedServlets.put( path, target);
+ }
+
+ /**
+ */
+ public void addMapping( String host, String path, Object target ) {
+ if( host == null )
+ prefixMappedServlets.put( path, target);
+ else {
+ host=host.toLowerCase();
+ PrefixMapper vmap=(PrefixMapper)vhostMaps.get( host );
+ if( vmap == null ) {
+ vmap=new PrefixMapper();
+ vhostMaps.put( host, vmap );
+ vmap.setMapCache( mapCacheEnabled );
+ }
+ vmap.addMapping( path, target );
+ }
+ }
+
+ /**
+ */
+ public void addExactMapping( String host, String path, Object target ) {
+ if( host==null )
+ exactMappedServlets.put( path, target);
+ else {
+ host=host.toLowerCase();
+ PrefixMapper vmap=(PrefixMapper)vhostMaps.get( host );
+ if( vmap == null ) {
+ vmap=new PrefixMapper();
+ vhostMaps.put( host, vmap );
+ }
+ vmap.addExactMapping( path, target );
+ }
+ }
+
+
+ // -------------------- Implementation --------------------
+
+ /** Match a prefix rule - /foo/bar/index.html/abc
+ */
+ public Object getLongestPrefixMatch( MessageBytes hostMB,
+ MessageBytes pathMB )
+ {
+ // XXX fixme
+ String host=hostMB.toString();
+ String path=pathMB.toString();
+ Object container = null;
+ String s = path;
+
+ PrefixMapper myMap=null;
+ if( host!=null ) {
+ myMap=(PrefixMapper)vhostMaps.get( host );
+ if( myMap==null ) {
+ myMap=(PrefixMapper)vhostMaps.get( host.toLowerCase() );
+ }
+ }
+
+ if( myMap==null ) myMap = this; // default server
+
+
+ container=myMap.exactMappedServlets.get( path );
+ if( container != null ) return container; // and we're done!
+
+ /** Cache for request results - exploit the fact that few
+ * request are more "popular" than other.
+ * Disable it if you want to benchmark the mapper !!!
+ */
+ if( myMap.mapCacheEnabled ) {
+ container=myMap.mapCache.get(path);
+ if( container!=null ) return container;
+ }
+
+ while (s.length() >= 0) {
+ //if(debug>8) context.log( "Prefix: " + s );
+ container = myMap.prefixMappedServlets.get(s);
+
+ if (container == null) {
+ // if empty string didn't map, time to give up
+ if ( s.length() == 0 )
+ break;
+ s=FileUtil.removeLast( s );
+ } else {
+ if( myMap.mapCacheEnabled ) {
+ // XXX implement LRU or another replacement alghoritm
+ myMap.mapCache.put( path, container );
+ }
+ return container;
+ }
+ }
+ return container;
+ }
+
+}
+
+