001: // $Id: PERF.java,v 1.10.10.1 2007/04/27 08:03:50 belaban Exp $
002:
003: package org.jgroups.protocols;
004:
005: import org.jgroups.Event;
006: import org.jgroups.Message;
007: import org.jgroups.View;
008: import org.jgroups.stack.Protocol;
009: import org.jgroups.stack.ProtocolObserver;
010:
011: import java.util.Properties;
012: import java.util.Vector;
013:
014: /**
015: * Measures time taken by each protocol to process a message. PERF has to be the top protocol in a stack. It
016: * adds a special header to the message which travels with the message. Upon initialization,
017: * PERF creates a ProtocolObserver for each protocol layer in the stack. That observer notes the time taken for a
018: * message to travel through the layer it observes, and records the start time, end time and total time
019: * <em>in the message itself</em> (in the header created by PERF). When a message is received by PERF, the statistics
020: * for the message are appended to a file (or displayed in a GUI (not yet done)).<p>
021: * <em>Because of different wall times between different machines, PERF should only be used for members
022: * in the same JVM. For members in different processes, physical clocks have to be synchronized: if they are
023: * only a few milliseconds aprt, the values will be incorrect.</em>
024: * For example, to write all performance data to a file, do the following:
025: * <ol>
026: * <li>Set tracing to on, e.g. <code>trace=true</code> in jgroups.properties
027: * <li>Add a trace statement for PERF.up(): <code>trace0=PERF.up DEBUG /tmp/trace.perf</code>. This will write
028: * all trace output to the given file.
029: * </ol>
030: *
031: * @author Bela Ban Oct 2001
032: * @version $Revision: 1.10.10.1 $
033: */
034: public class PERF extends Protocol {
035: boolean details = false;
036: final Vector members = new Vector();
037: Vector protocols = null;
038: static final String name = "PERF";
039:
040: /**
041: * All protocol names have to be unique !
042: */
043: public String getName() {
044: return name;
045: }
046:
047: public boolean setProperties(Properties props) {
048: super .setProperties(props);
049: String str;
050:
051: str = props.getProperty("details");
052: if (str != null) {
053: details = Boolean.valueOf(str).booleanValue();
054: props.remove("details");
055: }
056: if (props.size() > 0) {
057: log
058: .error("PERF.setProperties(): these properties are not recognized: "
059: + props);
060:
061: return false;
062: }
063: return true;
064: }
065:
066: public void start() throws Exception {
067: protocols = stack != null ? stack.getProtocols() : null;
068: setupObservers();
069: }
070:
071: public void up(Event evt) {
072: Message msg;
073: PerfHeader hdr;
074:
075: switch (evt.getType()) {
076:
077: case Event.MSG:
078: msg = (Message) evt.getArg();
079: hdr = removePerfHeader(msg);
080: if (hdr != null) {
081: hdr.setEndTime();
082: hdr.setDone(name, PerfHeader.UP); // we do this here because header is removed, so PassUp won't find it
083: if (log.isTraceEnabled())
084: log.trace(hdr.printContents(details, protocols)
085: + "\n---------------------------------\n");
086: }
087: break;
088: }
089:
090: passUp(evt); // Pass up to the layer above us
091: }
092:
093: public void down(Event evt) {
094: Message msg;
095:
096: switch (evt.getType()) {
097:
098: case Event.TMP_VIEW:
099: case Event.VIEW_CHANGE:
100: Vector new_members = ((View) evt.getArg()).getMembers();
101: synchronized (members) {
102: members.removeAllElements();
103: members.addAll(new_members);
104: }
105: passDown(evt);
106: break;
107:
108: case Event.MSG:
109: msg = (Message) evt.getArg();
110: initializeMessage(msg); // Add a PerfHeader to the message
111: break;
112: }
113:
114: passDown(evt); // Pass on to the layer below us
115: }
116:
117: /* ----------------------------------- Private Methods -------------------------------------- */
118:
119: /**
120: * Create PerfObservers for all protocols save PERF
121: */
122: void setupObservers() {
123: Protocol p = null;
124: String pname;
125: PerfObserver po = null;
126:
127: for (int i = 0; i < protocols.size(); i++) {
128: p = (Protocol) protocols.elementAt(i);
129: pname = p.getName();
130: if (pname != null) {
131: po = new PerfObserver(pname);
132: p.setObserver(po);
133: }
134: }
135: }
136:
137: void initializeMessage(Message msg) {
138: PerfHeader hdr = new PerfHeader(msg.getSrc(), msg.getDest());
139: Protocol p;
140: String pname = null;
141:
142: if (protocols == null) {
143: log
144: .error("PERF.initializeMessage(): 'protocols' variable is null");
145: return;
146: }
147:
148: for (int i = 0; i < protocols.size(); i++) {
149: p = (Protocol) protocols.elementAt(i);
150: pname = p.getName();
151: if (pname != null) {
152: hdr.addEntry(pname);
153: }
154: }
155: hdr.setReceived(name, PerfHeader.DOWN); // we do this here because down() didn't yet find a PerfHeader
156: msg.putHeader(name, hdr);
157: }
158:
159: /**
160: * Removes if present. Otherwise returns null
161: */
162: PerfHeader removePerfHeader(Message m) {
163: Object hdr = null;
164:
165: if (m == null || (hdr = m.removeHeader(name)) == null)
166: return null;
167: return (PerfHeader) hdr;
168: }
169:
170: // Vector getProtocols() {
171: // Vector ret=(Vector)stack.getProtocols().clone();
172: // Protocol p;
173:
174: // for(int i=0; i < ret.size(); i++) {
175: // p=(Protocol)ret.elementAt(i);
176: // if(p.getName() != null && p.getName().equals(getName())) {
177: // ret.removeElement(p);
178: // break;
179: // }
180: // }
181: // return ret;
182: // }
183:
184: /* -------------------------------- End of Private Methods ---------------------------------- */
185: }
186:
187: /**
188: * Observes a protocol and adds its timings to the PerfHeader attached to each protocol.
189: */
190: class PerfObserver implements ProtocolObserver {
191: final String prot_name;
192: boolean bottom = false;
193:
194: PerfObserver(String prot_name) {
195: this .prot_name = prot_name;
196: }
197:
198: public void setProtocol(Protocol prot) {
199: if (prot != null && prot.getDownProtocol() == null)
200: bottom = true;
201: }
202:
203: public boolean up(Event evt, int num_evts) {
204: PerfHeader hdr;
205: if (evt.getType() == Event.MSG) {
206: hdr = getPerfHeader((Message) evt.getArg());
207: if (hdr != null) {
208: hdr.setReceived(prot_name, PerfHeader.UP);
209: if (bottom)
210: hdr.setNetworkReceived();
211: }
212: }
213: return true;
214: }
215:
216: public boolean passUp(Event evt) {
217: PerfHeader hdr;
218: if (evt.getType() == Event.MSG) {
219: hdr = getPerfHeader((Message) evt.getArg());
220: if (hdr != null) {
221: hdr.setDone(prot_name, PerfHeader.UP);
222: }
223: }
224: return true;
225: }
226:
227: public boolean down(Event evt, int num_evts) {
228: PerfHeader hdr;
229: if (evt.getType() == Event.MSG) {
230: hdr = getPerfHeader((Message) evt.getArg());
231: if (hdr != null) {
232: hdr.setReceived(prot_name, PerfHeader.DOWN);
233: }
234: }
235: return true;
236: }
237:
238: public boolean passDown(Event evt) {
239: PerfHeader hdr;
240: if (evt.getType() == Event.MSG) {
241: hdr = getPerfHeader((Message) evt.getArg());
242: if (hdr != null) {
243: hdr.setDone(prot_name, PerfHeader.DOWN);
244: if (bottom)
245: hdr.setNetworkSent();
246: }
247: }
248: return true;
249: }
250:
251: PerfHeader getPerfHeader(Message m) {
252: Object hdr = null;
253:
254: if (m == null || (hdr = m.getHeader(PERF.name)) == null)
255: return null;
256: return (PerfHeader) hdr;
257: }
258:
259: }
|