1 |
|
//---PACKAGE DECLARATION--- |
2 |
< |
package uk.org.iscream.client; |
2 |
> |
package uk.org.iscream.cms.server.client; |
3 |
|
|
4 |
|
//---IMPORTS--- |
5 |
< |
import uk.org.iscream.componentmanager.*; |
6 |
< |
import uk.org.iscream.core.*; |
7 |
< |
import uk.org.iscream.util.*; |
5 |
> |
import uk.org.iscream.cms.server.componentmanager.*; |
6 |
> |
import uk.org.iscream.cms.server.core.*; |
7 |
> |
import uk.org.iscream.cms.server.util.*; |
8 |
|
import java.io.*; |
9 |
|
|
10 |
|
/** |
11 |
|
* Provides a feed to the webpage system. |
12 |
|
* |
13 |
– |
* !! There may also be need to have a Thread to grab any |
14 |
– |
* !! required config (groups, "nice names, etc) and dump |
15 |
– |
* !! that to a file. |
16 |
– |
* |
13 |
|
* @author $Author$ |
14 |
|
* @version $Id$ |
15 |
|
*/ |
32 |
|
*/ |
33 |
|
public final int DEFAULT_AGE = 3600; |
34 |
|
|
35 |
+ |
/** |
36 |
+ |
* The default path seperator, here for convienience |
37 |
+ |
*/ |
38 |
+ |
private final String sep = File.separator; |
39 |
+ |
|
40 |
|
//---STATIC METHODS--- |
41 |
|
|
42 |
|
/** |
43 |
|
* Return a reference to the single class. |
44 |
|
* Construct it if it does not already exist, otherwise just return the reference. |
45 |
|
*/ |
46 |
< |
public static WebFeeder getInstance() { |
46 |
> |
public synchronized static WebFeeder getInstance() { |
47 |
|
if (_instance == null){ |
48 |
|
_instance = new WebFeeder(); |
49 |
|
} |
70 |
|
// work out where things are |
71 |
|
rootPath = cp.getProperty("WebFeeder", "WebFeeder.rootPath"); |
72 |
|
alertSubDir = cp.getProperty("WebFeeder", "WebFeeder.alertSubDir"); |
73 |
< |
File alertsDir = new File(rootPath+"/"+alertSubDir); |
73 |
> |
File alertsDir = new File(rootPath, alertSubDir); |
74 |
|
if(deleteContents(alertsDir)) { |
75 |
< |
_logger.write(this.toString(), Logger.DEBUG, "Deleted all files and directories from: "+rootPath+"/"+alertSubDir); |
75 |
> |
_logger.write(this.toString(), Logger.DEBUG, "Deleted all files and directories from: "+rootPath+sep+alertSubDir); |
76 |
|
} else { |
77 |
< |
_logger.write(this.toString(), Logger.WARNING, "Failed to delete all files and directories from: "+rootPath+"/"+alertSubDir); |
77 |
> |
_logger.write(this.toString(), Logger.WARNING, "Failed to delete all files and directories from: "+rootPath+sep+alertSubDir); |
78 |
|
} |
79 |
|
// cleanup complete |
80 |
|
} catch (PropertyNotFoundException e) { |
142 |
|
_logger.write(toString(), Logger.WARNING, "WebFeeder.alertDeleteOlderThan value unavailable using default of " + deleteOlderThan + " seconds"); |
143 |
|
} |
144 |
|
|
145 |
< |
// list the files |
146 |
< |
String alertsPath = rootPath+"/"+alertSubDir; |
147 |
< |
File alertsDir = new File(alertsPath); |
145 |
> |
// list the files and delete as appropriate |
146 |
> |
File alertsDir = new File(rootPath, alertSubDir); |
147 |
> |
// get all the hostnames directories |
148 |
|
File[] contents = alertsDir.listFiles(); |
149 |
|
for(int i=0; i < contents.length; i++) { |
150 |
+ |
// get a single directory from the array.. |
151 |
|
File hostdir = contents[i]; |
152 |
< |
File[] hostdirContents = hostdir.listFiles(); |
153 |
< |
for(int j=0; j < hostdirContents.length; j++) { |
154 |
< |
File alertFile = hostdirContents[j]; |
155 |
< |
String filename = alertFile.getName(); |
156 |
< |
if(filename.endsWith(Alert.alertLevels[0]) || |
157 |
< |
filename.endsWith(Alert.alertLevels[Alert.alertLevels.length-1])) { |
158 |
< |
// it ends with either OK or FINAL |
159 |
< |
// ... so we can check it for deletion |
160 |
< |
long lastModified = alertFile.lastModified(); |
161 |
< |
long age = System.currentTimeMillis() - lastModified; |
162 |
< |
if(age > ((long) deleteOlderThan*1000)) { |
163 |
< |
// it's also older than our age to delete older than |
164 |
< |
if(!alertFile.delete()) { |
165 |
< |
_logger.write(this.toString(), Logger.WARNING, "Failed to delete the following 'old' alert file: "+alertFile.getPath()); |
152 |
> |
// ..and check it's a directory |
153 |
> |
if(hostdir.isDirectory()) { |
154 |
> |
// if this is set, we clean files older than it |
155 |
> |
long deleteFiles = -1; |
156 |
> |
// get all the contents of that directory |
157 |
> |
File[] hostdirContents = hostdir.listFiles(); |
158 |
> |
for(int j=0; j < hostdirContents.length; j++) { |
159 |
> |
File alertFile = hostdirContents[j]; |
160 |
> |
// get the filename.. |
161 |
> |
String filename = alertFile.getName(); |
162 |
> |
// ..and see if it ends with OK or FINAL |
163 |
> |
if(filename.endsWith(Alert.alertLevels[0]) || |
164 |
> |
filename.endsWith(Alert.alertLevels[Alert.alertLevels.length-1])) { |
165 |
> |
// it does end with either OK or FINAL |
166 |
> |
// ... so we can check it for deletion |
167 |
> |
long lastModified = alertFile.lastModified(); |
168 |
> |
long age = System.currentTimeMillis() - lastModified; |
169 |
> |
if(age > ((long) deleteOlderThan*1000)) { |
170 |
> |
// if we're on a final heartbeat, we probably want to |
171 |
> |
// clean up any stale alerts left behind |
172 |
> |
// by setting this flag, we'll clean them up on leaving this loop |
173 |
> |
if(filename.endsWith(".HB."+Alert.alertLevels[Alert.alertLevels.length-1])) { |
174 |
> |
// we do this so that delete files is set to the |
175 |
> |
// latest date of a HB.FINAL. There should only be |
176 |
> |
// one of them though :) |
177 |
> |
if(lastModified > deleteFiles) { |
178 |
> |
deleteFiles = lastModified; |
179 |
> |
} |
180 |
> |
} |
181 |
> |
// it's also older than our age to delete older than |
182 |
> |
if(!alertFile.delete()) { |
183 |
> |
_logger.write(this.toString(), Logger.WARNING, "Failed to delete the following 'old' alert file: "+alertFile.getPath()); |
184 |
> |
} |
185 |
|
} |
186 |
|
} |
187 |
|
} |
188 |
+ |
// cleanup stale alerts |
189 |
+ |
if(deleteFiles >= 0) { |
190 |
+ |
File[] remainingHostdirContents = hostdir.listFiles(); |
191 |
+ |
for(int j=0; j < remainingHostdirContents.length; j++) { |
192 |
+ |
File alertFile = remainingHostdirContents[j]; |
193 |
+ |
if(alertFile.lastModified() < deleteFiles) { |
194 |
+ |
// alert file is older than the most recent |
195 |
+ |
// FINAL Heartbeat alert. |
196 |
+ |
if(alertFile.delete()) { |
197 |
+ |
_logger.write(this.toString(), Logger.DEBUG, "Deleted stale alert file: "+alertFile.getPath()); |
198 |
+ |
} |
199 |
+ |
else { |
200 |
+ |
_logger.write(this.toString(), Logger.WARNING, "Failed to delete the following 'stale' alert file: "+alertFile.getPath()); |
201 |
+ |
} |
202 |
+ |
} |
203 |
+ |
} |
204 |
+ |
} |
205 |
+ |
// ---- RECAP ---- |
206 |
+ |
// at this point, we have cleaned up any OK or FINAL alerts |
207 |
+ |
// that have passed our age limit. We have then cleaned up |
208 |
+ |
// any alerts older the most recent Heartbeat FINAL alert, |
209 |
+ |
// as these are probably stale. Any files left are valid and |
210 |
+ |
// active alerts. We are now in a position to remove the host |
211 |
+ |
// directory if it's empty. |
212 |
+ |
// --------------- |
213 |
+ |
// do a quick check to see if the directory is now empty |
214 |
+ |
File[] newHostdirContents = hostdir.listFiles(); |
215 |
+ |
if(newHostdirContents.length == 0) { |
216 |
+ |
// it does seem to be, try and delete it |
217 |
+ |
// this will fail anyway if files still remain |
218 |
+ |
if(!hostdir.delete()) { |
219 |
+ |
_logger.write(this.toString(), Logger.WARNING, "Failed to delete the following empty host directory: "+hostdir.getPath()); |
220 |
+ |
} |
221 |
+ |
} |
222 |
|
} |
223 |
|
} |
169 |
– |
// check through, deleting those passed the age barrier |
224 |
|
} |
225 |
|
} |
226 |
|
|
254 |
|
String data = packet.printAll(); |
255 |
|
String hostname = packet.getParam("packet.attributes.machine_name"); |
256 |
|
// set paths |
257 |
< |
String destDir = rootPath+"/"+latestSubDir+"/"+hostname; |
258 |
< |
File outDir = new File(destDir); |
205 |
< |
String destFile = destDir+"/"+latestFileName; |
206 |
< |
File outFile = new File(destFile); |
257 |
> |
File outDir = new File(rootPath, latestSubDir+sep+hostname); |
258 |
> |
File outFile = new File(rootPath, latestSubDir+sep+hostname+sep+latestFileName); |
259 |
|
// write the data out |
260 |
|
writeData(outDir, outFile, data); |
261 |
|
} |
284 |
|
String data = alert.printAll(); |
285 |
|
String hostname = alert.getSource(); |
286 |
|
// set paths |
287 |
< |
String destDir = rootPath+"/"+alertSubDir+"/"+hostname; |
288 |
< |
File outDir = new File(destDir); |
237 |
< |
String destFile = destDir+"/"+alertFileName+"."+String.valueOf(alert.getInitialAlertTime()); |
287 |
> |
File outDir = new File(rootPath, alertSubDir+sep+hostname); |
288 |
> |
String destFile = alertSubDir+sep+hostname+sep+alertFileName+"."+String.valueOf(alert.getInitialAlertTime()); |
289 |
|
File outFile; |
290 |
|
// check if we're at a special "end case" (OK or FINAL) |
291 |
|
if(alert.getLevel()==0 || alert.getLevel()==Alert.alertLevels.length-1) { |
292 |
< |
File oldFile = new File(destFile); |
293 |
< |
outFile = new File(destFile+"."+Alert.alertLevels[alert.getLevel()]); |
292 |
> |
if(alert.getAttributeName().equals("Heartbeat") && alert.getLevel()==Alert.alertLevels.length-1) { |
293 |
> |
// new file is something like alert.nnnnnnnn.HB.FINAL |
294 |
> |
outFile = new File(rootPath, destFile+".HB."+Alert.alertLevels[alert.getLevel()]); |
295 |
> |
} else { |
296 |
> |
// new file is something like alert.nnnnnnnn.OK |
297 |
> |
outFile = new File(rootPath, destFile+"."+Alert.alertLevels[alert.getLevel()]); |
298 |
> |
} |
299 |
> |
File oldFile = new File(rootPath, destFile); |
300 |
|
if(!oldFile.renameTo(outFile)) { |
301 |
|
_logger.write(this.toString(), Logger.WARNING, "Failed to rename old file, "+oldFile.getPath()+" to new file, "+outFile.getPath()); |
302 |
|
} |
303 |
|
} else { |
304 |
< |
outFile = new File(destFile); |
304 |
> |
outFile = new File(rootPath, destFile); |
305 |
|
} |
306 |
|
// write the data out |
307 |
|
writeData(outDir, outFile, data); |
311 |
|
* Overrides the {@link java.lang.Object#toString() Object.toString()} |
312 |
|
* method to provide clean logging (every class should have this). |
313 |
|
* |
314 |
< |
* This uses the uk.org.iscream.util.FormatName class |
314 |
> |
* This uses the uk.org.iscream.cms.server.util.FormatName class |
315 |
|
* to format the toString() |
316 |
|
* |
317 |
|
* @return the name of this class and its CVS revision |