|
From: <ian...@us...> - 2007-11-15 02:59:30
|
Revision: 582
http://ogoglio.svn.sourceforge.net/ogoglio/?rev=582&view=rev
Author: iansmith
Date: 2007-11-14 18:59:34 -0800 (Wed, 14 Nov 2007)
Log Message:
-----------
Added some support for getting status information from a server running on linux. This is installed in /og/status and /og/status/all to get information about a cluster. You can use the parameter "?format=xml" or "?format=human" to control which output you want.
The servlet remembers the last ten status updates and shows you these in the results.
It tries to be smart about "clusters of one machine."
Modified Paths:
--------------
maven/trunk/ogoglio-common/src/main/java/com/ogoglio/xml/ServiceDocument.java
maven/trunk/ogoglio-integration-test/src/test/java/com/ogoglio/client/test/ClientTest.java
maven/trunk/ogoglio-server/src/main/java/com/ogoglio/media/MediaService.java
maven/trunk/ogoglio-server/src/main/webapp/WEB-INF/web.xml
Added Paths:
-----------
maven/trunk/ogoglio-server/src/main/java/com/ogoglio/site/StatusServlet.java
Modified: maven/trunk/ogoglio-common/src/main/java/com/ogoglio/xml/ServiceDocument.java
===================================================================
--- maven/trunk/ogoglio-common/src/main/java/com/ogoglio/xml/ServiceDocument.java 2007-11-14 21:17:12 UTC (rev 581)
+++ maven/trunk/ogoglio-common/src/main/java/com/ogoglio/xml/ServiceDocument.java 2007-11-15 02:59:34 UTC (rev 582)
@@ -1,5 +1,8 @@
package com.ogoglio.xml;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+
import nanoxml.XMLElement;
public class ServiceDocument {
@@ -16,8 +19,18 @@
data = new XMLElement(NAME);
data.setAttribute(USER_COUNT, userCount);
data.setAttribute(SIM_COUNT, simCount);
+
+ data.addChild(getMemoryChild());
}
+ public XMLElement getMemoryChild() {
+ MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
+ XMLElement result= new XMLElement("memory");
+ result.setAttribute("heapMemoryUsage", memoryBean.getHeapMemoryUsage());
+ result.setAttribute("nonHeapMemoryUsage", memoryBean.getNonHeapMemoryUsage());
+ return result;
+ }
+
public ServiceDocument(XMLElement data) {
if (!NAME.equals(data.getName())) {
throw new IllegalArgumentException("data is not named " + NAME + ": " + data);
Modified: maven/trunk/ogoglio-integration-test/src/test/java/com/ogoglio/client/test/ClientTest.java
===================================================================
--- maven/trunk/ogoglio-integration-test/src/test/java/com/ogoglio/client/test/ClientTest.java 2007-11-14 21:17:12 UTC (rev 581)
+++ maven/trunk/ogoglio-integration-test/src/test/java/com/ogoglio/client/test/ClientTest.java 2007-11-15 02:59:34 UTC (rev 582)
@@ -21,6 +21,7 @@
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
@@ -50,6 +51,7 @@
import com.ogoglio.client.model.Thing;
import com.ogoglio.client.model.User;
import com.ogoglio.util.Log;
+import com.ogoglio.util.OgoglioSpecBase;
import com.ogoglio.util.PropStorage;
import com.ogoglio.util.StreamUtils;
import com.ogoglio.util.UIConstants;
@@ -70,6 +72,7 @@
import com.ogoglio.xml.TemplateSupportFileDocument;
import com.ogoglio.xml.ThingDocument;
import com.ogoglio.xml.UserDocument;
+import com.sun.corba.se.impl.javax.rmi.CORBA.Util;
import com.sun.org.apache.xalan.internal.xsltc.compiler.Template;
public class ClientTest extends TestCase {
@@ -968,6 +971,50 @@
return newTemplateDoc;
}
+ private XMLElement getStatusXML() throws IOException, URISyntaxException {
+ InputStream s=new URI(serviceURI1.toString()+"status?format=xml").toURL().openConnection().getInputStream();
+ XMLElement result=XMLElement.parseElementFromString(StreamUtils.readInput(s));
+ s.close();
+ return result;
+ }
+
+ public void testStatus() throws IOException, URISyntaxException {
+ try {
+
+ InputStream forEffect=new URI(serviceURI1.toString()+"status?clear=true").toURL().openConnection().getInputStream();
+ forEffect.close();
+
+ //it's pretty hard to know what *should* be in the status message unless you dummy
+ //up a bunch of stuff in /proc ....this test, thus, is very weak
+
+ checkStatusReportChildren(1);
+
+ getStatusXML();
+ getStatusXML();
+
+ checkStatusReportChildren(4);
+
+ forEffect=new URI(serviceURI1.toString()+"status?clear=true").toURL().openConnection().getInputStream();
+ forEffect.close();
+
+ checkStatusReportChildren(1);//make sure clear works and wasn't lucky above
+
+
+ } catch (IOException e) {
+ if (e.getMessage().startsWith("Server returned HTTP response code: 412")) {
+ Log.info("Ignoring response code 412 for status URL. You probably aren't on linux.");
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ private XMLElement checkStatusReportChildren(int n) throws IOException, URISyntaxException {
+ XMLElement element=getStatusXML();
+ assertEquals(element.getName(),"statusreports");
+ assertEquals(n,element.getChildren().size());
+ return element;
+ }
private void assertStreamsEqual(InputStream input1, InputStream input2) throws IOException {
if(input1 == null || input2 == null){
fail("Not equal, null inputs: " + input1 + ", " + input2);
@@ -1181,5 +1228,4 @@
}
}
-
}
Modified: maven/trunk/ogoglio-server/src/main/java/com/ogoglio/media/MediaService.java
===================================================================
--- maven/trunk/ogoglio-server/src/main/java/com/ogoglio/media/MediaService.java 2007-11-14 21:17:12 UTC (rev 581)
+++ maven/trunk/ogoglio-server/src/main/java/com/ogoglio/media/MediaService.java 2007-11-15 02:59:34 UTC (rev 582)
@@ -39,6 +39,7 @@
private static final String BODY_TEXTURE_PREFIX = "bodyTexture-";
private MediaStore store = null;
+ private URI mediaURI;
public MediaService(URI mediaURI) throws IOException {
ArgumentUtils.assertNotNull(mediaURI);
@@ -50,8 +51,12 @@
} else {
throw new IllegalStateException("Could not create a store for " + mediaURI + " with scheme " + mediaURI.getScheme());
}
+ this.mediaURI=mediaURI;
}
+ public URI getMediaURI() {
+ return mediaURI;
+ }
public static String getTemplateScriptName(long templateID) {
return MediaService.TEMPLATE_SCRIPT_PREFIX + templateID + MediaService.TEMPLATE_SCRIPT_SUFFIX;
}
Added: maven/trunk/ogoglio-server/src/main/java/com/ogoglio/site/StatusServlet.java
===================================================================
--- maven/trunk/ogoglio-server/src/main/java/com/ogoglio/site/StatusServlet.java (rev 0)
+++ maven/trunk/ogoglio-server/src/main/java/com/ogoglio/site/StatusServlet.java 2007-11-15 02:59:34 UTC (rev 582)
@@ -0,0 +1,615 @@
+package com.ogoglio.site;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URL;
+import java.sql.Time;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import nanoxml.XMLElement;
+
+import com.ogoglio.appdev.persist.PersistException;
+import com.ogoglio.appdev.servlet.SiteResource;
+import com.ogoglio.persist.SimPersistTasks;
+import com.ogoglio.persist.SimRecord;
+import com.ogoglio.util.Log;
+import com.ogoglio.util.NetworkUtils;
+import com.ogoglio.util.StreamUtils;
+
+public class StatusServlet extends OgoglioServletBase {
+
+ private List recentChecks = new ArrayList();
+
+ private static final int MAX_RECENT_CHECKS = 10;
+
+ public SiteResource createBaseResource(ServletConfig servletConfig) {
+ return new StatusResource();
+ }
+
+ private class FSData {
+ public String root;
+
+ public double size;
+
+ public double used;
+
+ public double available;
+
+ public double percentAvailable() {
+ return available / size * 100.0;
+ }
+
+ public double percentUsed() {
+ return used / size * 100.0;
+ }
+
+ public FSData deepCopy() {
+ FSData result = new FSData();
+ result.size = size;
+ result.root = root;
+ result.used = used;
+ result.available = available;
+ return result;
+ }
+ }
+
+ private class StatusData {
+ public long timestamp;
+
+ public double load_1min;
+
+ public double load_5min;
+
+ public double load_15min;
+
+ public int totalMemory_kb;
+
+ public int freeMemory_kb;
+
+ public double memPercentAvail;
+
+ public FSData[] fs;
+
+ public double netIn_mb;
+
+ public double netOut_mb;
+
+ public int userCount;
+
+ public int simCount;
+
+ public StatusData deepCopy() {
+ StatusData result = new StatusData();
+ result.timestamp = timestamp;
+ result.load_1min = load_1min;
+ result.load_5min = load_5min;
+ result.load_15min = load_15min;
+ result.totalMemory_kb = totalMemory_kb;
+ result.freeMemory_kb = freeMemory_kb;
+ result.memPercentAvail = memPercentAvail;
+ result.fs = new FSData[fs.length];
+ result.netIn_mb = netIn_mb;
+ result.netOut_mb = netOut_mb;
+ result.userCount = userCount;
+ result.simCount = simCount;
+ for (int i = 0; i < fs.length; ++i) {
+ result.fs[i] = fs[i].deepCopy();
+ }
+ return result;
+ }
+ }
+
+ private String frontDoorGetText(String uri,String suffix) throws IOException {
+ InputStream s = new URL(uri + suffix).openConnection().getInputStream();
+ String result = StreamUtils.readInput(s);
+ s.close();
+ return result;
+ }
+
+ private XMLElement frontDoorGetXML(String uri,String suffix) throws IOException {
+ InputStream s = new URL(uri + suffix).openConnection().getInputStream();
+ XMLElement result = XMLElement.parseElementFromString(StreamUtils.readInput(s));
+ s.close();
+ return result;
+ }
+
+ private boolean shouldBeHumanReadable(HttpServletRequest request) {
+ String format = request.getParameter("format");
+ if ((format == null) || (format.equalsIgnoreCase("human"))) {
+ return true;
+ }
+ return false;
+ }
+
+ private class StatusResource extends SiteResource {
+
+ private static final String NETWORK_OUT_MB = "out";
+
+ private static final String NETWORK_IN_MB = "in";
+
+ public static final String NETWORK = "network";
+
+ public static final String AVAILABLE_FS_GB = "available";
+
+ public static final String PERCENT_USED_FS = "percentUsed";
+
+ public static final String USED_FS_GB = "used";
+
+ public static final String SIZE_FS_GB = "size";
+
+ public static final String ROOT_OF_FS = "root";
+
+ public static final String FILESYSTEM = "filesystem";
+
+ public static final String FILESYSTEMS = "filesystems";
+
+ public static final String FREE_MEM_KB = "free";
+
+ public static final String TOTAL_MEM_KB = "total";
+
+ public static final String MEMORY = "memory";
+
+ public static final String MIN_15 = "min15";
+
+ public static final String MIN_5 = "min5";
+
+ public static final String MIN_1 = "min1";
+
+ public static final String LOADAVERAGE = "loadaverage";
+
+ public static final String STATUSREPORT = "statusreport";
+
+ public static final String STATUSREPORTS = "statusreports";
+
+ private static final String PERCENT_AVAILABLE_MEM = "available";
+
+ public StatusResource() {
+ super("status");
+ addSubResource(new AllStatusResource());
+ }
+
+ public void doGet(HttpServletRequest request, HttpServletResponse response, String[] pathElements) throws ServletException, IOException {
+ if (!haveSlashProc()) {
+ response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
+ return;
+ }
+
+ //maybe trying to clear out the history?
+ if (request.getParameter("clear") != null) {
+ synchronized (recentChecks) {
+ recentChecks.clear();
+ }
+ response.setStatus(HttpServletResponse.SC_OK);
+ return;
+ }
+
+ try {
+ StatusData data = computeCurrentStatus();
+ List copy = new ArrayList();
+ addCurrentStatusToListAndCopy(data, copy);
+
+ StringBuffer buffer = new StringBuffer();
+ String type;
+ if (shouldBeHumanReadable(request)) {
+ formatForHuman(buffer, copy);
+ type = "text/plain";
+ } else {
+ formatXML(buffer, copy);
+ type = "text/xml";
+ }
+ sendStringResponse(buffer.toString(), type, response);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } catch (IOException e) {
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ Log.error("Trying to read the load average!", e);
+ }
+
+ }
+
+ private void addCurrentStatusToListAndCopy(StatusData data, List copy) {
+ synchronized (recentChecks) {
+ if (recentChecks.size() == MAX_RECENT_CHECKS) {
+ recentChecks.remove(0);
+ }
+ recentChecks.add(data);
+ for (int i = 0; i < recentChecks.size(); ++i) {
+ copy.add(((StatusData) recentChecks.get(i)).deepCopy());
+ }
+ }
+ }
+
+ private StatusData computeCurrentStatus() throws IOException {
+ StatusData data = new StatusData();
+ data.timestamp = System.currentTimeMillis();
+
+ getLoadAvg(data);
+ getMemoryInfo(data);
+ getDiskAvailable(data);
+ getNetworkInfo(data);
+ addSpaceInfo(data);
+ return data;
+ }
+
+ private void addSpaceInfo(StatusData data) throws IOException {
+ XMLElement space = frontDoorGetXML(getBaseUrl(),"space");
+ data.simCount = space.getIntAttribute("simcount");
+ data.userCount = space.getIntAttribute("usercount");
+
+ }
+
+ private void formatXML(StringBuffer buffer, List copy) {
+ XMLElement root = new XMLElement();
+ root.setName(STATUSREPORTS);
+ for (int i = copy.size() - 1; i >= 0; --i) {
+ XMLElement status = new XMLElement();
+ status.setName(STATUSREPORT);
+ StatusData sd = (StatusData) copy.get(i);
+ status.setAttribute("time", sd.timestamp);
+
+ XMLElement load = new XMLElement();
+ load.setName(LOADAVERAGE);
+ load.setAttribute(MIN_1, sd.load_1min);
+ load.setAttribute(MIN_5, sd.load_5min);
+ load.setAttribute(MIN_15, sd.load_15min);
+ status.addChild(load);
+
+ XMLElement memory = new XMLElement();
+ memory.setName(MEMORY);
+ memory.setAttribute(TOTAL_MEM_KB, sd.totalMemory_kb);
+ memory.setAttribute(FREE_MEM_KB, sd.freeMemory_kb);
+ memory.setAttribute(PERCENT_AVAILABLE_MEM, sd.memPercentAvail);
+ status.addChild(memory);
+
+ XMLElement filesystems = new XMLElement();
+ filesystems.setName(FILESYSTEMS);
+ for (int j = 0; j < sd.fs.length; ++j) {
+ XMLElement fs = new XMLElement();
+ fs.setName(FILESYSTEM);
+ fs.setAttribute(ROOT_OF_FS, sd.fs[j].root);
+ fs.setAttribute(SIZE_FS_GB, sd.fs[j].size);
+ fs.setAttribute(AVAILABLE_FS_GB, sd.fs[j].available);
+ fs.setAttribute(USED_FS_GB, sd.fs[j].used);
+ fs.setAttribute(PERCENT_USED_FS, sd.fs[j].percentUsed());
+ filesystems.addChild(fs);
+ }
+ status.addChild(filesystems);
+
+ XMLElement network = new XMLElement();
+ network.setName(NETWORK);
+ network.setAttribute(NETWORK_IN_MB, sd.netIn_mb);
+ network.setAttribute(NETWORK_OUT_MB, sd.netIn_mb);
+ status.addChild(network);
+
+ root.addChild(status);
+ }
+ buffer.append(root.toString());
+ }
+
+ private void formatForHuman(StringBuffer buffer, List copy) {
+ for (int i = copy.size() - 1; i >= 0; --i) {
+ StatusData sd = (StatusData) copy.get(i);
+ buffer.append("Time:" + new Time(sd.timestamp).toString() + "\n");
+ buffer.append("load average 1 min:" + sd.load_1min + "\n");
+ buffer.append("load average 5 min:" + sd.load_5min + "\n");
+ buffer.append("load average 15 min:" + sd.load_15min + "\n");
+
+ String per = "" + sd.memPercentAvail;
+
+ buffer.append("Total memory (kB) :" + sd.totalMemory_kb + "\n");
+ buffer.append("Free memory (kB) :" + sd.freeMemory_kb + "\n");
+ buffer.append("Available :" + per.substring(0, 5) + "% (approximately free + cache)\n");
+ buffer.append("Network in (mB) :" + sd.netIn_mb + "\n");
+ buffer.append("Network out (mB) :" + sd.netOut_mb + "\n");
+ if (i > 0) {
+ StatusData prev = (StatusData) copy.get(i - 1);
+ double inDiff = sd.netIn_mb - prev.netIn_mb;
+ double outDiff = sd.netOut_mb - prev.netOut_mb;
+ double timeDiff = (sd.timestamp - prev.timestamp) / 1000.0;
+ double inAvg = inDiff / timeDiff;
+ double outAvg = outDiff / timeDiff;
+ if (inAvg < 0.001) {
+ inAvg = 0.0;
+ }
+ if (outAvg < 0.001) {
+ outAvg = 0.0;
+ }
+ buffer.append("Network in mB/s :" + inAvg + "\n");
+ buffer.append("Network out mB/s :" + outAvg + "\n");
+ }
+ int width = "load average 1 min".length();
+ for (int j = 0; j < sd.fs.length; ++j) {
+ double used = sd.fs[j].percentUsed();
+ if (used < 0.1) {
+ used = 0.0;
+ }
+ per = "" + used;
+ if (per.length() > 5) {
+ per = per.substring(0, 5);
+ }
+ if (sd.fs[j].root.length() < width) {
+ buffer.append(sd.fs[j].root);
+ for (int k = sd.fs[j].root.length(); k < width; ++k) {
+ buffer.append(" ");
+ }
+ buffer.append(":" + per + "% full\n");
+ } else {
+ buffer.append(sd.fs[j].root + ":" + per + "% full\n");
+ }
+ }
+ buffer.append("User count :" + sd.userCount + "\n");
+ buffer.append("Sim count :" + sd.simCount + "\n");
+ buffer.append("-----------------------------------------------\n");
+ }
+
+ }
+
+ private void getDiskAvailable(StatusData data) throws IOException {
+ String[] cmdarray = { "/bin/df" };
+ Process df = Runtime.getRuntime().exec(cmdarray);
+ InputStream is = df.getInputStream();
+ InputStreamReader reader = new InputStreamReader(is);
+ BufferedReader dfoutput = new BufferedReader(reader);
+ dfoutput.readLine(); //ignore first line
+ String line;
+ List all = new ArrayList();
+ do {
+ line = dfoutput.readLine();
+ if (line == null)
+ continue;
+
+ FSData fsData = new FSData();
+ StringTokenizer tokenizer = new StringTokenizer(line);
+ tokenizer.nextToken(); //ignore unix mount name
+ fsData.size = toFloatGigs(tokenizer.nextToken());
+ fsData.used = toFloatGigs(tokenizer.nextToken());
+ fsData.available = toFloatGigs(tokenizer.nextToken());
+ tokenizer.nextToken(); //ignore percent, don't need it
+ fsData.root = tokenizer.nextToken();
+ all.add(fsData);
+ } while (line != null);
+
+ dfoutput.close();
+
+ data.fs = new FSData[all.size()];
+ for (int i = 0; i < all.size(); ++i) {
+ data.fs[i] = (FSData) all.get(i);
+ }
+ }
+
+ private double toFloatGigs(String token) throws IOException {
+ try {
+ double result = Double.parseDouble(token);
+ return result / 1000000.0; //convert to gigs from k
+ } catch (NumberFormatException e) {
+ throw new IOException("Unable to parse result of df:" + token);
+ }
+ }
+
+ private void getLoadAvg(StatusData data) throws IOException {
+ File load = new File("/proc/loadavg");
+ BufferedReader reader = new BufferedReader(new FileReader(load));
+ String line = reader.readLine();
+ StringTokenizer tokenizer = new StringTokenizer(line, " ");
+ String oneMin = tokenizer.nextToken();
+ String fiveMin = tokenizer.nextToken();
+ String fifteenMin = tokenizer.nextToken();
+ try {
+ data.load_1min = Double.parseDouble(oneMin);
+ data.load_5min = Double.parseDouble(fiveMin);
+ data.load_15min = Double.parseDouble(fifteenMin);
+ reader.close();
+ } catch (NumberFormatException e) {
+ throw new IOException("Unable to understand the format of the /proc/loadavg file:" + e.getMessage());
+ }
+ }
+
+ private void getNetworkInfo(StatusData data) throws IOException {
+ File load = new File("/proc/net/dev");
+ BufferedReader reader = new BufferedReader(new FileReader(load));
+ reader.readLine();
+ reader.readLine();//drop first two lines, they are headings
+ String line;
+ StringTokenizer tokenizer;
+ do {
+ line = reader.readLine();
+ tokenizer = new StringTokenizer(line, " :");
+ } while (!tokenizer.nextToken().startsWith("eth"));
+ String rcvBytes = tokenizer.nextToken();
+ for (int i = 0; i < 7; ++i) {
+ tokenizer.nextToken();//ignore fields we don't need
+ }
+ String sentBytes = tokenizer.nextToken();
+ try {
+ data.netIn_mb = Double.parseDouble(rcvBytes) / 1000000.0;
+ data.netOut_mb = Double.parseDouble(sentBytes) / 1000000.0;
+ } catch (NumberFormatException e) {
+ throw new IOException("Can't understand format of network information!" + line);
+ }
+ }
+
+ private void getMemoryInfo(StatusData data) throws IOException {
+
+ File load = new File("/proc/meminfo");
+ BufferedReader reader = new BufferedReader(new FileReader(load));
+ String memTotal = reader.readLine();
+ String memFree = reader.readLine();
+ reader.readLine(); //buffers
+ String cached = reader.readLine();
+ reader.close();
+
+ try {
+ int total = Integer.parseInt(parseMemLine(memTotal, "MemTotal:"));
+ int free = Integer.parseInt(parseMemLine(memFree, "MemFree:"));
+ int cache = Integer.parseInt(parseMemLine(cached, "Cached:"));
+ int totalAvail = free + cache;
+ data.memPercentAvail = ((double) totalAvail) / ((double) total) * 100.0;
+ data.totalMemory_kb = total;
+ data.freeMemory_kb = free;
+
+ } catch (NumberFormatException e) {
+ throw new IOException("Unable to understand the format of the /proc/meminfo file:" + e.getMessage());
+ }
+ }
+
+ private String parseMemLine(String line, String expectedFirst) throws IOException {
+ StringTokenizer tokenizer = new StringTokenizer(line, " ");
+ String first = tokenizer.nextToken();
+ String second = tokenizer.nextToken();
+ if (!expectedFirst.equals(first)) {
+ throw new IOException("Whoa! Line wasn't what we expected from /proc/meminfo! Expected:" + expectedFirst + " but was " + first);
+ }
+ return second;
+ }
+
+ public boolean haveSlashProc() {
+ File load = new File("/proc/loadavg");
+ if (!load.exists()) {
+ return false;
+ }
+ if (!load.canRead()) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+ private class AllStatusResource extends SiteResource {
+ private static final String STATUS_HUMAN = "status?format=human";
+
+ private static final String STATUS_XML = "status?format=xml";
+
+ public AllStatusResource() {
+ super("all");
+ }
+
+ public void doGet(HttpServletRequest request, HttpServletResponse response, String[] pathElements) throws ServletException, IOException {
+ StringBuffer buffer = new StringBuffer();
+ String type;
+ if (shouldBeHumanReadable(request)) {
+ formatForHuman(buffer);
+ type = "text/plain";
+ } else {
+ try {
+ formatXML(buffer);
+ } catch (PersistException e) {
+ Log.error("Unable to do a status check!", e);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ } catch (IOException e) {
+ Log.error("Unable to do a status check!", e);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return;
+ }
+ type = "text/xml";
+ }
+ sendStringResponse(buffer.toString(), type, response);
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+
+ private void formatXML(StringBuffer buffer) throws IOException, PersistException {
+ XMLElement cluster = new XMLElement();
+ cluster.setName("cluster");
+
+ XMLElement webapp = new XMLElement();
+ webapp.setName("webapp");
+ webapp.setAttribute("uri", getBaseUrl());
+ XMLElement statusReports = frontDoorGetXML(getBaseUrl(),STATUS_XML);
+ webapp.addChild(statusReports);
+ cluster.addChild(webapp);
+ SimRecord[] simRecord = SimPersistTasks.findSims(getSessionFactory());
+ for (int i = 0; i < simRecord.length; ++i) {
+ SimRecord sim = simRecord[i];
+ try {
+ XMLElement s=new XMLElement();
+ s.setName("sim");
+ s.setAttribute("uri", sim.getSimURI());
+ if (isOnLocalhost(sim)) {
+ s.setAttribute("ignored", true);
+ } else {
+ statusReports = frontDoorGetXML(dodgyConversionOfSimURI(sim.getSimURI().toString()),STATUS_XML);
+ s.addChild(statusReports);
+ }
+ cluster.addChild(s);
+ } catch (IOException e) {
+ Log.info("Unable to get XML from sim URI:"+sim.getSimURI(),e);
+ }
+ }
+ String mediaURI = getMediaService().getMediaURI().toString();
+ XMLElement media=new XMLElement();
+ media.setName("mediaserver");
+ media.setAttribute("uri", mediaURI);
+ if (!mediaURI.startsWith("file:")) {
+ statusReports = frontDoorGetXML(mediaURI,STATUS_XML);
+ media.addChild(statusReports);
+ } else {
+ media.setAttribute("ignored", true);
+ }
+ cluster.addChild(media);
+ buffer.append(cluster.toString());
+ }
+
+ private boolean isOnLocalhost(SimRecord sim) {
+ return sim.getSimURI().toString().indexOf("127.0.0.1")!=-1;
+ }
+
+ private String dodgyConversionOfSimURI(String simURI) {
+ String result;
+ String standardSIMSuffix="/og/sim/";
+ if (!simURI.endsWith(standardSIMSuffix)) {
+ Log.error("Don't understand the sim URI we got, so we can't convert to a status URI:"+simURI);
+ return simURI; //not a great answer, but it'll cause IOExceptions elsewhere
+ }
+ result=simURI.substring(0,simURI.length()-standardSIMSuffix.length()) + "/og/status";
+ Log.warn("Somewhat dodgy: Converting the URI "+simURI +" to "+result+" for status report!");
+ return result;
+ }
+ private void formatForHuman(StringBuffer buffer) {
+ buffer.append("WebApp Server:" + getBaseUrl() + "\n");
+
+ try {
+ String statusReports = frontDoorGetText(getBaseUrl(),STATUS_HUMAN);
+ buffer.append("===============================================\n");
+ buffer.append(statusReports);
+ SimRecord[] simRecord = SimPersistTasks.findSims(getSessionFactory());
+ for (int i = 0; i < simRecord.length; ++i) {
+ SimRecord sim = simRecord[i];
+ try {
+ buffer.append("Sim Server:" + sim.getDisplayName() + " [" + sim.getSimID() + "] " + sim.getSimURI() + "\n");
+ buffer.append("===============================================\n");
+ if (!isOnLocalhost(sim)) {
+ statusReports = frontDoorGetText(dodgyConversionOfSimURI(sim.getSimURI().toString()),STATUS_HUMAN);
+ buffer.append(statusReports);
+ }
+ } catch (IOException e) {
+ // swallow it b/c there can be sims in DB that are down
+ }
+ }
+ String mediaURI = getMediaService().getMediaURI().toString();
+ buffer.append("Media Server:" + mediaURI+"\n");
+ buffer.append("===============================================\n");
+ if (!mediaURI.startsWith("file:")) {
+ statusReports = frontDoorGetText(mediaURI,STATUS_HUMAN);
+ buffer.append(statusReports);
+ }
+ } catch (IOException e) {
+ buffer.append("Could not contact other status applet:" + e.getMessage());
+ } catch (PersistException e) {
+ buffer.append("Unable to contact database [PersistException]:" + e.getMessage());
+ }
+ }
+ }
+
+}
Modified: maven/trunk/ogoglio-server/src/main/webapp/WEB-INF/web.xml
===================================================================
--- maven/trunk/ogoglio-server/src/main/webapp/WEB-INF/web.xml 2007-11-14 21:17:12 UTC (rev 581)
+++ maven/trunk/ogoglio-server/src/main/webapp/WEB-INF/web.xml 2007-11-15 02:59:34 UTC (rev 582)
@@ -36,6 +36,12 @@
<load-on-startup>1</load-on-startup>
</servlet>
+ <servlet>
+ <servlet-name>StatusServlet</servlet-name>
+ <servlet-class>com.ogoglio.site.StatusServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
<servlet-mapping>
<servlet-name>AccountServlet</servlet-name>
<url-pattern>/account/*</url-pattern>
@@ -66,6 +72,11 @@
<url-pattern>/comet/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>StatusServlet</servlet-name>
+ <url-pattern>/status/*</url-pattern>
+ </servlet-mapping>
+
<error-page>
<error-code>404</error-code>
<location>/notFound.html</location>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|