Return-Path: Delivered-To: apmail-tomcat-dev-archive@www.apache.org Received: (qmail 58209 invoked from network); 23 Feb 2006 19:58:16 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 23 Feb 2006 19:58:16 -0000 Received: (qmail 60490 invoked by uid 500); 23 Feb 2006 19:56:35 -0000 Delivered-To: apmail-tomcat-dev-archive@tomcat.apache.org Received: (qmail 60188 invoked by uid 500); 23 Feb 2006 19:56:33 -0000 Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Developers List" Delivered-To: mailing list dev@tomcat.apache.org Received: (qmail 59832 invoked by uid 500); 23 Feb 2006 19:56:30 -0000 Delivered-To: apmail-jakarta-tomcat-dev@jakarta.apache.org Received: (qmail 59805 invoked by uid 99); 23 Feb 2006 19:56:28 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 23 Feb 2006 11:56:28 -0800 X-ASF-Spam-Status: No, hits=-8.6 required=10.0 tests=ALL_TRUSTED,INFO_TLD,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Thu, 23 Feb 2006 11:56:15 -0800 Received: (qmail 57371 invoked by uid 65534); 23 Feb 2006 19:55:55 -0000 Message-ID: <20060223195555.57369.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r380209 [5/12] - in /tomcat/container/tc5.5.x/modules: groupcom/ groupcom/etc/ groupcom/src/ groupcom/src/share/ groupcom/src/share/org/ groupcom/src/share/org/apache/ groupcom/src/share/org/apache/catalina/ groupcom/src/share/org/apache/ca... Date: Thu, 23 Feb 2006 19:55:25 -0000 To: tomcat-dev@jakarta.apache.org From: fhanik@apache.org X-Mailer: svnmailer-1.0.7 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/tcp/mbeans-descriptors.xml URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/tcp/mbeans-descriptors.xml?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/tcp/mbeans-descriptors.xml (added) +++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/tcp/mbeans-descriptors.xml Thu Feb 23 11:55:14 2006 @@ -0,0 +1,1046 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/FastQueue.java URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/FastQueue.java?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/FastQueue.java (added) +++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/FastQueue.java Thu Feb 23 11:55:14 2006 @@ -0,0 +1,625 @@ +/* + * Copyright 1999,2004-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.cluster.util; + +/** + * A fast queue that remover thread lock the adder thread.
Limit the queue + * length when you have strange producer thread problemes. + * + * FIXME add i18n support to log messages + * @author Rainer Jung + * @author Peter Rossbach + * @version $Revision: 345567 $ $Date: 2005-11-18 15:07:23 -0600 (Fri, 18 Nov 2005) $ + */ +public class FastQueue implements IQueue { + + private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory + .getLog(FastQueue.class); + + /** + * This is the actual queue + */ + private SingleRemoveSynchronizedAddLock lock = null; + + /** + * First Object at queue (consumer message) + */ + private LinkObject first = null; + + /** + * Last object in queue (producer Object) + */ + private LinkObject last = null; + + /** + * Current Queue elements size + */ + private int size = 0; + + /** + * check lock to detect strange threadings things + */ + private boolean checkLock = false; + + /** + * protocol the thread wait times + */ + private boolean timeWait = false; + + /** + * calc stats data + */ + private boolean doStats = false; + + private boolean inAdd = false; + + private boolean inRemove = false; + + private boolean inMutex = false; + + /** + * limit the queue legnth ( default is unlimited) + */ + private int maxQueueLength = 0; + + /** + * addWaitTimeout for producer + */ + private long addWaitTimeout = 10000L; + + + /** + * removeWaitTimeout for consumer + */ + private long removeWaitTimeout = 30000L; + + /** + * enabled the queue + */ + private boolean enabled = true; + + /** + * calc all add objects + */ + private long addCounter = 0; + + /** + * calc all add objetcs in error state ( see limit queue length) + */ + private long addErrorCounter = 0; + + /** + * calc all remove objects + */ + private long removeCounter = 0; + + /** + * calc all remove objects failures (hupps probleme detection) + */ + private long removeErrorCounter = 0; + + /** + * Calc wait time thread + */ + private long addWait = 0; + + /** + * Calc remove time threads + */ + private long removeWait = 0; + + /** + * max queue size + */ + private int maxSize = 0; + + /** + * avg queue size + */ + private long avgSize = 0; + + private int maxSizeSample = 0; + + private long avgSizeSample = 0; + + /** + * avg size sample interval + */ + private int sampleInterval = 100; + + /** + * Generate Queue SingleRemoveSynchronizedAddLock and set add and wait + * Timeouts + */ + public FastQueue() { + lock = new SingleRemoveSynchronizedAddLock(); + lock.setAddWaitTimeout(addWaitTimeout); + lock.setRemoveWaitTimeout(removeWaitTimeout); + } + + /** + * get current add wait timeout + * + * @return current wait timeout + */ + public long getAddWaitTimeout() { + addWaitTimeout = lock.getAddWaitTimeout(); + return addWaitTimeout; + } + + /** + * Set add wait timeout (default 10000 msec) + * + * @param timeout + */ + public void setAddWaitTimeout(long timeout) { + addWaitTimeout = timeout; + lock.setAddWaitTimeout(addWaitTimeout); + } + + /** + * get current remove wait timeout + * + * @return The timeout + */ + public long getRemoveWaitTimeout() { + removeWaitTimeout = lock.getRemoveWaitTimeout(); + return removeWaitTimeout; + } + + /** + * set remove wait timeout ( default 30000 msec) + * + * @param timeout + */ + public void setRemoveWaitTimeout(long timeout) { + removeWaitTimeout = timeout; + lock.setRemoveWaitTimeout(removeWaitTimeout); + } + + /** + * get Max Queue length + * + * @see org.apache.catalina.cluster.util.IQueue#getMaxQueueLength() + */ + public int getMaxQueueLength() { + return maxQueueLength; + } + + public void setMaxQueueLength(int length) { + maxQueueLength = length; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enable) { + enabled = enable; + if (!enabled) { + lock.abortRemove(); + } + } + + /** + * @return Returns the checkLock. + */ + public boolean isCheckLock() { + return checkLock; + } + + /** + * @param checkLock The checkLock to set. + */ + public void setCheckLock(boolean checkLock) { + this.checkLock = checkLock; + } + + /** + * @return Returns the doStats. + */ + public boolean isDoStats() { + return doStats; + } + + /** + * @param doStats The doStats to set. + */ + public void setDoStats(boolean doStats) { + this.doStats = doStats; + } + + /** + * @return Returns the timeWait. + */ + public boolean isTimeWait() { + return timeWait; + } + + /** + * @param timeWait The timeWait to set. + */ + public void setTimeWait(boolean timeWait) { + this.timeWait = timeWait; + } + + public int getSampleInterval() { + return sampleInterval; + } + + public void setSampleInterval(int interval) { + sampleInterval = interval; + } + + public long getAddCounter() { + return addCounter; + } + + public void setAddCounter(long counter) { + addCounter = counter; + } + + public long getAddErrorCounter() { + return addErrorCounter; + } + + public void setAddErrorCounter(long counter) { + addErrorCounter = counter; + } + + public long getRemoveCounter() { + return removeCounter; + } + + public void setRemoveCounter(long counter) { + removeCounter = counter; + } + + public long getRemoveErrorCounter() { + return removeErrorCounter; + } + + public void setRemoveErrorCounter(long counter) { + removeErrorCounter = counter; + } + + public long getAddWait() { + return addWait; + } + + public void setAddWait(long wait) { + addWait = wait; + } + + public long getRemoveWait() { + return removeWait; + } + + public void setRemoveWait(long wait) { + removeWait = wait; + } + + /** + * @return The max size + */ + public int getMaxSize() { + return maxSize; + } + + /** + * @param size + */ + public void setMaxSize(int size) { + maxSize = size; + } + + + /** + * Avg queue size + * @return The average queue size + */ + public long getAvgSize() { + if (addCounter > 0) { + return avgSize / addCounter; + } else { + return 0; + } + } + + /** + * reset all stats data + */ + public void resetStatistics() { + addCounter = 0; + addErrorCounter = 0; + removeCounter = 0; + removeErrorCounter = 0; + avgSize = 0; + maxSize = 0; + addWait = 0; + removeWait = 0; + } + + /** + * unlock queue for next add + */ + public void unlockAdd() { + lock.unlockAdd(size > 0 ? true : false); + } + + /** + * unlock queue for next remove + */ + public void unlockRemove() { + lock.unlockRemove(); + } + + /** + * start queuing + */ + public void start() { + setEnabled(true); + } + + /** + * start queuing + */ + public void stop() { + setEnabled(false); + } + + public long getSample() { + return addCounter % sampleInterval; + } + + public int getMaxSizeSample() { + return maxSizeSample; + } + + public void setMaxSizeSample(int size) { + maxSizeSample = size; + } + + public long getAvgSizeSample() { + long sample = addCounter % sampleInterval; + if (sample > 0) { + return avgSizeSample / sample; + } else if (addCounter > 0) { + return avgSizeSample / sampleInterval; + } else { + return 0; + } + } + + public int getSize() { + int sz; + sz = size; + return sz; + } + + /** + * Add new data to the queue + * @see org.apache.catalina.cluster.util.IQueue#add(java.lang.String, java.lang.Object) + * FIXME extract some method + */ + public boolean add(String key, Object data) { + boolean ok = true; + long time = 0; + + if (!enabled) { + if (log.isInfoEnabled()) + log.info("FastQueue.add: queue disabled, add aborted"); + return false; + } + + if (timeWait) { + time = System.currentTimeMillis(); + } + lock.lockAdd(); + try { + if (timeWait) { + addWait += (System.currentTimeMillis() - time); + } + + if (log.isTraceEnabled()) { + log.trace("FastQueue.add: starting with size " + size); + } + if (checkLock) { + if (inAdd) + log.warn("FastQueue.add: Detected other add"); + inAdd = true; + if (inMutex) + log.warn("FastQueue.add: Detected other mutex in add"); + inMutex = true; + } + + if ((maxQueueLength > 0) && (size >= maxQueueLength)) { + ok = false; + if (log.isTraceEnabled()) { + log.trace("FastQueue.add: Could not add, since queue is full (" + + size + ">=" + maxQueueLength + ")"); + } + + } else { + LinkObject element = new LinkObject(key, data); + if (size == 0) { + first = last = element; + size = 1; + } else { + if (last == null) { + ok = false; + log + .error("FastQueue.add: Could not add, since last is null although size is " + + size + " (>0)"); + } else { + last.append(element); + last = element; + size++; + } + } + + } + + if (doStats) { + if (ok) { + if (addCounter % sampleInterval == 0) { + maxSizeSample = 0; + avgSizeSample = 0; + } + addCounter++; + if (size > maxSize) { + maxSize = size; + } + if (size > maxSizeSample) { + maxSizeSample = size; + } + avgSize += size; + avgSizeSample += size; + } else { + addErrorCounter++; + } + } + + if (first == null) { + log.error("FastQueue.add: first is null, size is " + size + + " at end of add"); + } + if (last == null) { + log.error("FastQueue.add: last is null, size is " + size + + " at end of add"); + } + + if (checkLock) { + if (!inMutex) + log.warn("FastQueue.add: Cancelled by other mutex in add"); + inMutex = false; + if (!inAdd) + log.warn("FastQueue.add: Cancelled by other add"); + inAdd = false; + } + if (log.isTraceEnabled()) { + log.trace("FastQueue.add: add ending with size " + size); + } + + if (timeWait) { + time = System.currentTimeMillis(); + } + } finally { + lock.unlockAdd(true); + } + if (timeWait) { + addWait += (System.currentTimeMillis() - time); + } + return ok; + } + + /** + * remove the complete queued object list + * @see org.apache.catalina.cluster.util.IQueue#remove() + * FIXME extract some method + */ + public LinkObject remove() { + LinkObject element; + boolean gotLock; + long time = 0; + + if (!enabled) { + if (log.isInfoEnabled()) + log.info("FastQueue.remove: queue disabled, remove aborted"); + return null; + } + + if (timeWait) { + time = System.currentTimeMillis(); + } + gotLock = lock.lockRemove(); + try { + + if (!gotLock) { + if (enabled) { + if (timeWait) { + removeWait += (System.currentTimeMillis() - time); + } + if (doStats) { + removeErrorCounter++; + } + if (log.isInfoEnabled()) + log.info("FastQueue.remove: Remove aborted although queue enabled"); + } else { + if (log.isInfoEnabled()) + log.info("FastQueue.remove: queue disabled, remove aborted"); + } + return null; + } + + if (timeWait) { + removeWait += (System.currentTimeMillis() - time); + } + + if (log.isTraceEnabled()) { + log.trace("FastQueue.remove: remove starting with size " + size); + } + if (checkLock) { + if (inRemove) + log.warn("FastQueue.remove: Detected other remove"); + inRemove = true; + if (inMutex) + log.warn("FastQueue.remove: Detected other mutex in remove"); + inMutex = true; + } + + element = first; + + if (doStats) { + if (element != null) { + removeCounter++; + } else { + removeErrorCounter++; + log + .error("FastQueue.remove: Could not remove, since first is null although size is " + + size + " (>0)"); + } + } + + first = last = null; + size = 0; + + if (checkLock) { + if (!inMutex) + log.warn("FastQueue.remove: Cancelled by other mutex in remove"); + inMutex = false; + if (!inRemove) + log.warn("FastQueue.remove: Cancelled by other remove"); + inRemove = false; + } + if (log.isTraceEnabled()) { + log.trace("FastQueue.remove: remove ending with size " + size); + } + + if (timeWait) { + time = System.currentTimeMillis(); + } + } finally { + lock.unlockRemove(); + } + if (timeWait) { + removeWait += (System.currentTimeMillis() - time); + } + return element; + } + +} Added: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IDynamicProperty.java URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IDynamicProperty.java?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IDynamicProperty.java (added) +++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IDynamicProperty.java Thu Feb 23 11:55:14 2006 @@ -0,0 +1,57 @@ +/* + * Copyright 1999,2004-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.cluster.util; + +import java.util.Iterator; + +/** + * @author Peter Rossbach + * @version $Revision: 304032 $, $Date: 2005-07-27 10:11:55 -0500 (Wed, 27 Jul 2005) $ + */ + +public interface IDynamicProperty { + + /** + * set config attributes with reflect + * + * @param name + * @param value + */ + public void setProperty(String name, Object value) ; + + /** + * get current config + * + * @param key + * @return The property + */ + public Object getProperty(String key) ; + /** + * Get all properties keys + * + * @return An iterator over the property names + */ + public Iterator getPropertyNames() ; + + /** + * remove a configured property. + * + * @param key + */ + public void removeProperty(String key) ; + +} Added: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IQueue.java URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IQueue.java?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IQueue.java (added) +++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/IQueue.java Thu Feb 23 11:55:14 2006 @@ -0,0 +1,35 @@ +/* + * Copyright 1999,2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.cluster.util; + +/** + * A queue interface
+ * + * @author Rainer Jung + * @author Peter Rossbach + * @version $Revision: 303753 $ $Date: 2005-03-14 15:24:30 -0600 (Mon, 14 Mar 2005) $ + */ + +public interface IQueue { + + public LinkObject remove(); + public boolean add(String key,Object data); + public int getMaxQueueLength(); + public void setMaxQueueLength(int length); + public void start(); + public void stop(); +} Added: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/LinkObject.java URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/LinkObject.java?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/LinkObject.java (added) +++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/LinkObject.java Thu Feb 23 11:55:14 2006 @@ -0,0 +1,81 @@ +/* + * Copyright 1999,2004-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.cluster.util; + +/** + * The class LinkObject implements an element + * for a linked list, consisting of a general + * data object and a pointer to the next element. + * + * @author Rainer Jung + * @author Peter Rossbach + * @version $Revision: 304032 $ $Date: 2005-07-27 10:11:55 -0500 (Wed, 27 Jul 2005) $ + + */ + +public class LinkObject { + + private Object payload; + private LinkObject next; + private String key ; + + /** + * Construct a new element from the data object. + * Sets the pointer to null. + * + * @param key The key + * @param payload The data object. + */ + public LinkObject(String key,Object payload) { + this.payload = payload; + this.next = null; + this.key = key ; + } + + /** + * Set the next element. + * @param next The next element. + */ + public void append(LinkObject next) { + this.next = next; + } + + /** + * Get the next element. + * @return The next element. + */ + public LinkObject next() { + return next; + } + + /** + * Get the data object from the element. + * @return The data object from the element. + */ + public Object data() { + return payload; + } + + /** + * Get the unique message id + * @return the unique message id + */ + public Object getKey() { + return key; + } + +} Added: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SingleRemoveSynchronizedAddLock.java URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SingleRemoveSynchronizedAddLock.java?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SingleRemoveSynchronizedAddLock.java (added) +++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SingleRemoveSynchronizedAddLock.java Thu Feb 23 11:55:14 2006 @@ -0,0 +1,251 @@ +/* + * Copyright 1999,2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.cluster.util; + +/** + * The class SingleRemoveSynchronizedAddLock implement locking for accessing the queue + * by a single remove thread and multiple add threads. + * + * A thread is only allowed to be either the remove or + * an add thread. + * + * The lock can either be owned by the remove thread + * or by a single add thread. + * + * If the remove thread tries to get the lock, + * but the queue is empty, it will block (poll) + * until an add threads adds an entry to the queue and + * releases the lock. + * + * If the remove thread and add threads compete for + * the lock and an add thread releases the lock, then + * the remove thread will get the lock first. + * + * The remove thread removes all entries in the queue + * at once and proceeses them without further + * polling the queue. + * + * The lock is not reentrant, in the sense, that all + * threads must release an owned lock before competing + * for the lock again! + * + * @author Rainer Jung + * @author Peter Rossbach + * @version 1.1 + */ + +public class SingleRemoveSynchronizedAddLock { + + public SingleRemoveSynchronizedAddLock() { + } + + public SingleRemoveSynchronizedAddLock(boolean dataAvailable) { + this.dataAvailable=dataAvailable; + } + + /** + * Time in milliseconds after which threads + * waiting for an add lock are woken up. + * This is used as a safety measure in case + * thread notification via the unlock methods + * has a bug. + */ + private long addWaitTimeout = 10000L; + + /** + * Time in milliseconds after which threads + * waiting for a remove lock are woken up. + * This is used as a safety measure in case + * thread notification via the unlock methods + * has a bug. + */ + private long removeWaitTimeout = 30000L; + + /** + * The current remove thread. + * It is set to the remove thread polling for entries. + * It is reset to null when the remove thread + * releases the lock and proceeds processing + * the removed entries. + */ + private Thread remover = null; + + /** + * A flag indicating, if an add thread owns the lock. + */ + private boolean addLocked = false; + + /** + * A flag indicating, if the remove thread owns the lock. + */ + private boolean removeLocked = false; + + /** + * A flag indicating, if the remove thread is allowed + * to wait for the lock. The flag is set to false, when aborting. + */ + private boolean removeEnabled = true; + + /** + * A flag indicating, if the remover needs polling. + * It indicates, if the locked object has data available + * to be removed. + */ + private boolean dataAvailable = false; + + /** + * @return Value of addWaitTimeout + */ + public synchronized long getAddWaitTimeout() { + return addWaitTimeout; + } + + /** + * Set value of addWaitTimeout + */ + public synchronized void setAddWaitTimeout(long timeout) { + addWaitTimeout = timeout; + } + + /** + * @return Value of removeWaitTimeout + */ + public synchronized long getRemoveWaitTimeout() { + return removeWaitTimeout; + } + + /** + * Set value of removeWaitTimeout + */ + public synchronized void setRemoveWaitTimeout(long timeout) { + removeWaitTimeout = timeout; + } + + /** + * Check if the locked object has data available + * i.e. the remover can stop poling and get the lock. + * @return True iff the lock Object has data available. + */ + public synchronized boolean isDataAvailable() { + return dataAvailable; + } + + /** + * Check if an add thread owns the lock. + * @return True iff an add thread owns the lock. + */ + public synchronized boolean isAddLocked() { + return addLocked; + } + + /** + * Check if the remove thread owns the lock. + * @return True iff the remove thread owns the lock. + */ + public synchronized boolean isRemoveLocked() { + return removeLocked; + } + + /** + * Check if the remove thread is polling. + * @return True iff the remove thread is polling. + */ + public synchronized boolean isRemovePolling() { + if ( remover != null ) { + return true; + } + return false; + } + + /** + * Acquires the lock by an add thread and sets the add flag. + * If any add thread or the remove thread already acquired the lock + * this add thread will block until the lock is released. + */ + public synchronized void lockAdd() { + if ( addLocked || removeLocked ) { + do { + try { + wait(addWaitTimeout); + } catch ( InterruptedException e ) { + } + } while ( addLocked || removeLocked ); + } + addLocked=true; + } + + /** + * Acquires the lock by the remove thread and sets the remove flag. + * If any add thread already acquired the lock or the queue is + * empty, the remove thread will block until the lock is released + * and the queue is not empty. + */ + public synchronized boolean lockRemove() { + removeLocked=false; + removeEnabled=true; + if ( ( addLocked || ! dataAvailable ) && removeEnabled ) { + remover=Thread.currentThread(); + do { + try { + wait(removeWaitTimeout); + } catch ( InterruptedException e ) { + } + } while ( ( addLocked || ! dataAvailable ) && removeEnabled ); + remover=null; + } + if ( removeEnabled ) { + removeLocked=true; + } + return removeLocked; + } + + /** + * Releases the lock by an add thread and reset the remove flag. + * If the reader thread is polling, notify it. + */ + public synchronized void unlockAdd(boolean dataAvailable) { + addLocked=false; + this.dataAvailable=dataAvailable; + if ( ( remover != null ) && ( dataAvailable || ! removeEnabled ) ) { + remover.interrupt(); + } else { + notifyAll(); + } + } + + /** + * Releases the lock by the remove thread and reset the add flag. + * Notify all waiting add threads, + * that the lock has been released by the remove thread. + */ + public synchronized void unlockRemove() { + removeLocked=false; + dataAvailable=false; + notifyAll(); + } + + /** + * Abort any polling remover thread + */ + public synchronized void abortRemove() { + removeEnabled=false; + if ( remover != null ) { + remover.interrupt(); + } + } + +} Added: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SmartQueue.java URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SmartQueue.java?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SmartQueue.java (added) +++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/cluster/util/SmartQueue.java Thu Feb 23 11:55:14 2006 @@ -0,0 +1,189 @@ +/* + * Copyright 1999,2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.cluster.util; + +/** + * A smart queue, used for async replication
+ * the "smart" part of this queue is that if the session is already queued for + * replication, and it is updated again, the session will simply be replaced, + * hence we don't replicate stuff that is obsolete. Put this into util, since it + * is quite generic. + * + * @author Filip Hanik + * @version 1.0 + */ + +import java.util.LinkedList; +import java.util.HashMap; + +public class SmartQueue { + + public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory + .getLog(SmartQueue.class); + + /** + * This is the actual queue + */ + private LinkedList queue = new LinkedList(); + + /** + * And this is only for performance, fast lookups + */ + private HashMap queueMap = new HashMap(); + + private Object mutex = new Object(); + + public SmartQueue() { + } + + /** + * Add an object to the queue + * + * @param entry - + * the smart entry + */ + public void add(SmartEntry entry) { + /* + * make sure we are within a synchronized block since we are dealing + * with two unsync collections + */ + synchronized (mutex) { + /* check to see if this object has already been queued */ + SmartEntry current = (SmartEntry) queueMap.get(entry.getKey()); + if (current == null) { + /* the object has not been queued, at it to the end of the queue */ + if (log.isDebugEnabled()) + log.debug("[" + Thread.currentThread().getName() + + "][SmartQueue] Adding new object=" + entry); + queue.addLast(entry); + queueMap.put(entry.getKey(), entry); + } else { + /* the object has been queued, replace the value */ + if (log.isDebugEnabled()) + log.debug("[" + Thread.currentThread().getName() + + "][SmartQueue] Replacing old object=" + current); + current.setValue(entry.getValue()); + if (log.isDebugEnabled()) + log.debug("with new object=" + current); + } + /* + * wake up all the threads that are waiting for the lock to be + * released + */ + mutex.notifyAll(); + } + } + + public int size() { + synchronized (mutex) { + return queue.size(); + } + } + + /** + * Blocks forever until an element has been added to the queue + */ + public SmartEntry remove() { + return remove(0); + } + + public SmartEntry remove(long timeout) { + SmartEntry result = null; + long startEntry = System.currentTimeMillis(); + synchronized (mutex) { + while (size() == 0) { + try { + if (log.isDebugEnabled()) + log + .debug("[" + + Thread.currentThread().getName() + + "][SmartQueue] Queue sleeping until object added size=" + + size() + "."); + if ((timeout != 0) + && ((System.currentTimeMillis() - startEntry) > timeout)) { + return null; + } + mutex.wait(timeout); + if (log.isDebugEnabled()) + log + .debug("[" + + Thread.currentThread().getName() + + "][SmartQueue] Queue woke up or interrupted size=" + + size() + "."); + } catch (IllegalMonitorStateException ex) { + throw ex; + } catch (InterruptedException ex) { + }//catch + }//while + /* guaranteed that we are not empty by now */ + result = (SmartEntry) queue.removeFirst(); + queueMap.remove(result.getKey()); + if (log.isDebugEnabled()) + log.debug("[" + Thread.currentThread().getName() + + "][SmartQueue] Returning=" + result); + } + return result; + } + + public static class SmartEntry { + protected Object key; + + protected Object value; + + public SmartEntry(Object key, Object value) { + if (key == null) + throw new IllegalArgumentException( + "SmartEntry key can not be null."); + if (value == null) + throw new IllegalArgumentException( + "SmartEntry value can not be null."); + this.key = key; + this.value = value; + } + + public Object getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + if (value == null) + throw new IllegalArgumentException( + "SmartEntry value can not be null."); + this.value = value; + } + + public int hashCode() { + return key.hashCode(); + } + + public boolean equals(Object o) { + if (!(o instanceof SmartEntry)) + return false; + SmartEntry other = (SmartEntry) o; + return other.getKey().equals(getKey()); + } + + public String toString() { + return "[SmartyEntry key=" + key + " value=" + value + "]"; + } + } + +} \ No newline at end of file Added: tomcat/container/tc5.5.x/modules/ha/build.xml URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/build.xml?rev=380209&view=auto ============================================================================== --- tomcat/container/tc5.5.x/modules/ha/build.xml (added) +++ tomcat/container/tc5.5.x/modules/ha/build.xml Thu Feb 23 11:55:14 2006 @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org For additional commands, e-mail: dev-help@tomcat.apache.org