ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/util/uk/org/iscream/cms/util/Queue.java
(Generate patch)

Comparing projects/cms/source/util/uk/org/iscream/cms/util/Queue.java (file contents):
Revision 1.7 by tdb, Tue Jan 30 01:56:28 2001 UTC vs.
Revision 1.20 by tdb, Mon Mar 26 17:59:47 2001 UTC

# Line 1 | Line 1
1   //---PACKAGE DECLARATION---
2 < package uk.ac.ukc.iscream.util;
2 > package uk.org.iscream.util;
3  
4   //---IMPORTS---
5   import java.util.LinkedList;
6   import java.util.NoSuchElementException;
7 < import uk.ac.ukc.iscream.util.*;
7 > import java.util.Random;
8 > import uk.org.iscream.util.*;
9  
10   /**
11   * A Queue class designed to operate in a multi-threaded environment, with
# Line 24 | Line 25 | public class Queue {
25       */
26      public static final String REVISION = "$Revision$";
27      
28 +    /**
29 +     * Pass to constructor to remove a RANDOM item from
30 +     * the Queue upon reaching the maximum limit.
31 +     */
32 +    public static final int RANDOM = 0;
33 +    
34 +    /**
35 +     * Pass to constructor to remove the FIRST item from
36 +     * the Queue upon reaching the maximum limit.
37 +     */
38 +    public static final int FIRST = 1;
39 +    
40 +    /**
41 +     * Pass to constructor to remove the LAST item from
42 +     * the Queue upon reaching the maximum limit.
43 +     */
44 +    public static final int LAST = 2;
45 +    
46 +    /**
47 +     * Pass to constructor to drop the new item upon reaching
48 +     * the maximum Queue limit.
49 +     */
50 +    public static final int DROP = 3;
51 +    
52 +    /**
53 +     * To allow opposite lookups.
54 +     */
55 +    public static final String[] algorithms = {"RANDOM", "FIRST", "LAST", "DROP"};
56 +    
57   //---STATIC METHODS---
58  
59   //---CONSTRUCTORS---  
60 +    
61 +    /**
62 +     * Constructs a new Queue with a maximum size limit on
63 +     * any individual queue. This should be used to stop
64 +     * conditions where the Queue cannot be guaranteed to
65 +     * be emptied as quick as it's filled.
66 +     *
67 +     * An algorithm will be used to remove data when new data
68 +     * arrives. There may be choices of algorithms later on.
69 +     *
70 +     * @param maxSize the upper limit for a queue
71 +     * @param removeAlgorithm the remove algorithm to use upon reaching the maxSize
72 +     */
73 +    public Queue(int maxSize, int removeAlgorithm) {
74 +        _maxSize = maxSize;
75 +        _removeAlgorithm = removeAlgorithm;
76 +    }
77 +    
78 +    /**
79 +     * Constructs a Queue with no maximum size.
80 +     */
81 +    public Queue() {
82 +        _maxSize = -1;
83 +    }
84  
85   //---PUBLIC METHODS---
86      
# Line 40 | Line 94 | public class Queue {
94          for(int i=0; i < _lists.size(); i++) {
95              // skip over any gaps left in the list
96              if(_lists.get(i) != null) {
97 +                // get size before adding to the Queue
98                  int s = ((LinkedList) _lists.get(i)).size();
99 <                synchronized(this) {
100 <                    // add() does the same thing, but this ensures behaviour
101 <                    ((LinkedList) _lists.get(i)).addLast(o);
99 >                // check whether we need to remove an item from the current Queue
100 >                if(_maxSize!=-1 && s>=_maxSize && _removeAlgorithm!=DROP) {
101 >                    // we need to remove an item
102 >                    removeQueueItem((LinkedList) _lists.get(i));
103                  }
104 +                // check if we should add (not if Queue full, and using DROP algorithm)
105 +                if(!(s>=_maxSize && _removeAlgorithm==DROP)) {
106 +                    // add the next item, ensuring we lock
107 +                    synchronized(this) {
108 +                        // LinkedList.add() does the same thing, but this ensures behaviour
109 +                        ((LinkedList) _lists.get(i)).addLast(o);
110 +                    }
111 +                }
112                  // if the queue was empty before the add it is possible
113                  // that a consumer is waiting... so we notify them
114 <                if (s == 0) {
115 <                    synchronized(((LinkedList) _lists.get(i))) {
52 <                        ((LinkedList) _lists.get(i)).notifyAll();
53 <                    }
114 >                synchronized(((LinkedList) _lists.get(i))) {
115 >                    ((LinkedList) _lists.get(i)).notifyAll();
116                  }
117              }
118          }
# Line 62 | Line 124 | public class Queue {
124       * This method returns an object from the front of a given queue.
125       * It will block until data exists in the queue if required.
126       *
127 +     * @param The queue to retrieve data from.
128       * @return The object from the front of the queue.
129       * @throws InvalidQueueException if the queue does not exist.
130       */
# Line 71 | Line 134 | public class Queue {
134              throw new InvalidQueueException("Requested queue "+queue+" does not exist");
135          }
136          // block if the queue is empty
137 <        if (((LinkedList) _lists.get(queue)).size() == 0) {
138 <            synchronized(((LinkedList) _lists.get(queue))) {
137 >        synchronized(((LinkedList) _lists.get(queue))) {
138 >            if (((LinkedList) _lists.get(queue)).size() == 0) {
139                  try { ((LinkedList) _lists.get(queue)).wait(); } catch(Exception e) {}
140              }
141          }
# Line 95 | Line 158 | public class Queue {
158       * shutdown() type methods that may have problems closing
159       * if the thread of control is waiting on a queue.
160       *
161 <     * @param queue the queue to release
161 >     * @param queue the queue to release.
162       */
163      public void releaseQueue(int queue) {
164          synchronized(((LinkedList) _lists.get(queue))) {
# Line 118 | Line 181 | public class Queue {
181      }
182      
183      /**
184 <     * This method returns a textual status of the queues. It
185 <     * is merely for observation, and would most likely be used
186 <     * by a larger "monitoring" component. Information returned
187 <     * includes the current size of each queue, and the total
188 <     * items passed through.
184 >     * This method returns an XML textual status of the queues.
185 >     * It is merely for observation, and would most likely be
186 >     * used by a larger "monitoring" component. Information
187 >     * returned includes the current size of each queue, and
188 >     * the total items passed through.
189       *
190 <     * @return A String message containing status information.
190 >     * @return A String message containing status information in XML format
191       */
192 <    public String status() {
193 <        String status = "";
192 >    public String xmlStatus() {
193 >        String status = "<queue ";
194          for(int i=0; i < _lists.size(); i++) {
195              // check for null entries
196              if(_lists.get(i) != null) {
197 <                status += "Queue number "+i+" contains "+((LinkedList) _lists.get(i)).size()+" elements";
135 <                status += "\n";
197 >                status += "queue"+i+"=\""+((LinkedList) _lists.get(i)).size()+"\" ";
198              }
199              else {
200 <                status += "Slot number "+i+" is currently empty";
139 <                status += "\n";
200 >                status += "queue"+i+"=\"[deleted]\" ";
201              }
202          }
203 <        status += "A total of "+_count+" elements have been added to the queues";
203 >        status += "total=\""+_count+"\"";
204 >        if(_maxSize != -1) {
205 >            status += " maxSize=\""+_maxSize+"\"";
206 >        }
207 >        status += "></queue>";
208          return status;
209      }
210      
# Line 150 | Line 215 | public class Queue {
215       *
216       * @param queue The queue number to query.
217       * @return the current size of the queue.
218 +     * @throws InvalidQueueException if the queue does not exist.
219       */
220      public int queueSize(int queue) throws InvalidQueueException {
221          if (queue >= _lists.size() || _lists.get(queue) == null) {
# Line 162 | Line 228 | public class Queue {
228       * Returns the total numer of elements to have passed
229       * through this queue (ie. a counter on the add method).
230       *
231 <     * @return the element-ometer
231 >     * @return the element-ometer.
232       */
233      public int elementCount() {
234          return _count;
# Line 179 | Line 245 | public class Queue {
245       *
246       * @return An integer to be passed to the get() method.
247       */
248 <    public int getQueue() {
248 >    public synchronized int getQueue() {
249          int pos = -1;
250          for(int i=0; i < _lists.size(); i++) {
251              if(_lists.get(i) == null) {
# Line 203 | Line 269 | public class Queue {
269       *
270       * @param queue The integer identifier for the queue, given by getQueue().
271       */
272 <    public void removeQueue(int queue) {
272 >    public synchronized void removeQueue(int queue) {
273          _lists.set(queue, null);
274      }
275      
276      /**
277 +     * Start a monitor on our own Queue. This will log XML
278 +     * statistics about our Queue to a given Queue (could be
279 +     * the one being monitored).
280 +     *
281 +     * @param interval The long interval, in milliseconds, at which to take samples
282 +     * @param destQueue The queue to monitor to
283 +     * @param name A name to identify this Queue with
284 +     * @return whether we succeeded
285 +     */
286 +    public boolean startMonitor(long interval, Queue destQueue, String name) {
287 +        if(_queueMon == null) {
288 +            // start a monitor
289 +            _queueMon = new QueueMonitor(this, destQueue, interval, name);
290 +            _queueMon.start();
291 +            return true;
292 +        }
293 +        else {
294 +            // already have a monitor running
295 +            return false;
296 +        }
297 +    }
298 +    
299 +    /**
300 +     * Start a monitor on our own Queue. This will log XML
301 +     * statistics about our Queue to this Queue.
302 +     *
303 +     * @param interval The long interval, in milliseconds, at which to take samples
304 +     * @param name A name to identify this Queue with
305 +     * @return whether we succeeded
306 +     */
307 +    public boolean startMonitor(long interval, String name) {
308 +        return startMonitor(interval, this, name);
309 +    }
310 +    
311 +    /**
312 +     * Stop a monitor on our Queue if we have on running.
313 +     *
314 +     * @return whether we succeeded
315 +     */
316 +    public boolean stopMonitor() {
317 +        if(_queueMon != null) {
318 +            // stop a monitor
319 +            _queueMon.shutdown();
320 +            _queueMon = null;
321 +            return true;
322 +        }
323 +        else {
324 +            // no monitor running
325 +            return false;
326 +        }
327 +    }
328 +    
329 +    /**
330       * Overrides the {@link java.lang.Object#toString() Object.toString()}
331       * method to provide clean logging (every class should have this).
332       *
333 <     * This uses the uk.ac.ukc.iscream.util.FormatName class
333 >     * This uses the uk.org.iscream.util.FormatName class
334       * to format the toString()
335       *
336 <     * @return the name of this class and its CVS revision
336 >     * @return the name of this class and its CVS revision.
337       */
338      public String toString() {
339          return FormatName.getName(
# Line 224 | Line 343 | public class Queue {
343      }
344  
345   //---PRIVATE METHODS---
346 <
346 >    
347 >    /**
348 >     * This method removes an item from a Queue, using a method
349 >     * requested at construction.
350 >     *
351 >     * @param list The LinkedList from which to remove an item.
352 >     */
353 >    private void removeQueueItem(LinkedList list) {
354 >        // look at our algorithm
355 >        // remove a random item from the list
356 >        if(_removeAlgorithm==RANDOM) {
357 >            // new Random, with a good seed
358 >            Random rand = new Random(System.currentTimeMillis());
359 >            int i = rand.nextInt(_maxSize);
360 >            synchronized(this) {
361 >                list.remove(i);
362 >            }
363 >        }
364 >        // remove the first item from the list
365 >        else if(_removeAlgorithm==FIRST) {
366 >            synchronized(this) {
367 >                list.removeFirst();
368 >            }
369 >        }
370 >        // remove the last item from the list
371 >        else if(_removeAlgorithm==LAST) {
372 >            synchronized(this) {
373 >                list.removeLast();
374 >            }
375 >        }
376 >    }
377 >    
378   //---ACCESSOR/MUTATOR METHODS---
379  
380   //---ATTRIBUTES---
# Line 239 | Line 389 | public class Queue {
389       * passed through, for statistical purposes.
390       */
391      private int _count = 0;
392 +    
393 +    /**
394 +     * A reference to our QueueMonitor, if we have one.
395 +     */
396 +    private QueueMonitor _queueMon = null;
397 +    
398 +    /**
399 +     * The maximum size of any Queue.
400 +     */
401 +    private int _maxSize = -1;
402 +    
403 +    /**
404 +     * The remove algorithm to use upon a Queue reaching
405 +     * it's maximum size.
406 +     */
407 +    private int _removeAlgorithm = -1;
408      
409      /**
410       * This is the friendly identifier of the

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines