KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > roller > business > referrers > ReferrerQueueManagerImpl


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  * ReferrerQueueManagerImpl.java
20  *
21  * Created on December 16, 2005, 5:06 PM
22  */

23
24 package org.apache.roller.business.referrers;
25
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.roller.RollerException;
34 import org.apache.roller.business.runnable.ContinuousWorkerThread;
35 import org.apache.roller.business.runnable.WorkerThread;
36 import org.apache.roller.config.RollerConfig;
37 import org.apache.roller.model.RollerFactory;
38
39
40 /**
41  * The base implementation of the ReferrerQueueManager.
42  *
43  * This class is implemented using the singleton pattern to ensure that only
44  * one instance exists at any given time.
45  *
46  * This implementation can be configured to handle referrers in 2 ways ...
47  * 1. synchronously. referrers are processed immediately.
48  * 2. asynchronously. referrers are queued for later processing.
49  *
50  * Users can control the referrer queue mode via properties in the static
51  * roller.properties configuration file.
52  *
53  * In asynchronous processing mode we start some number of worker threads which
54  * run continously to process any referrers that have been queued. Each worker
55  * processes queued referrers until the queue is empty, then sleeps for a given
56  * amount of time. The number of workers used and their sleep time can be set
57  * via properties of the static roller.properties file.
58  *
59  * @author Allen Gilliland
60  */

61 public class ReferrerQueueManagerImpl implements ReferrerQueueManager {
62     
63     private static Log mLogger = LogFactory.getLog(ReferrerQueueManagerImpl.class);
64     
65     private static ReferrerQueueManager instance = null;
66     
67     private boolean asyncMode = false;
68     private int numWorkers = 1;
69     private int sleepTime = 10000;
70     private List JavaDoc workers = null;
71     private List JavaDoc referrerQueue = null;
72     
73     static {
74         instance = new ReferrerQueueManagerImpl();
75     }
76     
77     
78     // private because we are a singleton
79
private ReferrerQueueManagerImpl() {
80         mLogger.info("Initializing Referrer Queue Manager");
81         
82         // lookup config options
83
this.asyncMode = RollerConfig.getBooleanProperty("referrers.asyncProcessing.enabled");
84         
85         mLogger.info("Asynchronous referrer processing = "+this.asyncMode);
86         
87         if(this.asyncMode) {
88             
89             
90             String JavaDoc num = RollerConfig.getProperty("referrers.queue.numWorkers");
91             String JavaDoc sleep = RollerConfig.getProperty("referrers.queue.sleepTime");
92             
93             try {
94                 this.numWorkers = Integer.parseInt(num);
95                 
96                 if(numWorkers < 1)
97                     this.numWorkers = 1;
98                 
99             } catch(NumberFormatException JavaDoc nfe) {
100                 mLogger.warn("Invalid num workers ["+num+"], using default");
101             }
102             
103             try {
104                 // multiply by 1000 because we expect input in seconds
105
this.sleepTime = Integer.parseInt(sleep) * 1000;
106             } catch(NumberFormatException JavaDoc nfe) {
107                 mLogger.warn("Invalid sleep time ["+sleep+"], using default");
108             }
109             
110             // create the processing queue
111
this.referrerQueue = Collections.synchronizedList(new ArrayList JavaDoc());
112             
113             // start up workers
114
this.workers = new ArrayList JavaDoc();
115             ContinuousWorkerThread worker = null;
116             QueuedReferrerProcessingJob job = null;
117             for(int i=0; i < this.numWorkers; i++) {
118                 job = new QueuedReferrerProcessingJob();
119                 worker = new ContinuousWorkerThread("ReferrerWorker"+i, job, this.sleepTime);
120                 workers.add(worker);
121                 worker.start();
122             }
123         }
124     }
125     
126     
127     /**
128      * Get access to the singleton instance.
129      */

130     public static ReferrerQueueManager getInstance() {
131         return instance;
132     }
133     
134     
135     /**
136      * Process an incoming referrer.
137      *
138      * If we are doing asynchronous referrer processing then the referrer will
139      * just go into the queue for later processing. If not then we process it
140      * now.
141      */

142     public void processReferrer(IncomingReferrer referrer) {
143         
144         if(this.asyncMode) {
145             mLogger.debug("QUEUING: "+referrer.getRequestUrl());
146             
147             // add to queue
148
this.enqueue(referrer);
149         } else {
150             // process now
151
ReferrerProcessingJob job = new ReferrerProcessingJob();
152             
153             // setup input
154
HashMap JavaDoc inputs = new HashMap JavaDoc();
155             inputs.put("referrer", referrer);
156             job.input(inputs);
157             
158             // execute
159
job.execute();
160             
161             try {
162                 // flush changes
163
RollerFactory.getRoller().flush();
164             } catch (RollerException ex) {
165                 mLogger.error("ERROR commiting referrer", ex);
166             }
167         }
168         
169     }
170     
171     
172     /**
173      * Place a referrer in the queue.
174      */

175     public void enqueue(IncomingReferrer referrer) {
176         this.referrerQueue.add(referrer);
177         
178         if(this.referrerQueue.size() > 250) {
179             mLogger.warn("Referrer queue is rather full. queued="+this.referrerQueue.size());
180         }
181     }
182     
183     
184     /**
185      * Retrieve the next referrer in the queue.
186      */

187     public synchronized IncomingReferrer dequeue() {
188         
189         if(!this.referrerQueue.isEmpty()) {
190             return (IncomingReferrer) this.referrerQueue.remove(0);
191         }
192         
193         return null;
194     }
195     
196     
197     /**
198      * clean up.
199      */

200     public void shutdown() {
201         
202         if(this.workers != null && this.workers.size() > 0) {
203             mLogger.info("stopping all ReferrerQueue worker threads");
204             
205             // kill all of our threads
206
WorkerThread worker = null;
207             Iterator JavaDoc it = this.workers.iterator();
208             while(it.hasNext()) {
209                 worker = (WorkerThread) it.next();
210                 worker.interrupt();
211             }
212         }
213         
214     }
215     
216 }
217
Popular Tags