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 |