KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > monitor > alarm > AlarmTable


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.monitor.alarm;
23
24 import java.util.Collection JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.LinkedHashMap JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import javax.management.Notification JavaDoc;
30 import javax.management.ObjectName JavaDoc;
31
32 import org.jboss.system.ServiceMBeanSupport;
33
34 import EDU.oswego.cs.dl.util.concurrent.SynchronizedLong;
35
36 /**
37  * AlarmTable
38  *
39  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
40  * @version $Revision: 37459 $
41  */

42 public class AlarmTable
43 {
44    // Private/Protected Data ----------------------------------------
45

46    /** Mediates the related MBean */
47    protected MBeanImplAccess mbeanImpl;
48    
49    /** The serverId to use when producing AlarmTableNotification alarmIds */
50    private String JavaDoc serverId;
51    
52    /** Counter the help produce unique ids: serverId-alarmIdCount */
53    private SynchronizedLong alarmIdCount;
54    
55    /** The active alarm table, maps AlarmId(String) -> AlarmTableNotification */
56    private Map JavaDoc alarmMap;
57    
58    /** Maps AlarmKey -> AlarmId(String), for stateful alarms */
59    private Map JavaDoc statefulMap;
60
61    /** Maximum number of entries to keep */
62    private int maxSize = -1;
63    
64    // Constructors --------------------------------------------------
65

66    /**
67     * CTOR
68     */

69    public AlarmTable(MBeanImplAccess mbeanImpl)
70    {
71       this.mbeanImpl = mbeanImpl;
72       this.alarmIdCount = new SynchronizedLong(0);
73       this.alarmMap = new LinkedHashMap JavaDoc();
74       this.statefulMap = new HashMap JavaDoc();
75    }
76    
77    /**
78     * CTOR
79     *
80     * @param service hosting the AlarmManager
81     */

82    public AlarmTable(final ServiceMBeanSupport service)
83    {
84       this(new MBeanImplAccess() {
85          public ObjectName JavaDoc getMBeanName() { return service.getServiceName(); }
86          public long getSequenceNumber() { return service.nextNotificationSequenceNumber(); }
87          public void emitNotification(Notification JavaDoc n) { service.sendNotification(n); }
88       });
89    }
90    
91    // AlarmTable Implementation -------------------------------------
92

93    /**
94     * Sets the serverId
95     */

96    public void setServerId(String JavaDoc serverId)
97    {
98       this.serverId = serverId;
99    }
100    
101    /**
102     * Gets the serverId
103     */

104    public String JavaDoc getServerId()
105    {
106       return serverId;
107    }
108
109    /**
110     * Sets the maximum number of entries to keep
111     * -1 equals to no limit.
112     */

113    public void setMaxSize(int maxSize)
114    {
115       this.maxSize = maxSize;
116    }
117
118    /**
119     * Gets the maximum number of entries to keep
120     */

121    public int getMaxSize()
122    {
123       return maxSize;
124    }
125    
126    /**
127     * Update the AlarmTable based on the incoming Notification
128     */

129    public void update(Notification JavaDoc n)
130    {
131       if (n instanceof AlarmTableNotification)
132       {
133          // ignore - those notification are
134
// meant to be produced only by me
135
}
136       else if (n instanceof AlarmNotification)
137       {
138          AlarmNotification an = (AlarmNotification)n;
139          
140          if (an.getAlarmState() == Alarm.STATE_NONE)
141          {
142             updateNotificationStateless(n, an.getSeverity());
143          }
144          else
145          {
146             updateNotificationStatefull(an);
147          }
148       }
149       else
150       {
151          updateNotificationStateless(n, Alarm.SEVERITY_UNKNOWN);
152       }
153    }
154
155    /**
156     * Acknowledge an Alarm
157     *
158     * @return true if ack was succesful, false otherwise
159     * (not in table or acked already)
160     */

161    public boolean acknowledge(String JavaDoc alarmId, String JavaDoc user, String JavaDoc system)
162    {
163       AlarmTableNotification atn;
164       
165       synchronized (this)
166       {
167          AlarmTableNotification entry =
168             (AlarmTableNotification)alarmMap.get(alarmId);
169          
170          if (entry == null || entry.getAckState() == true)
171          {
172             return false; // ack failed
173
}
174          // ack the alarm
175
entry.setAckParams(true, System.currentTimeMillis(), user, system);
176          
177          // prepare the AlarmTableNotification to send
178
atn = new AlarmTableNotification(entry);
179          
180          // this is a new notification
181
atn.setSequenceNumber(mbeanImpl.getSequenceNumber());
182          atn.setTimeStamp(System.currentTimeMillis());
183          
184          // if alarm Stateless or Statefull but Cleared, remove from table
185
int alarmState = entry.getAlarmState();
186          if (alarmState == Alarm.STATE_NONE || alarmState == Alarm.STATE_CLEARED)
187          {
188             alarmMap.remove(alarmId);
189          }
190       }
191       // send the AlarmTableNotification
192
mbeanImpl.emitNotification(atn);
193       
194       return true; // ok
195
}
196
197    /**
198     * Unacknowledge an Alarm
199     *
200     * @return true if unack was succesful, false otherwise
201     * (not in table or unacked already)
202     */

203    public boolean unacknowledge(String JavaDoc alarmId, String JavaDoc user, String JavaDoc system)
204    {
205       AlarmTableNotification atn;
206       
207       synchronized (this)
208       {
209          AlarmTableNotification entry =
210             (AlarmTableNotification)alarmMap.get(alarmId);
211          
212          if (entry == null || entry.getAckState() == false)
213          {
214             return false; // unack failed
215
}
216          // unack the alarm
217
entry.setAckParams(false, System.currentTimeMillis(), user, system);
218          
219          // prepare the AlarmTableNotification to send
220
atn = new AlarmTableNotification(entry);
221          
222          // this is a new notification
223
atn.setSequenceNumber(mbeanImpl.getSequenceNumber());
224          atn.setTimeStamp(System.currentTimeMillis());
225       }
226       // send the AlarmTableNotification
227
mbeanImpl.emitNotification(atn);
228       
229       return true; // ok
230
}
231    
232    /**
233     * Gets a copy of the AlarmTable
234     */

235    public AlarmTableNotification[] getAlarmTable()
236    {
237       // this syncronized deep copy is quite expensive
238
synchronized (this)
239       {
240          Collection JavaDoc alarms = alarmMap.values();
241          AlarmTableNotification[] array = new AlarmTableNotification[alarms.size()];
242          return (AlarmTableNotification[])alarms.toArray(array);
243       }
244    }
245    
246    /**
247     * Gets the number of entries in the table
248     */

249    public int getAlarmSize()
250    {
251       synchronized(this)
252       {
253          return alarmMap.size();
254       }
255    }
256    
257    // Private Methods -----------------------------------------------
258

259    /**
260     * Since this is stateful, first check if there is already
261     * an entry in the stateful alarm map, then update both maps.
262     */

263    private void updateNotificationStatefull(AlarmNotification an)
264    {
265       int alarmState = an.getAlarmState();
266       int severity = an.getSeverity();
267       
268       // Create a key based on source+type
269
Object JavaDoc alarmKey = AlarmNotification.createKey(an);
270       
271       AlarmTableNotification atn;
272       
273       // Check if this stateful alarm is already stored
274
synchronized (this)
275       {
276          String JavaDoc alarmId = (String JavaDoc)statefulMap.get(alarmKey);
277          if (alarmId == null)
278          {
279             // the stateful alarm is not known
280
if (isMaxSizeReached())
281             {
282                // return if table is full
283
return;
284             }
285             else
286             {
287                // generate a new Id, if not found
288
alarmId = generateAlarmId();
289             }
290          }
291          // create an AlarmTableNotification
292
atn = new AlarmTableNotification(
293                   alarmId,
294                   AlarmTableNotification.ALARM_TABLE_UPDATE,
295                   this.mbeanImpl.getMBeanName(),
296                   null,
297                   severity,
298                   alarmState,
299                   this.mbeanImpl.getSequenceNumber(),
300                   System.currentTimeMillis(),
301                   null
302             );
303          
304          // store a reference to the original notification
305
atn.setUserData(an);
306       
307          // need to check if acked already, in which case
308
// we must copy the ack data to the new AlarmTableNotification
309
// and remove the entry from the table
310
if (alarmState == Alarm.STATE_CLEARED)
311          {
312             AlarmTableNotification entry =
313                (AlarmTableNotification)alarmMap.get(alarmId);
314             
315             if (entry != null && entry.getAckState() == true)
316             {
317                statefulMap.remove(alarmKey);
318                alarmMap.remove(alarmId);
319                
320                atn.setAckParams(true, entry.getAckTime(),
321                                 entry.getAckUser(), entry.getAckSystem());
322             }
323             else
324             {
325                // just add it
326
statefulMap.put(alarmKey, alarmId);
327                alarmMap.put(alarmId, atn);
328             }
329          }
330          else
331          {
332             // just add it
333
statefulMap.put(alarmKey, alarmId);
334             alarmMap.put(alarmId, atn);
335          }
336       }
337       // the only case to be acked is when it is not stored in table
338
// in which case send the new AlarmTableNotification itself
339
if (atn.getAckState() == true)
340       {
341          mbeanImpl.emitNotification(atn);
342       }
343       else // send a copy away
344
{
345          mbeanImpl.emitNotification(new AlarmTableNotification(atn));
346       }
347    }
348    
349    /**
350     * Store the notification in the active alarm map.
351     */

352    private void updateNotificationStateless(Notification JavaDoc n, int severity)
353    {
354       synchronized (this)
355       {
356          if (isMaxSizeReached())
357          {
358             // can't hold no more alarms
359
return;
360          }
361       }
362       // create an AlarmTableNotification
363
AlarmTableNotification atn =
364          new AlarmTableNotification(
365             generateAlarmId(),
366             AlarmTableNotification.ALARM_TABLE_UPDATE,
367             this.mbeanImpl.getMBeanName(),
368             null,
369             severity,
370             Alarm.STATE_NONE,
371             this.mbeanImpl.getSequenceNumber(),
372             System.currentTimeMillis(),
373             null
374          );
375       // store a reference to the original notification
376
atn.setUserData(n);
377       
378       // store the AlarmTableNotification - this is always a new entry
379
synchronized (this)
380       {
381          alarmMap.put(atn.getAlarmId(), atn);
382       }
383       
384       // send a copy away
385
mbeanImpl.emitNotification(new AlarmTableNotification(atn));
386    }
387    
388    /**
389     * Generate a (hopefully) unique alarmId
390     */

391    private String JavaDoc generateAlarmId()
392    {
393       return serverId + '-' + alarmIdCount.increment();
394    }
395    
396    /**
397     * Check if table is full
398     */

399    private boolean isMaxSizeReached()
400    {
401       if (maxSize != -1)
402       {
403          return (alarmMap.size() >= maxSize) ? true : false;
404       }
405       else
406       {
407          return false;
408       }
409    }
410 }
411
Popular Tags