001: //$Id: TotalTokenDemo.java,v 1.10 2005/05/30 16:14:40 belaban Exp $
002:
003: package org.jgroups.demos;
004:
005: import org.jgroups.*;
006: import org.jgroups.stack.Protocol;
007: import org.jgroups.stack.ProtocolStack;
008: import org.jgroups.util.Util;
009:
010: import javax.swing.*;
011: import java.awt.*;
012: import java.awt.event.ActionEvent;
013: import java.awt.event.ActionListener;
014: import java.io.Serializable;
015: import java.util.Iterator;
016: import java.util.Random;
017: import java.util.Vector;
018:
019: /**
020: *<p>
021: * Demonstration of TOTAL_TOKEN protocol stack implementing total
022: * order. TotalTokenDemo could however be used by any other
023: * stack configuration which does not neccesarily have to satisfy
024: * total order. If using stack configuration other than TOTAL_TOKEN
025: * an appropriate xml configuration file should be used. See -help for
026: * details.
027: * <p>
028: * TotalTokenDemo will verify :
029: * <p>
030: * total ordering of messages - by computing a color to be displayed
031: * in a gui window.
032: * <p>
033: * virtual synchrony - by displaying number of messages transmitted
034: * in last view.
035: * <p>
036: *
037: *@author Vladimir Blagojevic vladimir@cs.yorku.ca
038: *@author Ivan Bilenjkij ivan@ibossa.com
039: *@version $Revision: 1.10 $
040: *
041: *@see org.jgroups.protocols.TOTAL_TOKEN
042: *
043: **/
044:
045: public class TotalTokenDemo extends JFrame implements Runnable {
046: private JChannel channel;
047: //main tabbed pane
048:
049: final JTabbedPane tabbedPane;
050:
051: private ReceiverThread receiverThread;
052:
053: private ColorPanel colorPanel;
054: private final ControlPanel control;
055: private int mSize = 1024;
056: private volatile boolean transmitting = false;
057: private final String channelProperties;
058: private Dimension preffered;
059:
060: public TotalTokenDemo(String props) {
061: super ();
062: tabbedPane = new JTabbedPane();
063: control = new ControlPanel();
064: channelProperties = props;
065:
066: try {
067: channel = new JChannel(channelProperties);
068: } catch (ChannelException e) {
069: System.err
070: .println("Could not create channel, exiting ....");
071: e.printStackTrace(System.err);
072: }
073:
074: addPanel("Control", control);
075: getContentPane().add(tabbedPane);
076: connect();
077:
078: }
079:
080: public void addPanel(String name, JPanel panel) {
081:
082: if (tabbedPane.getTabCount() == 0) {
083: preffered = panel.getPreferredSize();
084: }
085:
086: panel.setPreferredSize(preffered);
087: tabbedPane.add(name, panel);
088: }
089:
090: public JChannel getChannel() {
091: return channel;
092: }
093:
094: public void connect() {
095: try {
096: channel.connect("TOTAL_TOKEN_DEMO_GROUP");
097: } catch (ChannelException e) {
098: e.printStackTrace();
099: }
100: receiverThread = new ReceiverThread();
101: receiverThread.start();
102: Address a = channel.getLocalAddress();
103: if (a != null)
104: setTitle(a.toString());
105: else
106: setTitle("Not connected");
107: control.connected();
108: }
109:
110: public void run() {
111: Random r = new Random();
112:
113: while (true) {
114: Util.sleep(10);
115: try {
116: if (transmitting) {
117: channel.send(new Message(null, null,
118: new TotalPayload(r.nextInt(255))));
119: } else {
120: Util.sleep(200);
121: }
122:
123: } catch (Exception e) {
124: e.printStackTrace();
125: }
126: }
127: }
128:
129: public void disconnect() {
130: transmitting = false;
131: receiverThread.shutDown();
132: channel.disconnect();
133: control.disconnected();
134: setTitle("Not connected");
135: }
136:
137: private class ReceiverThread extends Thread {
138: volatile boolean running = true;
139: Thread nullifier = null;
140: private long startTimeThroughput = System.currentTimeMillis();
141: private final long oneSecond = 1000;
142: private long throughput = 1;
143:
144: public ReceiverThread() {
145: nullifier = new Thread(new Runnable() {
146: public void run() {
147: //nullifies throughput display
148: while (running) {
149: Util.sleep(2000);
150: if ((System.currentTimeMillis() - startTimeThroughput) > 2000) {
151: control.throughput.setText("0 KB/sec");
152: }
153: }
154: }
155: });
156: nullifier.start();
157: }
158:
159: public void shutDown() {
160: running = false;
161: }
162:
163: private void measureThrougput(long size) {
164: if ((System.currentTimeMillis() - startTimeThroughput) > oneSecond) {
165: control.throughput.setText("" + (throughput / 1024)
166: + " KB/sec");
167: startTimeThroughput = System.currentTimeMillis();
168: throughput = 0;
169: } else {
170: throughput += size;
171: }
172: }
173:
174: public void run() {
175: Object tmp;
176: Message msg = null;
177: int counter = 0;
178: Vector v = new Vector();
179: while (running) {
180: Util.sleep(10);
181: try {
182:
183: tmp = channel.receive(0);
184: if (tmp == null)
185: continue;
186:
187: if (tmp instanceof View) {
188: View vw = (View) tmp;
189: control.viewNumber.setText(""
190: + vw.getVid().getId());
191: control.numMessagesInLastView.setText(""
192: + counter);
193: counter = 0;
194: v.clear();
195: continue;
196: }
197:
198: if (tmp instanceof ExitEvent) {
199: System.out.println("received EXIT");
200: break;
201: }
202:
203: if (!(tmp instanceof Message))
204: continue;
205:
206: msg = (Message) tmp;
207:
208: measureThrougput(msg.size());
209: TotalPayload p = null;
210:
211: p = (TotalPayload) msg.getObject();
212: v.addElement(new Integer(p.getRandomSequence()));
213: int size = v.size();
214: if (size % 50 == 0) {
215: int value = 0;
216: int i = 0;
217: Iterator iter = v.iterator();
218: while (iter.hasNext()) {
219: i++;
220: int seq = ((Integer) iter.next())
221: .intValue();
222: if (i % 2 == 0) {
223: value *= seq;
224: } else if (i % 3 == 0) {
225: value -= seq;
226: } else
227: value += seq;
228: }
229: v.clear();
230: value = Math.abs(value);
231: int r = value % 85;
232: int g = value % 170;
233: int b = value % 255;
234: colorPanel.setSeq(r, g, b);
235: }
236: counter++;
237: } catch (ChannelNotConnectedException e) {
238: e.printStackTrace();
239: } catch (ChannelClosedException e) {
240: e.printStackTrace();
241: } catch (TimeoutException e) {
242: e.printStackTrace();
243: }
244: }
245:
246: }
247: }
248:
249: public static class TotalPayload implements Serializable {
250: private final int seqRandom;
251:
252: public TotalPayload(int random) {
253: seqRandom = random;
254: }
255:
256: public int getRandomSequence() {
257: return seqRandom;
258: }
259:
260: }
261:
262: class TransmitAction extends AbstractAction {
263:
264: private static final String TRANSMIT_OFF = "transmit off";
265: private static final String TRANSMIT_ON = "transmit on";
266:
267: TransmitAction() {
268: putValue(NAME, TRANSMIT_OFF);
269: }
270:
271: public void actionPerformed(ActionEvent e) {
272: if (getValue(NAME) == TRANSMIT_OFF) {
273: putValue(NAME, TRANSMIT_ON);
274: transmitting = true;
275: } else {
276: putValue(NAME, TRANSMIT_OFF);
277: transmitting = false;
278: }
279: }
280:
281: }
282:
283: class ControlPanel extends JPanel {
284:
285: private static final String DISCONNECT = "Disconnect";
286: private static final String CONNECT = "Connect";
287: final JTextField numMessagesInLastView;
288: final JTextField throughput;
289: final JTextField viewNumber;
290: final JTextField messageSize;
291: final JTextField state;
292: final JButton transmit;
293: final JButton connectButton;
294:
295: JTabbedPane pane;
296:
297: public ControlPanel() {
298: super ();
299:
300: //Layout the labels in a panel
301: JPanel labelPane = new JPanel();
302: labelPane.setLayout(new GridLayout(0, 1));
303: labelPane.add(new JLabel("Message size"));
304: labelPane.add(new JLabel("Current view"));
305: labelPane.add(new JLabel("Throughput"));
306: labelPane.add(new JLabel("Last view count"));
307:
308: colorPanel = new ColorPanel();
309: connectButton = new JButton(DISCONNECT);
310:
311: connectButton.addActionListener(new ActionListener() {
312: public void actionPerformed(ActionEvent e) {
313: JButton b = (JButton) e.getSource();
314: String current_state = b.getText();
315: if (CONNECT.equals(current_state)) {
316: connect();
317: } else if (DISCONNECT.equals(current_state)) {
318: disconnect();
319: }
320: }
321: });
322:
323: transmit = new JButton(new TransmitAction());
324: labelPane.add(connectButton);
325: labelPane.add(transmit);
326:
327: int size = 10;
328: messageSize = new JTextField(size);
329: messageSize.setText("" + mSize);
330: messageSize.addActionListener(new ActionListener() {
331: /**
332: * Invoked when an action occurs.
333: */
334: public void actionPerformed(ActionEvent e) {
335: mSize = Integer.parseInt(messageSize.getText());
336: }
337: });
338: viewNumber = new JTextField(size);
339: viewNumber.setEditable(false);
340: throughput = new JTextField(size);
341: throughput.setEditable(false);
342: numMessagesInLastView = new JTextField(size);
343: numMessagesInLastView.setEditable(false);
344:
345: state = new JTextField(size);
346: state.setEditable(false);
347:
348: //Layout the text fields in a panel
349: JPanel fieldPane = new JPanel();
350: fieldPane.setLayout(new GridLayout(0, 1));
351: fieldPane.add(messageSize);
352: fieldPane.add(viewNumber);
353: fieldPane.add(throughput);
354: fieldPane.add(numMessagesInLastView);
355: fieldPane.add(state);
356: fieldPane.add(colorPanel);
357:
358: //Put the panels in another panel, labels on left,
359: //text fields on right
360: JPanel contentPane = new JPanel();
361: contentPane.setBorder(BorderFactory
362: .createTitledBorder("Control"));
363: contentPane.setLayout(new BorderLayout());
364: contentPane.add(labelPane, BorderLayout.CENTER);
365: contentPane.add(fieldPane, BorderLayout.EAST);
366: this .setLayout(new BorderLayout());
367: this .add(contentPane);
368: }
369:
370: public void connected() {
371: connectButton.setText(DISCONNECT);
372: state.setText("connected ok");
373: }
374:
375: public void disconnected() {
376: connectButton.setText(CONNECT);
377: state.setText("disconnected ok");
378: }
379: }
380:
381: class ColorPanel extends JPanel {
382:
383: long seq1, seq2, seq3;
384:
385: public ColorPanel() {
386: super ();
387: setOpaque(false);
388: this .setLayout(new BorderLayout());
389: //setBorder(BorderFactory.createLineBorder(Color.black));
390: }
391:
392: public Dimension getPreferredSize() {
393: Dimension layoutSize = super .getPreferredSize();
394: int max = Math.max(layoutSize.width, layoutSize.height);
395: return new Dimension(max + 20, max + 20);
396: }
397:
398: public void setSeq(long seq1, long seq2, long seq3) {
399: this .seq1 = seq1;
400: this .seq2 = seq2;
401: this .seq3 = seq3;
402: this .repaint();
403: }
404:
405: protected void paintComponent(Graphics g) {
406: Dimension size = this .getSize();
407: int x = 0;
408: int y = 0;
409: g.setColor(new Color((int) seq1, (int) seq2, (int) seq3));
410: g.fillRect(x, y, size.width, size.height);
411: }
412: }
413:
414: class StackPanel extends JPanel {
415: final ProtocolStack stack;
416:
417: public StackPanel(JChannel channel) {
418: super ();
419: setBorder(BorderFactory.createTitledBorder("ProtocolStack"));
420: this .setLayout(new GridLayout(0, 2));
421: this .stack = channel.getProtocolStack();
422: Iterator iter = stack.getProtocols().iterator();
423: String debugLevels[] = new String[] { "DEBUG", "INFO",
424: "ERROR" };
425: while (iter.hasNext()) {
426: Protocol p = (Protocol) iter.next();
427: JLabel field = new JLabel(p.getName());
428: JComboBox pane = new JComboBox(debugLevels);
429: this .add(field);
430: this .add(pane);
431:
432: }
433: }
434: }
435:
436: static void help() {
437: System.out
438: .println("\nTotalTokenDemo [-help] [-props <protocol stack definition>]");
439: System.out
440: .println("-props: argument can be an old-style protocol stack specification, or it can be "
441: + "a URL. In the latter case, the protocol specification will be read from the URL\n");
442: }
443:
444: public static void main(String args[]) {
445: String props = null;
446:
447: for (int i = 0; i < args.length; i++) {
448: if ("-help".equals(args[i])) {
449: help();
450: return;
451: }
452: if ("-props".equals(args[i])) {
453: props = args[++i];
454: continue;
455: }
456: help();
457: return;
458: }
459:
460: if (props == null) {
461: props = "UDP(mcast_addr=224.0.0.35;mcast_port=45566;ip_ttl=32;"
462: + "mcast_send_buf_size=150000;mcast_recv_buf_size=80000):"
463: + "PING(timeout=2000;num_initial_members=5):"
464: + "FD_SOCK:"
465: + "VERIFY_SUSPECT(timeout=1500):"
466: + "UNICAST(timeout=5000):"
467: + "FRAG(frag_size=8192;down_thread=false;up_thread=false):"
468: + "TOTAL_TOKEN(block_sending=50;unblock_sending=10):"
469: + "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;"
470: + "shun=false;print_local_addr=true)";
471:
472: }
473:
474: TotalTokenDemo ttd = new TotalTokenDemo(props);
475: //StackPanel not_done_yet = new StackPanel(ttd.getChannel());
476: //ttd.addPanel("Debug", not_done_yet);
477: ttd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
478: ttd.pack();
479: ttd.show();
480: new Thread(ttd).start();
481: }
482: }
|