File Source: PingQueueProcessor.java

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * 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.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.business.pings;
    20  
    21  import java.util.Iterator;
    22  import java.util.List;
    23  import org.apache.commons.logging.Log;
    24  import org.apache.commons.logging.LogFactory;
    25  import org.apache.roller.weblogger.WebloggerException;
    26  import org.apache.roller.weblogger.business.WebloggerFactory;
    27  import org.apache.roller.weblogger.config.PingConfig;
    28  import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
    29  import org.apache.roller.weblogger.pojos.PingQueueEntry;
    30  import org.apache.roller.weblogger.pojos.PingTarget;
    31  import org.apache.roller.weblogger.pojos.Weblog;
    32  
    33  
    34  /**
    35   * Ping Queue Processor.  Singleton encapsulating logic for processing the weblog update ping queue.
    36   *
    37   * @author <a href="mailto:anil@busybuddha.org">Anil Gangolli</a>
    38   */
    39  public class PingQueueProcessor {
    40      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.business.pings.PingQueueProcessor__static_init
              * 
              *  Postconditions:
              *    init'ed(logger)
              */
    41      private static final Log logger = LogFactory.getLog(PingQueueProcessor.class);
    42      
    43      private static PingQueueProcessor theInstance;
    44      
    45      private PingQueueManager pingQueueMgr;
    46      
    47      
    48      public static PingQueueProcessor getInstance() {
                 /* 
    P/P           *  Method: PingQueueProcessor getInstance()
                  * 
                  *  Preconditions:
                  *    init'ed(theInstance)
                  * 
                  *  Postconditions:
                  *    return_value == theInstance
                  *    init'ed(return_value)
                  */
    49          return theInstance;
    50      }
    51      
    52      
             /* 
    P/P       *  Method: void org.apache.roller.weblogger.business.pings.PingQueueProcessor()
              * 
              *  Preconditions:
              *    org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider != null
              *    org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider.webloggerInstance != null
              * 
              *  Presumptions:
              *    getWeblogger(...)@54 init'ed
              * 
              *  Postconditions:
              *    init'ed(this.pingQueueMgr)
              */
    53      private PingQueueProcessor() throws WebloggerException {
    54          pingQueueMgr = WebloggerFactory.getWeblogger().getPingQueueManager();
    55      }
    56      
    57      
    58      /**
    59       * Initialize the singleton.  This is called during <code>RollerContext</code> initialization.
    60       *
    61       * @throws WebloggerException
    62       */
    63      public static synchronized void init() throws WebloggerException {
                 /* 
    P/P           *  Method: void init()
                  * 
                  *  Preconditions:
                  *    init'ed(theInstance)
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider != null
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider.webloggerInstance != null
                  * 
                  *  Presumptions:
                  *    org.apache.commons.logging.LogFactory:getLog(...)@41 != null
                  * 
                  *  Postconditions:
                  *    theInstance == One-of{old theInstance, &new PingQueueProcessor(init#1)}
                  *    theInstance != null
                  *    new PingQueueProcessor(init#1) num objects <= 1
                  *    init'ed(new PingQueueProcessor(init#1).pingQueueMgr)
                  * 
                  *  Test Vectors:
                  *    theInstance: Addr_Set{null}, Inverse{null}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@69: {0}, {1}
                  */
    64          if (theInstance != null) {
    65              logger.warn("Ignoring duplicate initialization of PingQueueProcessor!");
    66              return;
    67          }
    68          theInstance = new PingQueueProcessor();
    69          if (logger.isDebugEnabled()) logger.debug("Ping queue processor initialized.");
    70      }
    71      
    72      
    73      /**
    74       * Process the ping queue.  Performs one pass through the ping queue, processing every entry once.  On ping failure
    75       * an entry is requeued for processing on subsequent passes until the configured maximum number of attempts is
    76       * reached.
    77       */
    78      public synchronized void processQueue() {
                 /* 
    P/P           *  Method: void processQueue()
                  * 
                  *  Preconditions:
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider != null
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider.webloggerInstance != null
                  *    (soft) org/apache/roller/weblogger/business/jpa/JPAPingQueueManagerImpl.log != null
                  *    (soft) org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    (soft) org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  *    (soft) init'ed(org/apache/roller/weblogger/config/WebloggerRuntimeConfig.absoluteContextURL)
                  *    (soft) org/apache/roller/weblogger/config/WebloggerRuntimeConfig.log != null
                  *    (soft) org/apache/roller/weblogger/pojos/PingQueueEntry.pcInheritedFieldCount <= 232-5
                  *    (soft) this.pingQueueMgr != null
                  *    (soft) this.pingQueueMgr.strategy != null
                  *    ...
                  * 
                  *  Presumptions:
                  *    java.util.Iterator:next(...)@102 != null
                  *    javax.persistence.Query:getResultList(...)@104 != null
                  *    org.apache.commons.logging.LogFactory:getLog(...)@41 != null
                  *    pingQueueEntry.attempts@102 <= 232-2
                  *    pingQueueEntry.pingTarget@102 != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    java.util.Iterator:hasNext(...)@101: {0}, {1}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@105: {0}, {1}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@96: {0}, {1}
                  */
    79          if (PingConfig.getSuspendPingProcessing()) {
    80              logger.info("Ping processing has been suspended.  Skipping current round of ping queue processing.");
    81              return;
    82          }
    83          
    84          String absoluteContextUrl = WebloggerRuntimeConfig.getAbsoluteContextURL();
    85          if (absoluteContextUrl == null) {
    86              logger.warn("WARNING: Skipping current ping queue processing round because we cannot yet determine the site's absolute context url.");
    87              return;
    88          }
    89          
    90          // TODO: Group by ping target and ping all sites for that target?
    91          // We're currently not taking advantage of grouping by ping target site and then sending
    92          // all of the pings for that target at once.  If it becomes an efficiency issue, we should do
    93          // that.
    94          
    95          try {
    96              if (logger.isDebugEnabled()) logger.debug("Started processing ping queue.");
    97              // Get all of the entries
    98              List entries = pingQueueMgr.getAllQueueEntries();
    99              
   100              // Process each entry
   101              for (Iterator i = entries.iterator(); i.hasNext();) {
   102                  PingQueueEntry pingQueueEntry = (PingQueueEntry) i.next();
   103                  processQueueEntry(pingQueueEntry);
   104              }
   105              if (logger.isDebugEnabled()) logger.debug("Finished processing ping queue.");
   106          } catch (Exception ex) {
   107              logger.error("Unexpected exception processing ping queue!  Aborting this pass of ping queue processing.", ex);
   108          }
   109      }
   110      
   111      
   112      /**
   113       * Process an individual ping queue entry.
   114       *
   115       * @param pingQueueEntry     the ping queue entry
   116       * @throws WebloggerException only if there are problems processing the queue.  Exceptions from sending pings are
   117       *                         handled, not thrown.
   118       */
   119      private void processQueueEntry(PingQueueEntry pingQueueEntry) throws WebloggerException {
                 /* 
    P/P           *  Method: void processQueueEntry(PingQueueEntry)
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  *    pingQueueEntry != null
                  *    init'ed(pingQueueEntry.pcStateManager)
                  *    (soft) pingQueueEntry.attempts <= 232-2
                  *    (soft) org/apache/roller/weblogger/business/jpa/JPAPingQueueManagerImpl.log != null
                  *    (soft) org/apache/roller/weblogger/pojos/PingQueueEntry.pcInheritedFieldCount <= 232-5
                  *    (soft) pingQueueEntry.pingTarget != null
                  *    (soft) pingQueueEntry.website != null
                  *    (soft) this.pingQueueMgr != null
                  *    ...
                  * 
                  *  Presumptions:
                  *    org.apache.commons.logging.LogFactory:getLog(...)@41 != null
                  * 
                  *  Postconditions:
                  *    pingQueueEntry.attempts == One-of{old pingQueueEntry.attempts, old pingQueueEntry.attempts + 1}
                  *    (soft) init'ed(pingQueueEntry.attempts)
                  * 
                  *  Test Vectors:
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@120: {0}, {1}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@144: {0}, {1}
                  */
   120          if (logger.isDebugEnabled()) logger.debug("Processing ping queue entry: " + pingQueueEntry);
   121          
   122          PingTarget pingTarget = pingQueueEntry.getPingTarget();
   123          Weblog website = pingQueueEntry.getWebsite();
   124          boolean pingSucceeded = false;
   125          if (PingConfig.getLogPingsOnly()) {
   126              // Just log the ping and pretend it succeeded.
   127              logger.info("Logging simulated ping for ping queue entry " + pingQueueEntry);
   128              pingSucceeded = true;
   129          } else {
   130              // Actually process the ping
   131              try {
   132                  // Send the ping
   133                  WeblogUpdatePinger.sendPing(pingTarget, website);
   134                  // Consider successful ping transmission if we didn't get an exception.  We don't care here
   135                  // about the result of the ping if it was transmitted.
   136                  pingSucceeded = true;
   137              } catch (Exception ex) {
   138                  // Handle the ping error, either removing or requeuing the ping queue entry.
   139                  handlePingError(pingQueueEntry, ex);
   140              }
   141          }
   142          // We do this outside of the previous try-catch because we don't want an exception here to be considered a ping error.
   143          if (pingSucceeded) {
   144              if (logger.isDebugEnabled()) logger.debug("Processed ping: " + pingQueueEntry);
   145              pingQueueMgr.removeQueueEntry(pingQueueEntry);
   146          }
   147      }
   148      
   149      
   150      /**
   151       * Handle any ping error.
   152       *
   153       * @param pingQueueEntry the ping queue entry
   154       * @param ex             the exception that occurred on the ping attempt
   155       * @throws WebloggerException
   156       */
   157      private void handlePingError(PingQueueEntry pingQueueEntry, Exception ex)
   158              throws WebloggerException {
   159          
                 /* 
    P/P           *  Method: void handlePingError(PingQueueEntry, Exception)
                  * 
                  *  Preconditions:
                  *    ex != null
                  *    pingQueueEntry.attempts <= 232-2
                  *    org/apache/roller/weblogger/business/jpa/JPAPingQueueManagerImpl.log != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  *    pingQueueEntry != null
                  *    init'ed(pingQueueEntry.pcStateManager)
                  *    this.pingQueueMgr != null
                  *    this.pingQueueMgr.strategy != null
                  *    this.pingQueueMgr.strategy.threadLocalEntityManager != null
                  *    ...
                  * 
                  *  Presumptions:
                  *    org.apache.commons.logging.LogFactory:getLog(...)@41 != null
                  * 
                  *  Postconditions:
                  *    pingQueueEntry.attempts == old pingQueueEntry.attempts + 1
                  *    pingQueueEntry.attempts >= -231+1
                  */
   160          if ((pingQueueEntry.incrementAttempts() < PingConfig.getMaxPingAttempts()) && WeblogUpdatePinger.shouldRetry(ex)) {
   161              // We have attempts remaining, and it looks like we should retry,
   162              // so requeue the entry for processing on subsequent rounds
   163              logger.debug("Error on ping attempt (" + pingQueueEntry.getAttempts() + ") for " + pingQueueEntry + ": [" + ex.getMessage() + "]. Will re-queue for later attempts.");
   164              logger.debug("Error on last ping attempt was: ", ex);
   165              pingQueueMgr.saveQueueEntry(pingQueueEntry);
   166          } else {
   167              // Remove the entry
   168              logger.warn("Error on ping attempt (" + pingQueueEntry.getAttempts() + ") for " + pingQueueEntry + ": [" + ex.getMessage() + "].  Entry will be REMOVED from ping queue.");
   169              logger.debug("Error on last ping attempt was: ", ex);
   170              pingQueueMgr.removeQueueEntry(pingQueueEntry);
   171              // TODO: mark ping target invalid?
   172          }
   173      }
   174      
   175  }








SofCheck Inspector Build Version : 2.18479
PingQueueProcessor.java 2009-Jan-02 14:25:40
PingQueueProcessor.class 2009-Sep-04 03:12:31