Return-Path: Mailing-List: contact tomcat-dev-help@jakarta.apache.org; run by ezmlm Delivered-To: mailing list tomcat-dev@jakarta.apache.org Received: (qmail 95248 invoked by uid 500); 2 Dec 2000 08:27:08 -0000 Delivered-To: apmail-jakarta-tomcat-cvs@apache.org Received: (qmail 95181 invoked by uid 1052); 2 Dec 2000 08:27:07 -0000 Date: 2 Dec 2000 08:27:07 -0000 Message-ID: <20001202082707.95170.qmail@locus.apache.org> From: costin@locus.apache.org To: jakarta-tomcat-cvs@apache.org Subject: cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util/http Parameters.java costin 00/12/02 00:27:05 Modified: src/share/org/apache/tomcat/core BaseInterceptor.java ContextManager.java src/share/org/apache/tomcat/request ReloadInterceptor.java src/share/org/apache/tomcat/util/collections MultiMap.java src/share/org/apache/tomcat/util/depend DependManager.java src/share/org/apache/tomcat/util/http Parameters.java Log: - Fixed the documentation of ContextManager ( or started to ), fixed the shutdown. Thanks Larry, I think now is better. I'll continue to fix the code to match the documentation. - fixed the compilation for jdk1.1.7 ( the compiler is buggy ) - make sure the "JVM is broken" is displayed only once, no need to see it for every request. Revision Changes Path 1.26 +5 -0 jakarta-tomcat/src/share/org/apache/tomcat/core/BaseInterceptor.java Index: BaseInterceptor.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/BaseInterceptor.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- BaseInterceptor.java 2000/11/02 21:24:42 1.25 +++ BaseInterceptor.java 2000/12/02 08:26:45 1.26 @@ -247,6 +247,9 @@ * * WebXmlReader needs to be the first interceptor in * the contextInit chain. + * + * @exception If the interceptor throws exception the context will + * not be initialized ( state==NEW or ADDED or DISABLED ). */ public void contextInit(Context ctx) throws TomcatException @@ -307,6 +310,8 @@ } /** Called when the ContextManger is started + * @exception TomcatException The server will not start if any exception is thrown by + * engineInit */ public void engineInit(ContextManager cm) throws TomcatException 1.153 +151 -94 jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java Index: ContextManager.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java,v retrieving revision 1.152 retrieving revision 1.153 diff -u -r1.152 -r1.153 --- ContextManager.java 2000/12/01 17:42:51 1.152 +++ ContextManager.java 2000/12/02 08:26:47 1.153 @@ -90,76 +90,91 @@ One application may try to embed multiple ( distinct ) servlet containers - this feature hasn't been tested or used - - Expected startup order: +

Startup

- 1. Create ContextManager + 1. Create ContextManager. - 2. Set settable properties for ContextManager ( home, debug, etc) + 2. Set properties for ContextManager ( home, debug, etc). - 3. Add global Interceptors + 3. Add global Interceptors. 4. You may create, set and add Contexts. NO HOOKS ARE CALLED. + This adds a lot of complexity to the code - but allow + the server to have an initial set of contexts when it starts. + More contexts can be added after startup. - 5. Call init(). At this stage engineInit() callback will be - called for all global interceptors. - - DefaultCMSetter ( or a replacement ) must be the first in - the chain and will adjust the paths and set defaults for - all unset properties. - - AutoSetup and other interceptors can automatically add/set - more properties and make other calls. + 5. init() At this stage engineInit() callback will be + called for all global interceptors. - During engineInit() a number of Contexts are created and + During engineInit() a number of Contexts can be created and added to the server. No addContext() callback is called until - the last engineInit() returns. ( XXX do we need this restriction ?) + the last engineInit() returns. Interceptors can also change the + state of the server ( change properites, add other interceptors, + etc) - XXX I'n not sure about contextInit and about anything below. + After this call the server will be in INITIALIZED state. + No callback other than engineInit can be called before the server + enters this state. - x. Server will move to INITIALIZED state. No callback other than engineInit - can be called before the server enters this state. + 6. init() will also call the addContext() hook for all contexts + that were added during engineInit or before init() was called. + More contexts can be added after init() and before start(). - x. addContext() callbacks will be called for each context. - After init you may add more contexts, and addContext() callback - will be called (since the server is initialized ) + InitContext will have no effect before the server is started - + all initContexts for added contexts will be called automatically + at start. - x. Call start(). + 7. start(). All contexts will be initialized ( contextInit() + callback ). ContextInit will move the context to READY state, + allowing it to serve requests. - x. All contexts will be initialized ( contextInit() - callback ). + Server will move to START state after all configured contexts + are READY. No servlet should be served before the container is + in START state ( tomcat should return "Server not ready") . - x. Server will move to STARTED state. No servlet should be - served before this state. +

Normal operation

- - During normal operation, it is possible to add Contexts. + 1. Requests for a context in READY state will be served by that context. + Requests for a context that is not READY will return an error ( + "application temp. unavailable" - no 404 on the parent context !) - 1. Create the Context, set properties ( that can be done from servlets - or by interceptors like ~user) + 2. At any time you can create a new Context, set properties ( that can + be done from servlets or by interceptors like ~user). The context is + not visible to tomcat until addContext completes. - 2. call CM.addContext(). This will triger the addContext() callback. - ( if CM is initialized ) + 3. addContext(). This will triger the addContext() callback. - 3. call CM.initContext( ctx ). This will triger contextInit() callback. - After that the context is initialized and can serve requests. - No request belonging to this context can't be served before this - method returns. + 4. initContext(). This will triger contextInit() callbacks/ + After that the context is READY and can serve requests. - XXX Context state - - It is also possible to remove Contexts. + 5. You can find a Context by enumerating all added contexts. - 1. Find the Context ( enumerate all existing contexts and find the one - you need - host and path are most likely keys ). + 6. contextShutdown(). The context will no longer be READY and can't + serve requests ( Application unavailable ). contextShutdown hooks + are called - 2. Call removeContext(). This will call removeContext() callbacks. + 7. removeContext(). This will call removeContext() hooks. After this + method the context will no longer be visible to tomcat and will + be removed from the list of known contexts. Requests for this + context will be served by the parent context ( or root ) - - To stop the server, you need to: +

Stopping the server

+ + 1. stop(). The server will exit the START state and enter STOP,any request + will get a "Server unavailable" error. All contextShutdown() and + will be called. ( STOP==INIT ? ) - 1. Call shutdown(). + 2. shutdown(). All removeContext() callbacks will be called and the server + will enter PRE_INIT state. The contexts will not be removed from + the server - it is possible to call init again ( server restart ? ) - 2. The server will ... + Notes: + DefaultCMSetter ( or a replacement ) must be the first in + the chain and will adjust the paths and set defaults for + all unset properties. + AutoSetup and other interceptors can automatically add/set + more properties and make other calls. @author James Duncan Davidson [duncan@eng.sun.com] @author James Todd [gonzo@eng.sun.com] @@ -385,39 +400,35 @@ */ public final void init() throws TomcatException { if(debug>0 ) log( "Tomcat init"); - + if( state!= STATE_PRE_INIT ) + throw new TomcatException("Invalid state in init " + state ); + BaseInterceptor cI[]=defaultContainer.getInterceptors(); for( int i=0; i< cI.length; i++ ) { cI[i].setContextManager( this ); + // If an exception is thrown, the server will not + // move to INIT state. cI[i].engineInit( this ); } state=STATE_INIT; - // delayed execution of addContext + // delayed execution of addContext. + // If any context is added before init, its initialization + // will be delayed until INIT Enumeration existingCtxE=contextsV.elements(); while( existingCtxE.hasMoreElements() ) { Context ctx=(Context)existingCtxE.nextElement(); - cI=ctx.getContainer().getInterceptors(); - for( int i=0; i< cI.length; i++ ) { - cI[i].addContext( this, ctx ); + try { + cI=ctx.getContainer().getInterceptors(); + for( int i=0; i< cI.length; i++ ) { + cI[i].addContext( this, ctx ); + } + ctx.setState( Context.STATE_ADDED ); + } catch( TomcatException ex ) { + log( "Context not added " + ctx , ex ); + continue; } - ctx.setState( Context.STATE_ADDED ); - } - } - - /** Remove all contexts. - * - call removeContext ( that will call Interceptor.removeContext hooks ) - * - call Interceptor.engineShutdown() hooks. - */ - public final void shutdown() throws TomcatException { - while (!contextsV.isEmpty()) { - removeContext((Context)contextsV.firstElement()); - } - - BaseInterceptor cI[]=defaultContainer.getInterceptors(); - for( int i=0; i< cI.length; i++ ) { - cI[i].engineShutdown( this ); } } @@ -425,17 +436,24 @@ * It must be called after init. */ public final void start() throws TomcatException { - + if( state!=STATE_INIT ) + throw new TomcatException( "Invalid state in start(), " + + " you need to call init() "+ state); + Enumeration enum = getContexts(); while (enum.hasMoreElements()) { Context ctx = (Context)enum.nextElement(); - BaseInterceptor cI[]=ctx.getContainer().getInterceptors(); - for( int i=0; i< cI.length; i++ ) { - cI[i].contextInit( ctx ); + try { + initContext( ctx ); + } catch( TomcatException ex ) { + // just log the error, the context will not serve + // requests but we go on + log( "Error initializing " + ctx , ex ); + continue; } - ctx.setState( Context.STATE_READY ); } - + + // requests can be processed now state=STATE_START; } @@ -445,6 +463,21 @@ shutdown(); } + /** Remove all contexts. + * - call removeContext ( that will call Interceptor.removeContext hooks ) + * - call Interceptor.engineShutdown() hooks. + */ + public final void shutdown() throws TomcatException { + while (!contextsV.isEmpty()) { + removeContext((Context)contextsV.firstElement()); + } + + BaseInterceptor cI[]=defaultContainer.getInterceptors(); + for( int i=0; i< cI.length; i++ ) { + cI[i].engineShutdown( this ); + } + } + // -------------------- Contexts -------------------- /** Return the list of contexts managed by this server @@ -465,22 +498,31 @@ * @param ctx context to be added. */ public final void addContext( Context ctx ) throws TomcatException { - log("Adding context " + ctx.toString()); - // Make sure context knows about its manager. ctx.setContextManager( this ); ctx.setState( Context.STATE_NEW ); - + + // Add it to the contextV, when init all contexts will be added contextsV.addElement( ctx ); - if( state == STATE_PRE_INIT ) - return; + if( state == STATE_PRE_INIT ) { + log( "Delay context add " + ctx.toString()); + return; + } - BaseInterceptor cI[]=ctx.getContainer().getInterceptors(); - for( int i=0; i< cI.length; i++ ) { - cI[i].addContext( this, ctx ); + try { + BaseInterceptor cI[]=ctx.getContainer().getInterceptors(); + for( int i=0; i< cI.length; i++ ) { + // If an exception is thrown, context will remain in + // NEW state. + cI[i].addContext( this, ctx ); + } + ctx.setState( Context.STATE_ADDED ); + log("Adding context " + ctx.toString()); + } catch (TomcatException ex ) { + log( "Context not added " + ctx , ex ); + throw ex; } - ctx.setState( Context.STATE_ADDED ); } /** Shut down and removes a context from service. @@ -489,24 +531,29 @@ if( context==null ) return; log( "Removing context " + context.toString()); - - // disable the context. - if( context.getState() == Context.STATE_READY ) - shutdownContext( context ); contextsV.removeElement(context); - if( context.getState() == Context.STATE_DISABLED ) + // if it's already disabled - or was never activated, + // no need to shutdown and remove + if( context.getState() == Context.STATE_NEW ) return; - context.setState( Context.STATE_NEW ); + // disable the context - it it is running + // ( it is possible to explicitely shut it down before + // calling removeContext ) + if( context.getState() == Context.STATE_READY ) + shutdownContext( context ); - // remove it from operation + // remove it from operation - notify interceptors that + // this context is no longer active BaseInterceptor cI[]=context.getContainer().getInterceptors(); for( int i=0; i< cI.length; i++ ) { cI[i].removeContext( this, context ); } + // mark the context as "not active" + context.setState( Context.STATE_NEW ); } @@ -522,14 +569,21 @@ * * After this call, the context will be in READY state and will * be able to server requests. + * + * @exception if any interceptor throws an exception the error + * will prevent the context from becoming READY */ public final void initContext( Context ctx ) throws TomcatException { - if( state!= STATE_PRE_INIT ) { - BaseInterceptor cI[]=ctx.getContainer().getInterceptors(); - for( int i=0; i< cI.length; i++ ) { - cI[i].contextInit( ctx ); - } + // no action if ContextManager is not initialized + if( state == STATE_PRE_INIT ) + throw new TomcatException("Invalid state"); + + BaseInterceptor cI[]=ctx.getContainer().getInterceptors(); + for( int i=0; i< cI.length; i++ ) { + cI[i].contextInit( ctx ); } + + // Only if all init methods succeed an no ex is thrown ctx.setState( Context.STATE_READY ); } @@ -542,10 +596,13 @@ All servlets will be destroyed, and resources held by the context will be freed. + + The contextShutdown callbacks can wait until the running serlvets + are completed - there is no way to force the shutdown. */ public final void shutdownContext( Context ctx ) throws TomcatException { ctx.setState( Context.STATE_DISABLED ); // called before - // the hook, no request should be allowed in unstable state + // the hook, no more request should be allowed in unstable state BaseInterceptor cI[]=ctx.getContainer().getInterceptors(); for( int i=0; i< cI.length; i++ ) { 1.9 +3 -0 jakarta-tomcat/src/share/org/apache/tomcat/request/ReloadInterceptor.java Index: ReloadInterceptor.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/ReloadInterceptor.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- ReloadInterceptor.java 2000/11/02 21:44:50 1.8 +++ ReloadInterceptor.java 2000/12/02 08:26:49 1.9 @@ -125,6 +125,9 @@ if( ! ctx.shouldReload() ) return 0; + if( debug> 0 ) + log( "Detected changes in " + ctx.toString()); + try { // Reload context. ContextManager cm=ctx.getContextManager(); 1.2 +8 -6 jakarta-tomcat/src/share/org/apache/tomcat/util/collections/MultiMap.java Index: MultiMap.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/collections/MultiMap.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- MultiMap.java 2000/11/30 17:34:16 1.1 +++ MultiMap.java 2000/12/02 08:26:53 1.2 @@ -232,7 +232,7 @@ public int findNext( int startPos ) { int next= fields[startPos].nextPos; - if( next != Field.NEED_NEXT ) { + if( next != MultiMap.NEED_NEXT ) { return next; } @@ -245,10 +245,14 @@ return i; } } - fields[startPos].nextPos= Field.LAST; + fields[startPos].nextPos= MultiMap.LAST; return -1; } + // workaround for JDK1.1.8/solaris + static final int NEED_NEXT=-2; + static final int LAST=-1; + // -------------------- Internal representation -------------------- final class Field { MessageBytes name; @@ -258,8 +262,6 @@ // multiple fields with same name - a linked list will // speed up multiple name enumerations and search. - static final int NEED_NEXT=-2; - static final int LAST=-1; int nextPos; // hashkey @@ -267,13 +269,13 @@ Field nextSameHash; Field() { - nextPos=NEED_NEXT; + nextPos=MultiMap.NEED_NEXT; } void recycle() { name.recycle(); value.recycle(); - nextPos=NEED_NEXT; + nextPos=MultiMap.NEED_NEXT; } } } 1.3 +5 -2 jakarta-tomcat/src/share/org/apache/tomcat/util/depend/DependManager.java Index: DependManager.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/depend/DependManager.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- DependManager.java 2000/12/01 23:15:22 1.2 +++ DependManager.java 2000/12/02 08:26:58 1.3 @@ -101,11 +101,14 @@ return checkCount; } + private static boolean noWarnBadVM=true; public boolean shouldReload() { boolean b=shouldReload1(); - if( b!=expired) + if( b!=expired && noWarnBadVM ) { log("BUG ( VM or Tomcat? ) shouldReload returns expired=" + b + " and the real value is " + expired); + noWarnBadVM=false; + } return expired; } @@ -173,7 +176,7 @@ // -------------------- Private - private static final int debug=10; + private static final int debug=0; void log( String s ) { System.out.println("DependManager: " + s ); 1.2 +15 -1 jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java Index: Parameters.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Parameters.java 2000/11/30 17:42:49 1.1 +++ Parameters.java 2000/12/02 08:27:03 1.2 @@ -87,7 +87,21 @@ isSet=false; isFormBased=false; } - + // XXX need better name + public boolean isEvaluated() { + return isSet; + } + public void setEvaluated( boolean b ) { + isSet=b; + } + // XXX need better name + public boolean hasFormData() { + return isFormBased; + } + public void setFormData(boolean b ) { + isFormBased=b; + } + // duplicated public static int indexOf( byte bytes[], int off, int end, char qq ) {