KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mq > server > MessageCounter


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mq.server;
23
24 import java.text.DateFormat JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Calendar JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.GregorianCalendar JavaDoc;
29
30 import org.jboss.mq.MessageStatistics;
31
32 /**
33  * This class stores message count informations for a given queue
34  *
35  * @todo The date processing has been reported as a bottleneck
36  * @author Ulf Schroeter (u.schroeter@mobilcom.de)
37  * @author Stephan Steinbacher (s.steinbacher@mobilcom.de)
38  * @version $Revision: 37459 $
39  */

40 public class MessageCounter
41 {
42    // destination related information
43
String JavaDoc destName;
44    String JavaDoc destSubscription;
45    boolean destTopic;
46    boolean destDurable;
47
48    // destination queue
49
BasicQueue destQueue;
50
51    // counter
52
int countTotal;
53    int countTotalLast;
54    int depthLast;
55    long timeLastUpdate;
56
57    // per hour day counter history
58
int dayCounterMax;
59    ArrayList JavaDoc dayCounter;
60    
61    /**
62     * Get an array of message statistics from an array of message counters
63     *
64     * @param counter the message counters
65     * @return the message statistics
66     * @throws Exception for any error
67     */

68    public static MessageStatistics[] getMessageStatistics(MessageCounter[] counter) throws Exception JavaDoc
69    {
70       MessageStatistics[] stats = new MessageStatistics[counter.length];
71       for (int i = 0; i < counter.length; ++i)
72       {
73          stats[i] = new MessageStatistics();
74          stats[i].setName(counter[i].getDestinationName());
75          stats[i].setSubscriptionID(counter[i].getDestinationSubscription());
76          stats[i].setTopic(counter[i].getDestinationTopic());
77          stats[i].setDurable(counter[i].getDestinationDurable());
78          stats[i].setCount(counter[i].getCount());
79          stats[i].setCountDelta(counter[i].getCountDelta());
80          stats[i].setDepth(counter[i].getDepth());
81          stats[i].setDepthDelta(counter[i].getDepthDelta());
82          stats[i].setTimeLastUpdate(counter[i].getLastUpdate());
83       }
84       return stats;
85    }
86
87    /**
88     * Constructor
89     *
90     * @param name destination name
91     * @param subscription subscription name
92     * @param queue internal queue object
93     * @param topic topic destination flag
94     * @param durable durable subsciption flag
95     * @param daycountmax max message history day count
96     */

97    public MessageCounter(
98       String JavaDoc name,
99       String JavaDoc subscription,
100       BasicQueue queue,
101       boolean topic,
102       boolean durable,
103       int daycountmax)
104    {
105       // store destination related information
106
destName = name;
107       destSubscription = subscription;
108       destTopic = topic;
109       destDurable = durable;
110       destQueue = queue;
111
112       // initialize counter
113
resetCounter();
114
115       // initialize message history
116
dayCounter = new ArrayList JavaDoc();
117
118       setHistoryLimit(daycountmax);
119    }
120
121    /**
122    * Get string representation
123    */

124    public String JavaDoc toString()
125    {
126       return getCounterAsString();
127    }
128
129    /**
130     * Increment message counter and update message history
131     */

132    public void incrementCounter()
133    {
134       // update message counter
135
countTotal++;
136
137       // update timestamp
138
timeLastUpdate = System.currentTimeMillis();
139
140       // update message history
141
updateHistory(true);
142    }
143
144    /**
145     * Gets the related destination name
146     *
147     * @return String destination name
148     */

149    public String JavaDoc getDestinationName()
150    {
151       return destName;
152    }
153
154    /**
155     * Gets the related destination subscription
156     *
157     * @return String destination name
158     */

159    public String JavaDoc getDestinationSubscription()
160    {
161       return destSubscription;
162    }
163
164    /**
165     * Gets the related destination topic flag
166     *
167     * @return boolean true: topic destination, false: queue destination
168     */

169    public boolean getDestinationTopic()
170    {
171       return destTopic;
172    }
173
174    /**
175     * Gets the related destination durable subscription flag
176     *
177     * @return boolean true : durable subscription,
178     * false: non-durable subscription
179     */

180    public boolean getDestinationDurable()
181    {
182       return destDurable;
183    }
184
185    /**
186     * Gets the total message count since startup or
187     * last counter reset
188     *
189     * @return int message count
190     */

191    public int getCount()
192    {
193       return countTotal;
194    }
195
196    /**
197     * Gets the message count delta since last method call
198     *
199     * @return int message count delta
200     */

201    public int getCountDelta()
202    {
203       int delta = countTotal - countTotalLast;
204
205       countTotalLast = countTotal;
206
207       return delta;
208    }
209
210    /**
211     * Gets the current message count of pending messages
212     * within the destination waiting for dispatch
213     *
214     * @return int message queue depth
215     */

216    public int getDepth()
217    {
218       return destQueue.getQueueDepth();
219    }
220
221    /**
222     * Gets the message count delta of pending messages
223     * since last method call. Therefore
224     *
225     * @return int message queue depth delta
226     */

227    public int getDepthDelta()
228    {
229       int current = destQueue.getQueueDepth();
230       int delta = current - depthLast;
231
232       depthLast = current;
233
234       return delta;
235    }
236
237    /**
238     * Gets the timestamp of the last message add
239     *
240     * @return long system time
241     */

242    public long getLastUpdate()
243    {
244       return timeLastUpdate;
245    }
246
247    /**
248     * Reset message counter values
249     */

250    public void resetCounter()
251    {
252       countTotal = 0;
253       countTotalLast = 0;
254       depthLast = 0;
255       timeLastUpdate = 0;
256    }
257
258    /**
259     * Get message counter data as string in format
260     *
261     * "Topic/Queue, Name, Subscription, Durable, Count, CountDelta,
262     * Depth, DepthDelta, Timestamp Last Increment"
263     *
264     * @return String message counter data string
265     */

266    public String JavaDoc getCounterAsString()
267    {
268       String JavaDoc ret;
269
270       // Topic/Queue
271
if (destTopic)
272          ret = "Topic,";
273       else
274          ret = "Queue,";
275
276       // name
277
ret += destName + ",";
278
279       // subscription
280
if (destSubscription != null)
281          ret += destSubscription + ",";
282       else
283          ret += "-,";
284
285       // Durable subscription
286
if (destTopic)
287       {
288          // Topic
289
if (destDurable)
290             ret += "true,";
291          else
292             ret += "false,";
293       }
294       else
295       {
296          // Queue
297
ret += "-,";
298       }
299
300       // counter values
301
ret += getCount() + "," + getCountDelta() + "," + getDepth() + "," + getDepthDelta() + ",";
302
303       // timestamp last counter update
304
if (timeLastUpdate > 0)
305       {
306          DateFormat JavaDoc dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
307
308          ret += dateFormat.format(new Date JavaDoc(timeLastUpdate));
309       }
310       else
311       {
312          ret += "-";
313       }
314
315       return ret;
316    }
317
318    /**
319     * Get message counter history day count limit
320     *
321     * <0: unlimited, 0: history disabled, >0: day count
322     */

323    public int getHistoryLimit()
324    {
325       return dayCounterMax;
326    }
327
328    /**
329     * Set message counter history day count limit
330     *
331     * <0: unlimited, 0: history disabled, >0: day count
332     */

333    public void setHistoryLimit(int daycountmax)
334    {
335       boolean bInitialize = false;
336
337       // store new maximum day count
338
dayCounterMax = daycountmax;
339
340       // update day counter array
341
synchronized (dayCounter)
342       {
343          if (dayCounterMax > 0)
344          {
345             // limit day history to specified day count
346
int delta = dayCounter.size() - dayCounterMax;
347
348             for (int i = 0; i < delta; i++)
349             {
350                // reduce array size to requested size by dropping
351
// oldest day counters
352
dayCounter.remove(0);
353             }
354
355             // create initial day counter when empty
356
bInitialize = dayCounter.isEmpty();
357          }
358          else if (dayCounterMax == 0)
359          {
360             // disable history
361
dayCounter.clear();
362          }
363          else
364          {
365             // unlimited day history
366

367             // create initial day counter when empty
368
bInitialize = dayCounter.isEmpty();
369          }
370
371          // optionally initialize first day counter entry
372
if (bInitialize)
373          {
374             dayCounter.add(new DayCounter(new GregorianCalendar JavaDoc(), true));
375          }
376       }
377    }
378
379    /**
380     * Update message counter history
381     */

382    private void updateHistory(boolean incrementCounter)
383    {
384       // check history activation
385
if (dayCounter.isEmpty())
386       {
387          return;
388       }
389
390       // calculate day difference between current date and date of last day counter entry
391
synchronized (dayCounter)
392       {
393          DayCounter counterLast = (DayCounter) dayCounter.get(dayCounter.size() - 1);
394
395          GregorianCalendar JavaDoc calNow = new GregorianCalendar JavaDoc();
396          GregorianCalendar JavaDoc calLast = counterLast.getDate();
397
398          // clip day time part for day delta calulation
399
calNow.clear(Calendar.AM_PM);
400          calNow.clear(Calendar.HOUR);
401          calNow.clear(Calendar.HOUR_OF_DAY);
402          calNow.clear(Calendar.MINUTE);
403          calNow.clear(Calendar.SECOND);
404          calNow.clear(Calendar.MILLISECOND);
405
406          calLast.clear(Calendar.AM_PM);
407          calLast.clear(Calendar.HOUR);
408          calLast.clear(Calendar.HOUR_OF_DAY);
409          calLast.clear(Calendar.MINUTE);
410          calLast.clear(Calendar.SECOND);
411          calLast.clear(Calendar.MILLISECOND);
412
413          long millisPerDay = 86400000; // 24 * 60 * 60 * 1000
414
long millisDelta = calNow.getTime().getTime() - calLast.getTime().getTime();
415
416          int dayDelta = (int) (millisDelta / millisPerDay);
417
418          if (dayDelta > 0)
419          {
420             // finalize last day counter
421
counterLast.finalizeDayCounter();
422
423             // add new intermediate empty day counter entries
424
DayCounter counterNew;
425
426             for (int i = 1; i < dayDelta; i++)
427             {
428                // increment date
429
calLast.add(Calendar.DAY_OF_YEAR, 1);
430
431                counterNew = new DayCounter(calLast, false);
432                counterNew.finalizeDayCounter();
433
434                dayCounter.add(counterNew);
435             }
436
437             // add new day counter entry for current day
438
counterNew = new DayCounter(calNow, false);
439
440             dayCounter.add(counterNew);
441
442             // ensure history day count limit
443
setHistoryLimit(dayCounterMax);
444          }
445
446          // update last day counter entry
447
counterLast = (DayCounter) dayCounter.get(dayCounter.size() - 1);
448          counterLast.updateDayCounter(incrementCounter);
449       }
450    }
451
452    /**
453     * Reset message counter history
454     */

455    public void resetHistory()
456    {
457       int max = dayCounterMax;
458
459       setHistoryLimit(0);
460       setHistoryLimit(max);
461    }
462
463    /**
464     * Get message counter history data as string in format
465     *
466     * "day count\n
467     * Date 1, hour counter 0, hour counter 1, ..., hour counter 23\n
468     * Date 2, hour counter 0, hour counter 1, ..., hour counter 23\n
469     * .....
470     * .....
471     * Date n, hour counter 0, hour counter 1, ..., hour counter 23\n"
472     *
473     * @return String message history data string
474     */

475    public String JavaDoc getHistoryAsString()
476    {
477       String JavaDoc ret = "";
478
479       // ensure history counters are up to date
480
updateHistory(false);
481
482       // compile string
483
synchronized (dayCounter)
484       {
485          // first line: history day count
486
ret += dayCounter.size() + "\n";
487
488          // following lines: day counter data
489
for (int i = 0; i < dayCounter.size(); i++)
490          {
491             DayCounter counter = (DayCounter) dayCounter.get(i);
492
493             ret += counter.getDayCounterAsString() + "\n";
494          }
495       }
496
497       return ret;
498    }
499
500    /**
501     * Internal day counter class for one day hour based counter history
502     */

503    static class DayCounter
504    {
505       static final int HOURS = 24;
506
507       GregorianCalendar JavaDoc date = null;
508       int[] counters = new int[HOURS];
509
510       /**
511        * Constructor
512        *
513        * @param date day counter date
514        * @param isStartDay true first day counter
515        * false follow up day counter
516        */

517       DayCounter(GregorianCalendar JavaDoc date, boolean isStartDay)
518       {
519          // store internal copy of creation date
520
this.date = (GregorianCalendar JavaDoc) date.clone();
521
522          // initialize the array with '0'- values to current hour (if it is not the
523
// first monitored day) and the rest with default values ('-1')
524
int hour = date.get(Calendar.HOUR_OF_DAY);
525
526          for (int i = 0; i < HOURS; i++)
527          {
528             if (i < hour)
529             {
530                if (isStartDay)
531                   counters[i] = -1;
532                else
533                   counters[i] = 0;
534             }
535             else
536             {
537                counters[i] = -1;
538             }
539          }
540
541          // set the array element of the current hour to '0'
542
counters[hour] = 0;
543       }
544
545       /**
546        * Gets copy of day counter date
547        *
548        * @return GregorianCalendar day counter date
549        */

550       GregorianCalendar JavaDoc getDate()
551       {
552          return (GregorianCalendar JavaDoc) date.clone();
553       }
554
555       /**
556        * Update day counter hour array elements
557        *
558        * @param incrementCounter update current hour counter
559        */

560       void updateDayCounter(boolean incrementCounter)
561       {
562          // get the current hour of the day
563
GregorianCalendar JavaDoc cal = new GregorianCalendar JavaDoc();
564
565          int currentIndex = cal.get(Calendar.HOUR_OF_DAY);
566
567          // check if the last array update is more than 1 hour ago, if so fill all
568
// array elements between the last index and the current index with '0' values
569
boolean bUpdate = false;
570
571          for (int i = 0; i <= currentIndex; i++)
572          {
573             if (counters[i] > -1)
574             {
575                // found first initialized hour counter
576
// -> set all following uninitialized
577
// counter values to 0
578
bUpdate = true;
579             }
580
581             if (bUpdate == true)
582             {
583                if (counters[i] == -1)
584                   counters[i] = 0;
585             }
586          }
587
588          // optionally increment current counter
589
if (incrementCounter)
590          {
591             counters[currentIndex]++;
592          }
593       }
594
595       /**
596        * Finalize day counter hour array elements
597        */

598       void finalizeDayCounter()
599       {
600          // a new day has began, so fill all array elements from index to end with
601
// '0' values
602
boolean bFinalize = false;
603
604          for (int i = 0; i < HOURS; i++)
605          {
606             if (counters[i] > -1)
607             {
608                // found first initialized hour counter
609
// -> finalize all following uninitialized
610
// counter values
611
bFinalize = true;
612             }
613
614             if (bFinalize)
615             {
616                if (counters[i] == -1)
617                   counters[i] = 0;
618             }
619          }
620       }
621
622       /**
623        * Return day counter data as string with format
624        * "Date, hour counter 0, hour counter 1, ..., hour counter 23"
625        *
626        * @return String day counter data
627        */

628       String JavaDoc getDayCounterAsString()
629       {
630          // first element day counter date
631
DateFormat JavaDoc dateFormat = DateFormat.getDateInstance(DateFormat.SHORT);
632
633          String JavaDoc strData = dateFormat.format(date.getTime());
634
635          // append 24 comma separated hour counter values
636
for (int i = 0; i < HOURS; i++)
637          {
638             strData += "," + counters[i];
639          }
640
641          return strData;
642       }
643    }
644 }
645
Popular Tags