ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/clientinterface/PacketSorter.java
Revision: 1.25
Committed: Wed Dec 8 14:50:32 2004 UTC (19 years, 5 months ago) by tdb
Branch: MAIN
Changes since 1.24: +6 -2 lines
Log Message:
Check packet isn't null. Another one of those "shouldn't happen but did"
things ;-)

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2002 i-scream
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 //---PACKAGE DECLARATION---
22 package uk.org.iscream.cms.server.clientinterface;
23
24 //---IMPORTS---
25 import uk.org.iscream.cms.util.*;
26 import uk.org.iscream.cms.server.componentmanager.*;
27 import uk.org.iscream.cms.server.core.*;
28 import java.util.*;
29
30 /**
31 * Receives data from the incoming CORBA servant, places
32 * it in a Queue, and then arranges distribution to the
33 * DataHandlers.
34 * Has extra functionality to send data to DataHandlers
35 * on a per-host basis - ie. the Client can request which
36 * hosts it would like to listen for.
37 *
38 * @author $Author: tdb $
39 * @version $Id: PacketSorter.java,v 1.24 2004/08/01 10:40:48 tdb Exp $
40 */
41 class PacketSorter extends Thread {
42
43 //---FINAL ATTRIBUTES---
44
45 /**
46 * The current CVS revision of this class
47 */
48 public final String REVISION = "$Revision: 1.24 $";
49
50 //---STATIC METHODS---
51
52 //---CONSTRUCTORS---
53
54 /**
55 * Creates a new PacketSorter.
56 */
57 public PacketSorter() {
58 // set the Thread name
59 setName("clientinterface.PacketSorter");
60
61 ConfigurationProxy cp = ConfigurationProxy.getInstance();
62 String configName = "ClientInterface";
63
64 // see if this Queue needs a size limit
65 try {
66 int queueSizeLimit = Integer.parseInt(cp.getProperty(configName, "Queue.SizeLimit"));
67 String queueRemoveAlgorithm = cp.getProperty(configName, "Queue.RemoveAlgorithm");
68 int algorithm = StringUtils.getStringPos(queueRemoveAlgorithm, Queue.algorithms);
69 if(algorithm != -1) {
70 _logger.write(toString(), Logger.DEBUG, "Starting Queue with size limit of "+queueSizeLimit+", using remove algorithm "+queueRemoveAlgorithm);
71 // we have valid values, so lets start it.
72 _queue = new Queue(queueSizeLimit, algorithm);
73 }
74 else {
75 _logger.write(toString(), Logger.WARNING, "Bad Queue Algorithm configuration, not known: "+queueRemoveAlgorithm);
76 // just don't activate a limit
77 _queue = new Queue();
78 }
79
80 } catch (PropertyNotFoundException e) {
81 _logger.write(toString(), Logger.DEBUG, "Optional config not set: "+e);
82 // just don't activate a limit
83 _queue = new Queue();
84 } catch (NumberFormatException e) {
85 _logger.write(toString(), Logger.WARNING, "Bad Queue SizeLimit configuration: "+e);
86 // just don't activate a limit
87 _queue = new Queue();
88 }
89
90 // startup a monitor on this queue
91 try {
92 // try to get the interval, if this fails, we won't start up the monitor
93 int queueMonitorInterval = Integer.parseInt(cp.getProperty(configName, "Queue.MonitorInterval"));
94 String queueName = _name + " PacketSorterQueue";
95 _queue.startMonitor(queueMonitorInterval*1000, queueName);
96 } catch (PropertyNotFoundException e) {
97 _logger.write(toString(), Logger.WARNING, "failed to find queue monitor config, disabling. " + e);
98 }
99
100 _hostMap = new HashMap();
101 _allHostDataList = new LinkedList();
102 _allHostsList = new LinkedList();
103 _logger.write(toString(), Logger.SYSINIT, "created");
104 }
105
106 //---PUBLIC METHODS---
107
108 /**
109 * Method to start the PacketSorter running. This method will
110 * loop forever processing and sending data.
111 */
112 public void run() {
113 int qID = _queue.getQueue();
114 while(true) {
115 // attempt to get some data from the Queue
116 String xml = "";
117 try {
118 xml = (String) _queue.get(qID);
119 }
120 catch(InvalidQueueException e) {
121 _logger.write(toString(), Logger.ERROR, "Queue failure: "+e);
122 }
123
124 XMLPacket packet = null;
125
126 try {
127 packet = _xmlCache.getXMLPacket(xml);
128 } catch(InvalidXMLException e) {
129 _logger.write(toString(), Logger.ERROR, "Invalid XML: "+e);
130 // skip the rest of this loop iteration
131 continue;
132 }
133
134 if(packet == null) {
135 continue;
136 }
137
138 String packetType = packet.getParam("packet.attributes.type");
139 // check if we need to send it regardless
140 if(packetType.equals("data")) {
141 String host = packet.getParam("packet.attributes.machine_name");
142
143 // look in the hostMap to see if anyone wants this data
144 synchronized(this) {
145 if(_hostMap.containsKey(host)) {
146 LinkedList list = (LinkedList) _hostMap.get(host);
147 Iterator i = list.iterator();
148 // push the data to the listening Handler's queue
149 while(i.hasNext()) {
150 ((Queue) i.next()).add(xml);
151 }
152 }
153 }
154
155 // any handler in this list wants all packets, so send
156 // it on to them regardless
157 synchronized(this) {
158 Iterator i = _allHostDataList.iterator();
159 while(i.hasNext()) {
160 ((Queue) i.next()).add(xml);
161 }
162 }
163 }
164 else {
165 // always send this packet to all hosts, because it's
166 // "extra" data, not host data
167 synchronized(this) {
168 Iterator i = _allHostsList.iterator();
169 while(i.hasNext()) {
170 ((Queue) i.next()).add(xml);
171 }
172 }
173 }
174 }
175 }
176
177 /**
178 * Register a DataHandler in the system. This method
179 * actually takes a reference to a Queue, which should be
180 * a Queue that the DataHandler is making use of.
181 * It also takes a hostList, this being a semi-colon
182 * seperated list of hosts that the Client the DataHandler
183 * is serving has requested. If this list is simply an empty
184 * String, it is assumed the Client wants to listen to all
185 * host information.
186 *
187 * @param dhQueue a Queue being used by the DataHandler that is registering
188 * @param hostList a semi-colon seperated list of hosts
189 */
190 public void register(Queue dhQueue, String hostList) {
191 // check to see if we want all hosts
192 if(hostList.equals("")) {
193 synchronized(this) {
194 _allHostDataList.add(dhQueue);
195 }
196 _logger.write(toString(), Logger.SYSMSG, "registered DataHandler for all hosts");
197 }
198 else {
199 // go through the list of hosts
200 StringTokenizer st = new StringTokenizer(hostList, ";");
201 while(st.hasMoreTokens()) {
202 String host = st.nextToken();
203 synchronized(this) {
204 // see if we already have a list in the map for this host
205 if(_hostMap.containsKey(host)) {
206 // we do, so add to it
207 List list = (List) _hostMap.get(host);
208 list.add(dhQueue);
209 }
210 else {
211 // we don't, so create a list and put it in the map
212 LinkedList list = new LinkedList();
213 list.add(dhQueue);
214 _hostMap.put(host, list);
215 }
216 }
217 }
218 _logger.write(toString(), Logger.SYSMSG, "registered DataHandler for hosts: "+hostList);
219 }
220 // always add host to our complete host list
221 synchronized(this) {
222 _allHostsList.add(dhQueue);
223 }
224 }
225
226 /**
227 * Deregister a DataHandler. The DataHandler should give a reference
228 * to the Queue it's using, and the *same* hostList it gave when it
229 * register. It is imperative that the hostList is the same, otherwise
230 * there will be all sorts of problems with lists getting out of sync.
231 *
232 * NB: Possible future addition would be recording of hostList's.
233 *
234 * @param dhQueue a Queue being used by the DataHandler that is deregistering
235 * @param hostList a semi-colon seperated list of hosts
236 */
237 public void deregister(Queue dhQueue, String hostList) {
238 // go through the list of hosts
239 if(hostList.equals("")) {
240 synchronized(this) {
241 _allHostDataList.remove(dhQueue);
242 }
243 _logger.write(toString(), Logger.SYSMSG, "deregistered DataHandler for all hosts");
244 }
245 else {
246 StringTokenizer st = new StringTokenizer(hostList, ";");
247 while(st.hasMoreTokens()) {
248 String host = st.nextToken();
249 synchronized(this) {
250 // this should in reality always be true, but best check
251 if(_hostMap.containsKey(host)) {
252 // get the list and remove the host in question
253 LinkedList list = (LinkedList) _hostMap.get(host);
254 list.remove(dhQueue);
255 // if the list is now empty, we might as well remove it
256 if(list.size()==0) {
257 _hostMap.remove(host);
258 }
259 }
260 }
261 }
262 _logger.write(toString(), Logger.SYSMSG, "deregistered DataHandler for hosts: "+hostList);
263 }
264 // always remove host from our complete host list
265 synchronized(this) {
266 _allHostsList.remove(dhQueue);
267 }
268 }
269
270 /**
271 * Overrides the {@link java.lang.Object#toString() Object.toString()}
272 * method to provide clean logging (every class should have this).
273 *
274 * This uses the uk.org.iscream.cms.util.NameFormat class
275 * to format the toString()
276 *
277 * @return the name of this class and its CVS revision
278 */
279 public String toString() {
280 return FormatName.getName(
281 _name,
282 getClass().getName(),
283 REVISION);
284 }
285
286 //---PRIVATE METHODS---
287
288 //---ACCESSOR/MUTATOR METHODS---
289
290 /**
291 * Accessor to return a reference to the Queue object. This
292 * is needed so the ClientInterfaceServant can get add data
293 * easily.
294 *
295 * @return a reference to our Queue object.
296 */
297 public Queue getQueue() {
298 return _queue;
299 }
300
301 //---ATTRIBUTES---
302
303 /**
304 * This is the friendly identifier of the
305 * component this class is running in.
306 * eg, a Filter may be called "filter1",
307 * If this class does not have an owning
308 * component, a name from the configuration
309 * can be placed here. This name could also
310 * be changed to null for utility classes.
311 */
312 private String _name = ClientInterfaceMain.NAME;
313
314 /**
315 * This holds a reference to the
316 * system logger that is being used.
317 */
318 private Logger _logger = ReferenceManager.getInstance().getLogger();
319
320 /**
321 * A reference to the Queue we're using.
322 */
323 private Queue _queue;
324
325 /**
326 * A HashMap to store lists of Queue's (in the DataHandlers)
327 * in a way that can be easily accessed when data comes in.
328 */
329 private HashMap _hostMap;
330
331 /**
332 * A list specifically for a Queue's associated with DataHandlers
333 * that want all host information.
334 */
335 private LinkedList _allHostDataList;
336
337 /**
338 * A list of all hosts.
339 */
340 private LinkedList _allHostsList;
341
342 /**
343 * A reference to the XMLCache in use
344 */
345 private XMLCache _xmlCache = XMLCache.getInstance();
346
347 //---STATIC ATTRIBUTES---
348
349 }