001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2007 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.demo.mesh;
028:
029: import java.io.IOException;
030: import java.io.PrintWriter;
031: import java.text.DecimalFormat;
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.Collections;
035: import java.util.HashMap;
036: import java.util.HashSet;
037: import java.util.List;
038: import java.util.Map;
039: import java.util.Set;
040:
041: import javax.servlet.http.HttpServletRequest;
042: import javax.servlet.http.HttpServletResponse;
043:
044: import org.cougaar.core.mts.MessageAddress;
045: import org.cougaar.core.relay.SimpleRelay;
046: import org.cougaar.core.service.BlackboardQueryService;
047: import org.cougaar.core.servlet.ComponentServlet;
048: import org.cougaar.util.UnaryPredicate;
049:
050: /**
051: * This servlet shows our mesh relays as an HTML page.
052: * <p>
053: * Supports an optional Servlet path parameter, which defaults to "/mesh".
054: * <p>
055: * For simplicity, it's easiest to load a copy of this servlet into every
056: * agent.
057: */
058: public class MeshServlet extends ComponentServlet {
059:
060: private long loadTime;
061:
062: private BlackboardQueryService blackboard;
063:
064: /** @return a default path if a plugin parameter is not specified */
065: protected String getPath() {
066: String ret = super .getPath();
067: return (ret == null ? "/mesh" : ret);
068: }
069:
070: /** This method is called when the agent is created */
071: public void load() {
072: super .load();
073:
074: // Record our load time
075: loadTime = System.currentTimeMillis();
076:
077: // Get our required Cougaar services
078: this .blackboard = (BlackboardQueryService) getServiceBroker()
079: .getService(this , BlackboardQueryService.class, null);
080: }
081:
082: /** This method is called whenever the browser loads our URL. */
083: public void doGet(HttpServletRequest request,
084: HttpServletResponse response) throws IOException {
085:
086: // Begin our HTML page response
087: response.setContentType("text/html");
088: PrintWriter out = response.getWriter();
089: String title = "Agent " + getEncodedAgentName();
090: out.println("<html>" + "<head><title>" + title
091: + "</title></head>" + "<body><h1>" + title + "</h1>");
092:
093: // Write how long we've been running, to make it easy for the user
094: // to calculate the relay throughput
095: long runTime = System.currentTimeMillis() - loadTime;
096: out
097: .println("Milliseconds since agent load: " + runTime
098: + "<p>");
099:
100: // Query the blackboard for relays
101: UnaryPredicate pred = new UnaryPredicate() {
102: public boolean execute(Object o) {
103: return (o instanceof SimpleRelay);
104: }
105: };
106: Collection col = blackboard.query(pred);
107:
108: // We expect multiple "incoming" relays from different remote targets, each
109: // with possibly different counter values, plus corresponding "outgoing"
110: // relays with identical counter values.
111: //
112: // So, we'll split our relays into pairs based on the targets.
113: Map<String, SimpleRelay> sent = new HashMap<String, SimpleRelay>(
114: col.size() >> 1);
115: Map<String, SimpleRelay> recv = new HashMap<String, SimpleRelay>(
116: col.size() >> 1);
117: for (Object oi : col) {
118: SimpleRelay relay = (SimpleRelay) oi;
119: boolean isOutgoing = agentId.equals(relay.getSource());
120: MessageAddress addr = (isOutgoing ? relay.getTarget()
121: : relay.getSource());
122: String key = (addr == null ? null : addr.getAddress());
123: if (key == null) {
124: key = "null";
125: }
126: if (isOutgoing) {
127: sent.put(key, relay);
128: } else {
129: recv.put(key, relay);
130: }
131: }
132:
133: // Get a sorted set of all unique target names
134: Set<String> targetSet = new HashSet<String>(sent.keySet());
135: targetSet.addAll(recv.keySet());
136: List<String> targets = new ArrayList<String>(targetSet);
137: Collections.sort(targets);
138:
139: // Write the relays as an HTML table
140: out.println("<table border=1>" + "<tr>"
141: + " <th rowspan=2></th>"
142: + " <th rowspan=2>Target</th>"
143: + " <th colspan=5>Sent</th>"
144: + " <th colspan=5>Received</th>" + "</tr>" + "<tr>"
145: + " <th bgcolor=lightgray> </th>"
146: + " <th>UID</th>" + " <th>Bloat (byte[])</th>"
147: + " <th>Count</th>"
148: + " <th>Throughput (relays/second)</th>"
149: + " <th bgcolor=lightgray> </th>"
150: + " <th>UID</th>" + " <th>Bloat (byte[])</th>"
151: + " <th>Count</th>"
152: + " <th>Throughput (relays/second)</th>" + "</tr>");
153: DecimalFormat formatter = new DecimalFormat("0.000");
154: for (int i = 0; i < targets.size(); i++) {
155: String target = targets.get(i);
156:
157: out.print("<tr align=right>" + " <td>" + i + "</td>"
158: + " <td>" + target + "</td>");
159:
160: for (int j = 0; j < 2; j++) {
161: SimpleRelay relay = (j == 0 ? sent.get(target) : recv
162: .get(target));
163:
164: out.print(" <td bgcolor=lightgray> </td>");
165:
166: if (relay == null) {
167: out
168: .print(" <td colspan=4><font color=red>null</font></td>");
169: continue;
170: }
171:
172: int bloat = -1;
173: Object o = relay.getQuery();
174: if (o instanceof Payload) {
175: Payload p = (Payload) o;
176: bloat = p.getBloat();
177: o = p.getData();
178: }
179: long count = ((Long) o).longValue();
180:
181: double throughput = Double.NaN;
182: if (count > 0 && runTime > 0) {
183: throughput = 1000.0 * ((double) count / runTime);
184: }
185:
186: out.print(" <td>" + relay.getUID() + "</td>"
187: + " <td>" + bloat + "</td>" + " <td>" + count
188: + "</td>" + " <td>"
189: + formatter.format(throughput) + "</td>");
190: }
191:
192: out.println("<tr>");
193: }
194: out.println("</table>");
195:
196: // Create a "reload" button for the user to invoke our servlet again
197: out.println("<form method=\"get\" action=\""
198: + request.getRequestURI() + "\">"
199: + " <input type=\"submit\" value=\"Reload\">"
200: + "</form>");
201:
202: // End our HTML page
203: out.println("</body></html>");
204: }
205: }
|