001: // $Id: Topology.java,v 1.7 2005/07/17 11:36:42 chrislott Exp $
002:
003: package org.jgroups.demos;
004:
005: import org.jgroups.*;
006: import org.jgroups.blocks.PullPushAdapter;
007:
008: import java.awt.*;
009: import java.awt.event.WindowEvent;
010: import java.awt.event.WindowListener;
011: import java.util.Vector;
012:
013: /**
014: * Demonstrates the membership service. Each member is represented by a rectangle that contains the
015: * addresses of all the members. The coordinator (= oldest member in the group) is painted in blue.
016: * New members can be started; all existing members will update their graphical appearance to reflect
017: * the new membership. When the coordinator itself is killed, another one will take over (the next in rank).<p>
018: * A nice demo is to start a number of Topology instances at the same time. All of them will be blue (all are
019: * coordinators since they don't find each other). Then the MERGE2 protocol sets in and only one will retain
020: * its coordinator role.
021: * @todo Needs to be ported to Swing.
022: * @author Bela Ban
023: */
024: public class Topology extends Frame implements WindowListener,
025: MembershipListener {
026: private final Vector members = new Vector();
027: private final Font myFont;
028: private final FontMetrics fm;
029: private final Color node_color = new Color(250, 220, 100);
030: private boolean coordinator = false;
031: private static final int NormalStyle = 0;
032: private static final int CheckStyle = 1;
033: private Channel channel;
034: private Object my_addr = null;
035: private static final String channel_name = "FD-Heartbeat";
036:
037: public Topology() {
038: addWindowListener(this );
039: //g=getGraphics();
040: fm = getFontMetrics(new Font("Helvetica", Font.PLAIN, 12));
041: myFont = new Font("Helvetica", Font.PLAIN, 12);
042:
043: }
044:
045: public void addNode(Object member) {
046: Object tmp;
047: for (int i = 0; i < members.size(); i++) {
048: tmp = members.elementAt(i);
049: if (member.equals(tmp))
050: return;
051: }
052: members.addElement(member);
053: repaint();
054: }
055:
056: public void removeNode(Object member) {
057: Object tmp;
058: for (int i = 0; i < members.size(); i++) {
059: tmp = members.elementAt(i);
060: if (member.equals(tmp)) {
061: members.removeElement(members.elementAt(i));
062: break;
063: }
064: }
065: repaint();
066: }
067:
068: public void drawNode(Graphics g, int x, int y, String label,
069: int style) {
070: Color old = g.getColor();
071: int width, height;
072: width = fm.stringWidth(label) + 10;
073: height = fm.getHeight() + 5;
074:
075: g.setColor(node_color);
076:
077: g.fillRect(x, y, width, height);
078: g.setColor(old);
079: g.drawString(label, x + 5, y + 15);
080: g.drawRoundRect(x - 1, y - 1, width + 1, height + 1, 10, 10);
081: if (style == CheckStyle) {
082: g
083: .drawRoundRect(x - 2, y - 2, width + 2, height + 2,
084: 10, 10);
085: g
086: .drawRoundRect(x - 3, y - 3, width + 3, height + 3,
087: 10, 10);
088: }
089: }
090:
091: public void drawTopology(Graphics g) {
092: int x = 20, y = 50;
093: String label;
094: Dimension box = getSize();
095: Color old = g.getColor();
096:
097: if (coordinator) {
098: g.setColor(Color.cyan);
099: g.fillRect(11, 31, box.width - 21, box.height - 61);
100: g.setColor(old);
101: }
102:
103: g.drawRect(10, 30, box.width - 20, box.height - 60);
104: g.setFont(myFont);
105:
106: for (int i = 0; i < members.size(); i++) {
107: label = members.elementAt(i).toString();
108: drawNode(g, x, y, label, NormalStyle);
109: y += 50;
110: }
111:
112: }
113:
114: public void paint(Graphics g) {
115: drawTopology(g);
116: }
117:
118: /* ------------ Callbacks ------------- */
119:
120: public void viewAccepted(View view) {
121: setState(view.getMembers());
122: }
123:
124: public void suspect(Address suspected_mbr) {
125: }
126:
127: public void block() {
128: }
129:
130: public void setState(Vector mbrs) {
131: members.removeAllElements();
132: for (int i = 0; i < mbrs.size(); i++)
133: addNode(mbrs.elementAt(i));
134: if (mbrs.size() <= 1
135: || (mbrs.size() > 1 && mbrs.elementAt(0)
136: .equals(my_addr)))
137: coordinator = true;
138: else
139: coordinator = false;
140: repaint();
141: }
142:
143: public void coordinatorChosen() {
144: coordinator = true;
145: repaint();
146: }
147:
148: public void windowActivated(WindowEvent e) {
149: }
150:
151: public void windowClosed(WindowEvent e) {
152: }
153:
154: public void windowClosing(WindowEvent e) {
155: channel.close();
156: System.exit(0);
157: }
158:
159: public void windowDeactivated(WindowEvent e) {
160: }
161:
162: public void windowDeiconified(WindowEvent e) {
163: }
164:
165: public void windowIconified(WindowEvent e) {
166: }
167:
168: public void windowOpened(WindowEvent e) {
169: }
170:
171: public void start() throws Exception {
172:
173: //String props="TCP:" +
174: // "TCPPING(timeout=2000;num_initial_members=1;port_range=3;" +
175: // "initial_hosts=localhost[8880]):" +
176: // "FD:STABLE:NAKACK:FLUSH:GMS(join_timeout=12000):VIEW_ENFORCER:QUEUE";
177:
178: // test for pbcast
179: //String props="UDP:PING:FD:" +
180: // "pbcast.PBCAST:UNICAST:FRAG:pbcast.GMS:" +
181: // "STATE_TRANSFER:QUEUE";
182:
183: // test for pbcast
184: //String props="TCP:TCPPING(port_range=2;initial_hosts=daddy[8880],terrapin[8880]):FD:" +
185: // "pbcast.PBCAST:UNICAST:FRAG:pbcast.GMS:" +
186: // "STATE_TRANSFER:QUEUE";
187:
188: // test2 for pbcast
189: //String props="UDP:PING:FD:" +
190: // "pbcast.PBCAST:UNICAST:FRAG:pbcast.GMS:" +
191: // "pbcast.STATE_TRANSFER";
192:
193: // String props=null; // default properties
194:
195: String props = "UDP(mcast_addr=224.0.0.35;mcast_port=45566;ip_ttl=32;"
196: + "mcast_send_buf_size=150000;mcast_recv_buf_size=80000):"
197: + "PING(timeout=2000;num_initial_members=3):"
198: + "MERGE2(min_interval=5000;max_interval=10000):"
199: + "FD_SOCK:"
200: + "VERIFY_SUSPECT(timeout=1500):"
201: + "pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):"
202: + "UNICAST(timeout=5000):"
203: + "pbcast.STABLE(desired_avg_gossip=20000):"
204: + "FRAG(frag_size=4096;down_thread=false;up_thread=false):"
205: + "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;"
206: + "shun=false;print_local_addr=true)";
207:
208: channel = new JChannel(props);
209: channel.connect(channel_name);
210: new PullPushAdapter(channel, this );
211: my_addr = channel.getLocalAddress();
212: if (my_addr != null)
213: setTitle(my_addr.toString());
214: pack();
215: show();
216: }
217:
218: public static void main(String[] args) {
219: try {
220: Topology top = new Topology();
221: top.setLayout(null);
222: top.setSize(240, 507);
223: top.start();
224: } catch (Exception e) {
225: System.err.println(e);
226: e.printStackTrace();
227: System.exit(0);
228: }
229: }
230:
231: }
|