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.6 by tdb, Tue Jan 23 18:22:28 2001 UTC vs.
Revision 1.22 by tdb, Tue May 29 17:02:35 2001 UTC

# Line 1 | Line 1
1   //---PACKAGE DECLARATION---
2 < package uk.ac.ukc.iscream.util;
2 > package uk.org.iscream.cms.server.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.cms.server.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 <                int s = ((LinkedList) _lists.get(i)).size();
98 <                synchronized(this) {
99 <                    // add() does the same thing, but this ensures behaviour
100 <                    ((LinkedList) _lists.get(i)).addLast(o);
101 <                }
102 <                // if the queue was empty before the add it is possible
103 <                // that a consumer is waiting... so we notify them
50 <                if (s == 0) {
51 <                    synchronized(((LinkedList) _lists.get(i))) {
52 <                        ((LinkedList) _lists.get(i)).notifyAll();
97 >                synchronized(((LinkedList) _lists.get(i))) {
98 >                    // get size before adding to the Queue
99 >                    int s = ((LinkedList) _lists.get(i)).size();
100 >                    // check whether we need to remove an item from the current Queue
101 >                    if(_maxSize!=-1 && s>=_maxSize && _removeAlgorithm!=DROP) {
102 >                        // we need to remove an item
103 >                        removeQueueItem((LinkedList) _lists.get(i));
104                      }
105 +                    // check if we should add (not if Queue full, and using DROP algorithm)
106 +                    if(!(s>=_maxSize && _removeAlgorithm==DROP)) {
107 +                        // add the next item, ensuring we lock
108 +                        synchronized(this) {
109 +                            // LinkedList.add() does the same thing, but this ensures behaviour
110 +                            ((LinkedList) _lists.get(i)).addLast(o);
111 +                        }
112 +                        // if the queue was empty before the add it is possible
113 +                        // that a consumer is waiting... so we notify them
114 +                        //synchronized(((LinkedList) _lists.get(i))) {
115 +                            ((LinkedList) _lists.get(i)).notifyAll();
116 +                        //}
117 +                    }
118                  }
119              }
120          }
# Line 62 | Line 126 | public class Queue {
126       * This method returns an object from the front of a given queue.
127       * It will block until data exists in the queue if required.
128       *
129 +     * @param The queue to retrieve data from.
130       * @return The object from the front of the queue.
131       * @throws InvalidQueueException if the queue does not exist.
132       */
# Line 71 | Line 136 | public class Queue {
136              throw new InvalidQueueException("Requested queue "+queue+" does not exist");
137          }
138          // block if the queue is empty
139 <        if (((LinkedList) _lists.get(queue)).size() == 0) {
140 <            synchronized(((LinkedList) _lists.get(queue))) {
139 >        synchronized(((LinkedList) _lists.get(queue))) {
140 >            if (((LinkedList) _lists.get(queue)).size() == 0) {
141                  try { ((LinkedList) _lists.get(queue)).wait(); } catch(Exception e) {}
142              }
143          }
# Line 95 | Line 160 | public class Queue {
160       * shutdown() type methods that may have problems closing
161       * if the thread of control is waiting on a queue.
162       *
163 <     * @param queue the queue to release
163 >     * @param queue the queue to release.
164       */
165      public void releaseQueue(int queue) {
166          synchronized(((LinkedList) _lists.get(queue))) {
167                  ((LinkedList) _lists.get(queue)).notifyAll();
168          }
169      }
170 +
171 +    /**
172 +     * This method erases the contents of a given queue. This
173 +     * method should be used with care. It can only empty one
174 +     * internal queue, not all of them. This must be called
175 +     * multiple times to empty all queues.
176 +     *
177 +     * @param queue the queue to empty.
178 +     */
179 +    public void clearQueue(int queue) {
180 +        synchronized(this) {
181 +            ((LinkedList) _lists.get(queue)).clear();
182 +        }
183 +    }
184      
185      /**
186 <     * This method returns a textual status of the queues. It
187 <     * is merely for observation, and would most likely be used
188 <     * by a larger "monitoring" component. Information returned
189 <     * includes the current size of each queue, and the total
190 <     * items passed through.
186 >     * This method returns an XML textual status of the queues.
187 >     * It is merely for observation, and would most likely be
188 >     * used by a larger "monitoring" component. Information
189 >     * returned includes the current size of each queue, and
190 >     * the total items passed through.
191       *
192 <     * @return A String message containing status information.
192 >     * @return A String message containing status information in XML format
193       */
194 <    public String status() {
195 <        String status = "";
194 >    public String xmlStatus() {
195 >        String status = "<queue ";
196          for(int i=0; i < _lists.size(); i++) {
197              // check for null entries
198              if(_lists.get(i) != null) {
199 <                status += "Queue number "+i+" contains "+((LinkedList) _lists.get(i)).size()+" elements";
121 <                status += "\n";
199 >                status += "queue"+i+"=\""+((LinkedList) _lists.get(i)).size()+"\" ";
200              }
201              else {
202 <                status += "Slot number "+i+" is currently empty";
125 <                status += "\n";
202 >                status += "queue"+i+"=\"[deleted]\" ";
203              }
204          }
205 <        status += "A total of "+_count+" elements have been added to the queues";
205 >        status += "total=\""+_count+"\"";
206 >        if(_maxSize != -1) {
207 >            status += " maxSize=\""+_maxSize+"\"";
208 >        }
209 >        status += "></queue>";
210          return status;
211      }
212      
# Line 136 | Line 217 | public class Queue {
217       *
218       * @param queue The queue number to query.
219       * @return the current size of the queue.
220 +     * @throws InvalidQueueException if the queue does not exist.
221       */
222      public int queueSize(int queue) throws InvalidQueueException {
223          if (queue >= _lists.size() || _lists.get(queue) == null) {
# Line 148 | Line 230 | public class Queue {
230       * Returns the total numer of elements to have passed
231       * through this queue (ie. a counter on the add method).
232       *
233 <     * @return the element-ometer
233 >     * @return the element-ometer.
234       */
235      public int elementCount() {
236          return _count;
# Line 165 | Line 247 | public class Queue {
247       *
248       * @return An integer to be passed to the get() method.
249       */
250 <    public int getQueue() {
250 >    public synchronized int getQueue() {
251          int pos = -1;
252          for(int i=0; i < _lists.size(); i++) {
253              if(_lists.get(i) == null) {
# Line 189 | Line 271 | public class Queue {
271       *
272       * @param queue The integer identifier for the queue, given by getQueue().
273       */
274 <    public void removeQueue(int queue) {
274 >    public synchronized void removeQueue(int queue) {
275          _lists.set(queue, null);
276      }
277      
278      /**
279 +     * Start a monitor on our own Queue. This will log XML
280 +     * statistics about our Queue to a given Queue (could be
281 +     * the one being monitored).
282 +     *
283 +     * @param interval The long interval, in milliseconds, at which to take samples
284 +     * @param destQueue The queue to monitor to
285 +     * @param name A name to identify this Queue with
286 +     * @return whether we succeeded
287 +     */
288 +    public boolean startMonitor(long interval, Queue destQueue, String name) {
289 +        if(_queueMon == null) {
290 +            // start a monitor
291 +            _queueMon = new QueueMonitor(this, destQueue, interval, name);
292 +            _queueMon.start();
293 +            return true;
294 +        }
295 +        else {
296 +            // already have a monitor running
297 +            return false;
298 +        }
299 +    }
300 +    
301 +    /**
302 +     * Start a monitor on our own Queue. This will log XML
303 +     * statistics about our Queue to this Queue.
304 +     *
305 +     * @param interval The long interval, in milliseconds, at which to take samples
306 +     * @param name A name to identify this Queue with
307 +     * @return whether we succeeded
308 +     */
309 +    public boolean startMonitor(long interval, String name) {
310 +        return startMonitor(interval, this, name);
311 +    }
312 +    
313 +    /**
314 +     * Stop a monitor on our Queue if we have on running.
315 +     *
316 +     * @return whether we succeeded
317 +     */
318 +    public boolean stopMonitor() {
319 +        if(_queueMon != null) {
320 +            // stop a monitor
321 +            _queueMon.shutdown();
322 +            _queueMon = null;
323 +            return true;
324 +        }
325 +        else {
326 +            // no monitor running
327 +            return false;
328 +        }
329 +    }
330 +    
331 +    /**
332       * Overrides the {@link java.lang.Object#toString() Object.toString()}
333       * method to provide clean logging (every class should have this).
334       *
335 <     * This uses the uk.ac.ukc.iscream.util.FormatName class
335 >     * This uses the uk.org.iscream.cms.server.util.FormatName class
336       * to format the toString()
337       *
338 <     * @return the name of this class and its CVS revision
338 >     * @return the name of this class and its CVS revision.
339       */
340      public String toString() {
341          return FormatName.getName(
# Line 210 | Line 345 | public class Queue {
345      }
346  
347   //---PRIVATE METHODS---
348 <
348 >    
349 >    /**
350 >     * This method removes an item from a Queue, using a method
351 >     * requested at construction.
352 >     *
353 >     * @param list The LinkedList from which to remove an item.
354 >     */
355 >    private void removeQueueItem(LinkedList list) {
356 >        // look at our algorithm
357 >        // remove a random item from the list
358 >        if(_removeAlgorithm==RANDOM) {
359 >            // new Random, with a good seed
360 >            Random rand = new Random(System.currentTimeMillis());
361 >            int i = rand.nextInt(_maxSize);
362 >            synchronized(this) {
363 >                list.remove(i);
364 >            }
365 >        }
366 >        // remove the first item from the list
367 >        else if(_removeAlgorithm==FIRST) {
368 >            synchronized(this) {
369 >                list.removeFirst();
370 >            }
371 >        }
372 >        // remove the last item from the list
373 >        else if(_removeAlgorithm==LAST) {
374 >            synchronized(this) {
375 >                list.removeLast();
376 >            }
377 >        }
378 >    }
379 >    
380   //---ACCESSOR/MUTATOR METHODS---
381  
382   //---ATTRIBUTES---
# Line 225 | Line 391 | public class Queue {
391       * passed through, for statistical purposes.
392       */
393      private int _count = 0;
394 +    
395 +    /**
396 +     * A reference to our QueueMonitor, if we have one.
397 +     */
398 +    private QueueMonitor _queueMon = null;
399 +    
400 +    /**
401 +     * The maximum size of any Queue.
402 +     */
403 +    private int _maxSize = -1;
404 +    
405 +    /**
406 +     * The remove algorithm to use upon a Queue reaching
407 +     * it's maximum size.
408 +     */
409 +    private int _removeAlgorithm = -1;
410      
411      /**
412       * This is the friendly identifier of the

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines