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

# User Rev Content
1 tdb 1.19 /*
2     * i-scream central monitoring system
3 tdb 1.24 * http://www.i-scream.org
4 tdb 1.19 * 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 tdb 1.1 //---PACKAGE DECLARATION---
22 tdb 1.18 package uk.org.iscream.cms.server.clientinterface;
23 tdb 1.1
24     //---IMPORTS---
25 tdb 1.22 import uk.org.iscream.cms.util.*;
26 tdb 1.18 import uk.org.iscream.cms.server.componentmanager.*;
27     import uk.org.iscream.cms.server.core.*;
28 tdb 1.1 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 tdb 1.4 * 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 tdb 1.1 *
38 tdb 1.19 * @author $Author: tdb $
39 tdb 1.25 * @version $Id: PacketSorter.java,v 1.24 2004/08/01 10:40:48 tdb Exp $
40 tdb 1.1 */
41     class PacketSorter extends Thread {
42    
43     //---FINAL ATTRIBUTES---
44    
45     /**
46     * The current CVS revision of this class
47     */
48 tdb 1.25 public final String REVISION = "$Revision: 1.24 $";
49 tdb 1.1
50     //---STATIC METHODS---
51    
52     //---CONSTRUCTORS---
53    
54     /**
55     * Creates a new PacketSorter.
56     */
57 tdb 1.15 public PacketSorter() {
58 tdb 1.14 // set the Thread name
59     setName("clientinterface.PacketSorter");
60    
61 tdb 1.17 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 tdb 1.15 // 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 tdb 1.17 int queueMonitorInterval = Integer.parseInt(cp.getProperty(configName, "Queue.MonitorInterval"));
94 tdb 1.15 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 tdb 1.11 _hostMap = new HashMap();
101     _allHostDataList = new LinkedList();
102     _allHostsList = new LinkedList();
103 tdb 1.1 _logger.write(toString(), Logger.SYSINIT, "created");
104     }
105    
106     //---PUBLIC METHODS---
107    
108 tdb 1.4 /**
109     * Method to start the PacketSorter running. This method will
110     * loop forever processing and sending data.
111     */
112 tdb 1.1 public void run() {
113     int qID = _queue.getQueue();
114     while(true) {
115 tdb 1.4 // attempt to get some data from the Queue
116 tdb 1.1 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 tdb 1.10 XMLPacket packet = null;
125    
126     try {
127 tdb 1.21 packet = _xmlCache.getXMLPacket(xml);
128 tdb 1.10 } catch(InvalidXMLException e) {
129     _logger.write(toString(), Logger.ERROR, "Invalid XML: "+e);
130     // skip the rest of this loop iteration
131 tdb 1.25 continue;
132     }
133    
134     if(packet == null) {
135 tdb 1.10 continue;
136     }
137 tdb 1.1
138 tdb 1.8 String packetType = packet.getParam("packet.attributes.type");
139     // check if we need to send it regardless
140 tdb 1.23 if(packetType.equals("data")) {
141 tdb 1.8 String host = packet.getParam("packet.attributes.machine_name");
142    
143     // look in the hostMap to see if anyone wants this data
144 tdb 1.11 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 tdb 1.8 }
153     }
154    
155     // any handler in this list wants all packets, so send
156     // it on to them regardless
157 tdb 1.11 synchronized(this) {
158     Iterator i = _allHostDataList.iterator();
159     while(i.hasNext()) {
160     ((Queue) i.next()).add(xml);
161     }
162     }
163 tdb 1.1 }
164 tdb 1.8 else {
165 tdb 1.10 // always send this packet to all hosts, because it's
166     // "extra" data, not host data
167 tdb 1.11 synchronized(this) {
168     Iterator i = _allHostsList.iterator();
169     while(i.hasNext()) {
170     ((Queue) i.next()).add(xml);
171     }
172     }
173 tdb 1.2 }
174 tdb 1.1 }
175     }
176    
177 tdb 1.4 /**
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 tdb 1.12 public void register(Queue dhQueue, String hostList) {
191 tdb 1.4 // check to see if we want all hosts
192 tdb 1.2 if(hostList.equals("")) {
193 tdb 1.12 synchronized(this) {
194     _allHostDataList.add(dhQueue);
195     }
196 tdb 1.2 _logger.write(toString(), Logger.SYSMSG, "registered DataHandler for all hosts");
197     }
198     else {
199 tdb 1.4 // go through the list of hosts
200 tdb 1.2 StringTokenizer st = new StringTokenizer(hostList, ";");
201     while(st.hasMoreTokens()) {
202     String host = st.nextToken();
203 tdb 1.12 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 tdb 1.2 }
217 tdb 1.1 }
218 tdb 1.2 _logger.write(toString(), Logger.SYSMSG, "registered DataHandler for hosts: "+hostList);
219 tdb 1.1 }
220 tdb 1.10 // always add host to our complete host list
221 tdb 1.12 synchronized(this) {
222     _allHostsList.add(dhQueue);
223     }
224 tdb 1.1 }
225    
226 tdb 1.4 /**
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 tdb 1.12 public void deregister(Queue dhQueue, String hostList) {
238 tdb 1.4 // go through the list of hosts
239 tdb 1.2 if(hostList.equals("")) {
240 tdb 1.12 synchronized(this) {
241     _allHostDataList.remove(dhQueue);
242     }
243 tdb 1.2 _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 tdb 1.12 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 tdb 1.2 }
260 tdb 1.1 }
261     }
262 tdb 1.2 _logger.write(toString(), Logger.SYSMSG, "deregistered DataHandler for hosts: "+hostList);
263 tdb 1.1 }
264 tdb 1.10 // always remove host from our complete host list
265 tdb 1.12 synchronized(this) {
266     _allHostsList.remove(dhQueue);
267     }
268 tdb 1.1 }
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 tdb 1.22 * This uses the uk.org.iscream.cms.util.NameFormat class
275 tdb 1.1 * 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 tdb 1.4
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 tdb 1.1 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 tdb 1.4 /**
321     * A reference to the Queue we're using.
322     */
323 tdb 1.1 private Queue _queue;
324    
325 tdb 1.4 /**
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 tdb 1.11 private HashMap _hostMap;
330 tdb 1.4
331     /**
332     * A list specifically for a Queue's associated with DataHandlers
333     * that want all host information.
334 tdb 1.10 */
335 tdb 1.11 private LinkedList _allHostDataList;
336 tdb 1.10
337     /**
338     * A list of all hosts.
339 tdb 1.4 */
340 tdb 1.11 private LinkedList _allHostsList;
341 tdb 1.21
342     /**
343     * A reference to the XMLCache in use
344     */
345     private XMLCache _xmlCache = XMLCache.getInstance();
346 tdb 1.1
347     //---STATIC ATTRIBUTES---
348    
349     }