001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018:
019: package org.apache.roller.business;
020:
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.List;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.apache.roller.business.runnable.ContinuousWorkerThread;
027: import org.apache.roller.business.runnable.HitCountProcessingJob;
028: import org.apache.roller.business.runnable.WorkerThread;
029: import org.apache.roller.config.RollerConfig;
030: import org.apache.roller.pojos.WebsiteData;
031:
032: /**
033: * Queue's up incoming hit counts so that they can be recorded to the db in
034: * an asynchronous manner at give intervals.
035: *
036: * We also start up a single thread which runs continously to take the queued
037: * hit counts, tally them, and record them into the db.
038: *
039: * TODO: we may want to make this an interface that is pluggable if there is
040: * some indication that users want to override this implementation.
041: */
042: public class HitCountQueue {
043:
044: private static Log log = LogFactory.getLog(HitCountQueue.class);
045:
046: private static HitCountQueue instance = null;
047:
048: private int numWorkers = 1;
049: private int sleepTime = 180000;
050: private WorkerThread worker = null;
051: private List queue = null;
052:
053: static {
054: instance = new HitCountQueue();
055: }
056:
057: // non-instantiable because we are a singleton
058: private HitCountQueue() {
059:
060: String sleep = RollerConfig.getProperty(
061: "hitcount.queue.sleepTime", "180");
062:
063: try {
064: // multiply by 1000 because we expect input in seconds
065: this .sleepTime = Integer.parseInt(sleep) * 1000;
066: } catch (NumberFormatException nfe) {
067: log.warn("Invalid sleep time [" + sleep
068: + "], using default");
069: }
070:
071: // create the hits queue
072: this .queue = Collections.synchronizedList(new ArrayList());
073:
074: // start up a worker to process the hits at intervals
075: HitCountProcessingJob job = new HitCountProcessingJob();
076: worker = new ContinuousWorkerThread("HitCountQueueProcessor",
077: job, this .sleepTime);
078: worker.start();
079: }
080:
081: public static HitCountQueue getInstance() {
082: return instance;
083: }
084:
085: public void processHit(WebsiteData weblog, String url,
086: String referrer) {
087:
088: // if the weblog isn't null then just drop it's handle in the queue
089: // each entry in the queue is a weblog handle and indicates a single hit
090: if (weblog != null) {
091: this .queue.add(weblog.getHandle());
092: }
093: }
094:
095: public List getHits() {
096: return new ArrayList(this .queue);
097: }
098:
099: /**
100: * Reset the queued hits.
101: */
102: public synchronized void resetHits() {
103: this .queue = Collections.synchronizedList(new ArrayList());
104: }
105:
106: /**
107: * clean up.
108: */
109: public void shutdown() {
110:
111: if (this .worker != null) {
112: log.info("stopping worker " + this.worker.getName());
113: worker.interrupt();
114: }
115:
116: }
117:
118: }
|