Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » cluster » tcp » [javadoc | source]
    1   /*
    2    * Copyright 1999,2004-2005 The Apache Software Foundation.
    3    * 
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    * 
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    * 
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.apache.catalina.cluster.tcp;
   18   
   19   import java.io.IOException;
   20   import java.util.StringTokenizer;
   21   import java.util.regex.Pattern;
   22   
   23   import javax.servlet.ServletException;
   24   
   25   import org.apache.catalina.Manager;
   26   import org.apache.catalina.Session;
   27   import org.apache.catalina.cluster.CatalinaCluster;
   28   import org.apache.catalina.cluster.ClusterManager;
   29   import org.apache.catalina.cluster.ClusterMessage;
   30   import org.apache.catalina.cluster.ClusterSession;
   31   import org.apache.catalina.cluster.ClusterValve;
   32   import org.apache.catalina.cluster.session.DeltaManager;
   33   import org.apache.catalina.connector.Request;
   34   import org.apache.catalina.connector.Response;
   35   import org.apache.catalina.util.StringManager;
   36   import org.apache.catalina.valves.ValveBase;
   37   
   38   /**
   39    * <p>Implementation of a Valve that logs interesting contents from the
   40    * specified Request (before processing) and the corresponding Response
   41    * (after processing).  It is especially useful in debugging problems
   42    * related to headers and cookies.</p>
   43    *
   44    * <p>This Valve may be attached to any Container, depending on the granularity
   45    * of the logging you wish to perform.</p>
   46    *
   47    * <p>primaryIndicator=true, then the request attribute <i>org.apache.catalina.cluster.tcp.isPrimarySession.</i>
   48    * is set true, when request processing is at sessions primary node.
   49    * </p>
   50    *
   51    * @author Craig R. McClanahan
   52    * @author Filip Hanik
   53    * @author Peter Rossbach
   54    * @version $Revision: 304032 $ $Date: 2005-07-27 11:11:55 -0400 (Wed, 27 Jul 2005) $
   55    */
   56   
   57   public class ReplicationValve
   58       extends ValveBase implements ClusterValve {
   59       
   60       private static org.apache.commons.logging.Log log =
   61           org.apache.commons.logging.LogFactory.getLog( ReplicationValve.class );
   62   
   63       // ----------------------------------------------------- Instance Variables
   64   
   65       /**
   66        * The descriptive information related to this implementation.
   67        */
   68       private static final String info =
   69           "org.apache.catalina.cluster.tcp.ReplicationValve/1.2";
   70   
   71   
   72       /**
   73        * The StringManager for this package.
   74        */
   75       protected static StringManager sm =
   76           StringManager.getManager(Constants.Package);
   77   
   78       private CatalinaCluster cluster = null ;
   79   
   80       /**
   81        * holds file endings to not call for like images and others
   82        */
   83       protected java.util.regex.Pattern[] reqFilters = new java.util.regex.Pattern[0];
   84       protected String filter ;
   85   
   86       protected long totalRequestTime=0;
   87       protected long totalSendTime=0;
   88       protected long nrOfRequests =0;
   89       protected long lastSendTime =0;
   90       protected long nrOfFilterRequests=0;
   91       protected boolean primaryIndicator = false ;
   92       protected String primaryIndicatorName = "org.apache.catalina.cluster.tcp.isPrimarySession";
   93      
   94       // ------------------------------------------------------------- Properties
   95   
   96       public ReplicationValve() {
   97       }
   98       /**
   99        * Return descriptive information about this Valve implementation.
  100        */
  101       public String getInfo() {
  102   
  103           return (info);
  104   
  105       }
  106       
  107       /**
  108        * @return Returns the cluster.
  109        */
  110       public CatalinaCluster getCluster() {
  111           return cluster;
  112       }
  113       
  114       /**
  115        * @param cluster The cluster to set.
  116        */
  117       public void setCluster(CatalinaCluster cluster) {
  118           this.cluster = cluster;
  119       }
  120    
  121       /**
  122        * @return Returns the filter
  123        */
  124       public String getFilter() {
  125          return filter ;
  126       }
  127   
  128       /**
  129        * compile filter string to regular expressions
  130        * @see Pattern#compile(java.lang.String)
  131        * @param filter
  132        *            The filter to set.
  133        */
  134       public void setFilter(String filter) {
  135           if (log.isDebugEnabled())
  136               log.debug(sm.getString("ReplicationValve.filter.loading", filter));
  137           this.filter = filter;
  138           StringTokenizer t = new StringTokenizer(filter, ";");
  139           this.reqFilters = new Pattern[t.countTokens()];
  140           int i = 0;
  141           while (t.hasMoreTokens()) {
  142               String s = t.nextToken();
  143               if (log.isTraceEnabled())
  144                   log.trace(sm.getString("ReplicationValve.filter.token", s));
  145               try {
  146                   reqFilters[i++] = Pattern.compile(s);
  147               } catch (Exception x) {
  148                   log.error(sm.getString("ReplicationValve.filter.token.failure",
  149                           s), x);
  150               }
  151           }
  152       }
  153   
  154       /**
  155        * @return Returns the primaryIndicator.
  156        */
  157       public boolean isPrimaryIndicator() {
  158           return primaryIndicator;
  159       }
  160       /**
  161        * @param primaryIndicator The primaryIndicator to set.
  162        */
  163       public void setPrimaryIndicator(boolean primaryIndicator) {
  164           this.primaryIndicator = primaryIndicator;
  165       }
  166       /**
  167        * @return Returns the primaryIndicatorName.
  168        */
  169       public String getPrimaryIndicatorName() {
  170           return primaryIndicatorName;
  171       }
  172       /**
  173        * @param primaryIndicatorName The primaryIndicatorName to set.
  174        */
  175       public void setPrimaryIndicatorName(String primaryIndicatorName) {
  176           this.primaryIndicatorName = primaryIndicatorName;
  177       }
  178         
  179       /**
  180        * @return Returns the lastSendTime.
  181        */
  182       public long getLastSendTime() {
  183           return lastSendTime;
  184       }
  185       
  186       /**
  187        * @return Returns the nrOfRequests.
  188        */
  189       public long getNrOfRequests() {
  190           return nrOfRequests;
  191       }
  192       
  193       /**
  194        * @return Returns the nrOfFilterRequests.
  195        */
  196       public long getNrOfFilterRequests() {
  197           return nrOfFilterRequests;
  198       }
  199   
  200       /**
  201        * @return Returns the totalRequestTime.
  202        */
  203       public long getTotalRequestTime() {
  204           return totalRequestTime;
  205       }
  206       
  207       /**
  208        * @return Returns the totalSendTime.
  209        */
  210       public long getTotalSendTime() {
  211           return totalSendTime;
  212       }
  213   
  214       /**
  215        * @return Returns the reqFilters.
  216        */
  217       protected java.util.regex.Pattern[] getReqFilters() {
  218           return reqFilters;
  219       }
  220       /**
  221        * @param reqFilters The reqFilters to set.
  222        */
  223       protected void setReqFilters(java.util.regex.Pattern[] reqFilters) {
  224           this.reqFilters = reqFilters;
  225       }
  226       
  227       // --------------------------------------------------------- Public Methods
  228       
  229   
  230       /**
  231        * Log the interesting request parameters, invoke the next Valve in the
  232        * sequence, and log the interesting response parameters.
  233        *
  234        * @param request The servlet request to be processed
  235        * @param response The servlet response to be created
  236        *
  237        * @exception IOException if an input/output error occurs
  238        * @exception ServletException if a servlet error occurs
  239        */
  240       public void invoke(Request request, Response response)
  241           throws IOException, ServletException
  242       {
  243           long totalstart = System.currentTimeMillis();
  244           //this happens before the request
  245           if (primaryIndicator)
  246               createPrimaryIndicator( request) ;
  247           getNext().invoke(request, response);
  248           //this happens after the request
  249           long start = System.currentTimeMillis();
  250           Manager manager = request.getContext().getManager();
  251           if (manager != null && manager instanceof ClusterManager) {
  252               ClusterManager clusterManager = (ClusterManager) manager;
  253               CatalinaCluster cluster = (CatalinaCluster) getContainer()
  254                       .getCluster();
  255               if (cluster == null) {
  256                   if (log.isWarnEnabled())
  257                       log.warn(sm.getString("ReplicationValve.nocluster"));
  258                   return;
  259               }
  260               // valve cluster can access manager - other clusterhandle replication 
  261               // at host level - hopefully!
  262               if(cluster.getManager(clusterManager.getName()) == null)
  263                   return ;
  264               if(cluster.getMembers().length > 0  ) {
  265                   try {
  266                       // send invalid sessions
  267                       // DeltaManager returns String[0]
  268                       if (!(clusterManager instanceof DeltaManager))
  269                           sendInvalidSessions(clusterManager, cluster);
  270                       // send replication
  271                       sendSessionReplicationMessage(request, clusterManager, cluster);
  272                   } catch (Exception x) {
  273                       log.error(sm.getString("ReplicationValve.send.failure"), x);
  274                   } finally {
  275                       long stop = System.currentTimeMillis();
  276                       updateStats(stop - totalstart, stop - start);
  277                   }
  278               }
  279           }
  280       }
  281     
  282       /**
  283        * reset the active statitics 
  284        */
  285       public void resetStatistics() {
  286           totalRequestTime = 0 ;
  287           totalSendTime = 0 ;
  288           lastSendTime = 0 ;
  289           nrOfFilterRequests = 0 ;
  290           nrOfRequests = 0 ;
  291       }
  292       
  293       /**
  294        * Return a String rendering of this object.
  295        */
  296       public String toString() {
  297   
  298           StringBuffer sb = new StringBuffer("ReplicationValve[");
  299           if (container != null)
  300               sb.append(container.getName());
  301           sb.append("]");
  302           return (sb.toString());
  303   
  304       }
  305   
  306       // --------------------------------------------------------- Protected Methods
  307   
  308       /**
  309        * Send Cluster Replication Request
  310        * @see DeltaManager#requestCompleted(String)
  311        * @see SimpleTcpCluster#send(ClusterMessage)
  312        * @param request
  313        * @param manager
  314        * @param cluster
  315        */
  316       protected void sendSessionReplicationMessage(Request request,
  317               ClusterManager manager, CatalinaCluster cluster) {
  318           Session session = request.getSessionInternal(false);
  319           if (session != null) {
  320               String uri = request.getDecodedRequestURI();
  321               // request without session change
  322               if (!isRequestWithoutSessionChange(uri)) {
  323   
  324                   if (log.isDebugEnabled())
  325                       log.debug(sm.getString("ReplicationValve.invoke.uri", uri));
  326                   String id = session.getIdInternal();
  327                   if (id != null) {
  328                       ClusterMessage msg = manager.requestCompleted(id);
  329                       // really send replication send request
  330                       // FIXME send directly via ClusterManager.send
  331                       if (msg != null) {
  332                           if(manager.isSendClusterDomainOnly())
  333                               cluster.sendClusterDomain(msg);
  334                           else
  335                               cluster.send(msg);
  336                       }
  337                   }
  338               } else
  339                   nrOfFilterRequests++;
  340           }
  341   
  342       }
  343       
  344       /**
  345        * check for session invalidations
  346        * @param manager
  347        * @param cluster
  348        */
  349       protected void sendInvalidSessions(ClusterManager manager, CatalinaCluster cluster) {
  350           String[] invalidIds=manager.getInvalidatedSessions();
  351           if ( invalidIds.length > 0 ) {
  352               for ( int i=0;i<invalidIds.length; i++ ) {
  353                   try {
  354                       ClusterMessage imsg = manager.requestCompleted(invalidIds[i]);
  355                       // FIXME send directly via ClusterManager.send
  356                       if (imsg != null) {
  357                           if(manager.isSendClusterDomainOnly())
  358                               cluster.sendClusterDomain(imsg);
  359                           else
  360                               cluster.send(imsg);
  361                       }
  362                   } catch ( Exception x ) {
  363                       log.error(sm.getString("ReplicationValve.send.invalid.failure",invalidIds[i]),x);
  364                   }
  365               }
  366           }
  367       }
  368       
  369       /**
  370        * is request without possible session change
  371        * @param uri The request uri
  372        * @return True if no session change
  373        */
  374       protected boolean isRequestWithoutSessionChange(String uri) {
  375   
  376           boolean filterfound = false;
  377   
  378           for (int i = 0; (i < reqFilters.length) && (!filterfound); i++) {
  379               java.util.regex.Matcher matcher = reqFilters[i].matcher(uri);
  380               filterfound = matcher.matches();
  381           }
  382           return filterfound;
  383       }
  384   
  385       /**
  386        * protocol cluster replications stats
  387        * @param requestTime
  388        * @param clusterTime
  389        */
  390       protected synchronized void updateStats(long requestTime, long clusterTime) {
  391           totalSendTime+=clusterTime;
  392           totalRequestTime+=requestTime;
  393           nrOfRequests++;
  394           if ( (nrOfRequests % 100) == 0 ) {
  395               if(log.isInfoEnabled()) {
  396                    log.info(sm.getString("ReplicationValve.stats",
  397                        new Object[]{
  398                            new Long(totalRequestTime/nrOfRequests),
  399                            new Long(totalSendTime/nrOfRequests),
  400                            new Long(nrOfRequests),
  401                            new Long(nrOfFilterRequests),
  402                            new Long(totalRequestTime),
  403                            new Long(totalSendTime)}));
  404                }
  405           }
  406           lastSendTime=System.currentTimeMillis();
  407       }
  408   
  409   
  410       /**
  411        * Mark Request that processed at primary node with attribute
  412        * primaryIndicatorName
  413        * 
  414        * @param request
  415        * @throws IOException
  416        */
  417       protected void createPrimaryIndicator(Request request) throws IOException {
  418           String id = request.getRequestedSessionId();
  419           if ((id != null) && (id.length() > 0)) {
  420               Manager manager = request.getContext().getManager();
  421               Session session = manager.findSession(id);
  422               if (session instanceof ClusterSession) {
  423                   ClusterSession cses = (ClusterSession) session;
  424                   if (cses != null) {
  425                       Boolean isPrimary = new Boolean(cses.isPrimarySession());
  426                       if (log.isDebugEnabled())
  427                           log.debug(sm.getString(
  428                                   "ReplicationValve.session.indicator", request.getContext().getName(),id,
  429                                   primaryIndicatorName, isPrimary));
  430                       request.setAttribute(primaryIndicatorName, isPrimary);
  431                   }
  432               } else {
  433                   if (log.isDebugEnabled()) {
  434                       if (session != null) {
  435                           log.debug(sm.getString(
  436                                   "ReplicationValve.session.found", request.getContext().getName(),id));
  437                       } else {
  438                           log.debug(sm.getString(
  439                                   "ReplicationValve.session.invalid", request.getContext().getName(),id));
  440                       }
  441                   }
  442               }
  443           }
  444       }
  445   
  446   
  447   
  448   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » cluster » tcp » [javadoc | source]