--- projects/cms/source/util/uk/org/iscream/cms/util/Queue.java 2001/01/30 02:12:23 1.8 +++ projects/cms/source/util/uk/org/iscream/cms/util/Queue.java 2002/05/18 18:16:03 1.24 @@ -1,10 +1,30 @@ +/* + * i-scream central monitoring system + * Copyright (C) 2000-2002 i-scream + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + //---PACKAGE DECLARATION--- -package uk.ac.ukc.iscream.util; +package uk.org.iscream.cms.server.util; //---IMPORTS--- import java.util.LinkedList; import java.util.NoSuchElementException; -import uk.ac.ukc.iscream.util.*; +import java.util.Random; +import uk.org.iscream.cms.server.util.*; /** * A Queue class designed to operate in a multi-threaded environment, with @@ -13,7 +33,7 @@ import uk.ac.ukc.iscream.util.*; * actually contains some elements. * * @author $Author: tdb $ - * @version $Id: Queue.java,v 1.8 2001/01/30 02:12:23 tdb Exp $ + * @version $Id: Queue.java,v 1.24 2002/05/18 18:16:03 tdb Exp $ */ public class Queue { @@ -22,11 +42,64 @@ public class Queue { /** * The current CVS revision of this class */ - public static final String REVISION = "$Revision: 1.8 $"; + public static final String REVISION = "$Revision: 1.24 $"; + /** + * Pass to constructor to remove a RANDOM item from + * the Queue upon reaching the maximum limit. + */ + public static final int RANDOM = 0; + + /** + * Pass to constructor to remove the FIRST item from + * the Queue upon reaching the maximum limit. + */ + public static final int FIRST = 1; + + /** + * Pass to constructor to remove the LAST item from + * the Queue upon reaching the maximum limit. + */ + public static final int LAST = 2; + + /** + * Pass to constructor to drop the new item upon reaching + * the maximum Queue limit. + */ + public static final int DROP = 3; + + /** + * To allow opposite lookups. + */ + public static final String[] algorithms = {"RANDOM", "FIRST", "LAST", "DROP"}; + //---STATIC METHODS--- //---CONSTRUCTORS--- + + /** + * Constructs a new Queue with a maximum size limit on + * any individual queue. This should be used to stop + * conditions where the Queue cannot be guaranteed to + * be emptied as quick as it's filled. + * + * An algorithm will be used to remove data when new data + * arrives. There may be choices of algorithms later on. + * + * @param maxSize the upper limit for a queue + * @param removeAlgorithm the remove algorithm to use upon reaching the maxSize + */ + public Queue(int maxSize, int removeAlgorithm) { + _maxSize = maxSize; + _removeAlgorithm = removeAlgorithm; + } + + /** + * Constructs a Queue with no maximum size. + */ + public Queue() { + _maxSize = -1; + } //---PUBLIC METHODS--- @@ -40,17 +113,27 @@ public class Queue { for(int i=0; i < _lists.size(); i++) { // skip over any gaps left in the list if(_lists.get(i) != null) { - int s = ((LinkedList) _lists.get(i)).size(); - synchronized(this) { - // add() does the same thing, but this ensures behaviour - ((LinkedList) _lists.get(i)).addLast(o); - } - // if the queue was empty before the add it is possible - // that a consumer is waiting... so we notify them - if (s == 0) { - synchronized(((LinkedList) _lists.get(i))) { - ((LinkedList) _lists.get(i)).notifyAll(); + synchronized(((LinkedList) _lists.get(i))) { + // get size before adding to the Queue + int s = ((LinkedList) _lists.get(i)).size(); + // check whether we need to remove an item from the current Queue + if(_maxSize!=-1 && s>=_maxSize && _removeAlgorithm!=DROP) { + // we need to remove an item + removeQueueItem((LinkedList) _lists.get(i)); } + // check if we should add (not if Queue full, and using DROP algorithm) + if(!(s>=_maxSize && _removeAlgorithm==DROP)) { + // add the next item, ensuring we lock + synchronized(this) { + // LinkedList.add() does the same thing, but this ensures behaviour + ((LinkedList) _lists.get(i)).addLast(o); + } + // if the queue was empty before the add it is possible + // that a consumer is waiting... so we notify them + //synchronized(((LinkedList) _lists.get(i))) { + ((LinkedList) _lists.get(i)).notifyAll(); + //} + } } } } @@ -72,8 +155,8 @@ public class Queue { throw new InvalidQueueException("Requested queue "+queue+" does not exist"); } // block if the queue is empty - if (((LinkedList) _lists.get(queue)).size() == 0) { - synchronized(((LinkedList) _lists.get(queue))) { + synchronized(((LinkedList) _lists.get(queue))) { + if (((LinkedList) _lists.get(queue)).size() == 0) { try { ((LinkedList) _lists.get(queue)).wait(); } catch(Exception e) {} } } @@ -119,28 +202,30 @@ public class Queue { } /** - * This method returns a textual status of the queues. It - * is merely for observation, and would most likely be used - * by a larger "monitoring" component. Information returned - * includes the current size of each queue, and the total - * items passed through. + * This method returns an XML textual status of the queues. + * It is merely for observation, and would most likely be + * used by a larger "monitoring" component. Information + * returned includes the current size of each queue, and + * the total items passed through. * - * @return A String message containing status information. + * @return A String message containing status information in XML format */ - public String status() { - String status = ""; + public String xmlStatus() { + String status = "