KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > protocols > ClientGmsImpl


1 // $Id: ClientGmsImpl.java,v 1.9 2005/04/20 20:25:46 belaban Exp $
2

3 package org.jgroups.protocols;
4
5
6 import org.jgroups.Address;
7 import org.jgroups.Event;
8 import org.jgroups.View;
9 import org.jgroups.ViewId;
10 import org.jgroups.blocks.GroupRequest;
11 import org.jgroups.blocks.MethodCall;
12 import org.jgroups.util.Util;
13
14 import java.util.Enumeration JavaDoc;
15 import java.util.Hashtable JavaDoc;
16 import java.util.Vector JavaDoc;
17
18
19 /**
20  * Client part of GMS. Whenever a new member wants to join a group, it starts in the CLIENT role.
21  * No multicasts to the group will be received and processed until the member has been joined and
22  * turned into a SERVER (either coordinator or participant, mostly just participant). This class
23  * only implements <code>Join</code> (called by clients who want to join a certain group, and
24  * <code>ViewChange</code> which is called by the coordinator that was contacted by this client, to
25  * tell the client what its initial membership is.
26  *
27  * @author Bela Ban
28  * @version $Revision: 1.9 $
29  */

30 public class ClientGmsImpl extends GmsImpl {
31     final Vector JavaDoc initial_mbrs=new Vector JavaDoc(7);
32     final Object JavaDoc view_installation_mutex=new Object JavaDoc();
33     boolean joined=false;
34
35
36     public ClientGmsImpl(GMS g) {
37         gms=g;
38     }
39
40
41     public void init() {
42         initial_mbrs.removeAllElements();
43         joined=false;
44     }
45
46
47     /**
48      * Will generate a CONNECT_OK event. Determines the coordinator and sends a unicast
49      * join() message to it. If successful, we wait for a ViewChange (can time out).
50      * If view change is received, impl is changed to an instance of ParticipantGmsImpl.
51      * Otherwise, we continue trying to send join() messages to the coordinator,
52      * until we succeed (or there is no member in the group. In this case, we create
53      * our own singleton group).
54      * <p>When GMS.disable_initial_coord is set to true, then we won't become coordinator on receiving an initial
55      * membership of 0, but instead will retry (forever) until we get an initial membership of > 0.
56      *
57      * @param mbr Our own address (assigned through SET_LOCAL_ADDRESS)
58      */

59     public void join(Address mbr) {
60         Address coord=null;
61         Event view_evt;
62
63         while(!joined) {
64             findInitialMembers();
65             if(joined) {
66                  if(log.isInfoEnabled()) log.info("joined successfully");
67                 return;
68             }
69             if(initial_mbrs.size() == 0) {
70                 if(gms.disable_initial_coord) {
71
72                         if(log.isInfoEnabled()) log.info("received an initial membership of 0, but " +
73                                 "cannot become coordinator (disable_initial_coord=" + gms.disable_initial_coord +
74                                 "), will retry fetching the initial membership");
75                     continue;
76                 }
77                 joined=true;
78                 gms.view_id=new ViewId(mbr); // create singleton view with mbr as only member
79
gms.members.add(mbr);
80                 view_evt=new Event(Event.VIEW_CHANGE,
81                         gms.makeView(gms.members.getMembers(), gms.view_id));
82                 gms.passDown(view_evt);
83                 gms.passUp(view_evt);
84                 gms.becomeCoordinator();
85
86                 gms.passUp(new Event(Event.BECOME_SERVER));
87                 gms.passDown(new Event(Event.BECOME_SERVER));
88                  if(log.isInfoEnabled()) log.info("created group (first member)");
89                 break;
90             }
91
92             coord=determineCoord(initial_mbrs);
93             if(coord == null) {
94                 if(log.isWarnEnabled()) log.warn("could not determine coordinator " +
95                                                  "from responses " + initial_mbrs);
96                 continue;
97             }
98
99             synchronized(view_installation_mutex) {
100                 try {
101                     if(log.isInfoEnabled()) log.info("sending handleJoin() to " + coord);
102                     MethodCall call=new MethodCall("handleJoin", new Object JavaDoc[]{mbr}, new Class JavaDoc[]{Address.class});
103                     gms.callRemoteMethod(coord, call, GroupRequest.GET_NONE, 0);
104                     view_installation_mutex.wait(gms.join_timeout); // wait for view -> handleView()
105
}
106                 catch(Exception JavaDoc e) {
107                     if(log.isErrorEnabled()) log.error("exception is " + e);
108                     continue;
109                 }
110             } // end synchronized
111

112             if(joined) {
113                 if(log.isInfoEnabled()) log.info("joined successfully");
114                 return; // --> SUCCESS
115
}
116             else {
117                 if(log.isInfoEnabled()) log.info("failed, retrying");
118                 Util.sleep(gms.join_retry_timeout);
119             }
120
121         } // end while
122
}
123
124
125     public void leave(Address mbr) {
126         wrongMethod("leave");
127     }
128
129
130     public void suspect(Address mbr) {
131         // wrongMethod("suspect");
132
}
133
134
135     public void merge(Vector JavaDoc other_coords) {
136         wrongMethod("merge");
137     }
138
139
140     public boolean handleJoin(Address mbr) {
141         wrongMethod("handleJoin");
142         return false;
143     }
144
145
146     /**
147      * Returns false. Clients don't handle leave() requests
148      */

149     public void handleLeave(Address mbr, boolean suspected) {
150         wrongMethod("handleLeave");
151     }
152
153
154     /**
155      * Install the first view in which we are a member. This is essentially a confirmation
156      * of our JOIN request (see join() above).
157      */

158     public void handleViewChange(ViewId new_view, Vector JavaDoc mems) {
159         if(gms.local_addr != null && mems != null && mems.contains(gms.local_addr)) {
160             synchronized(view_installation_mutex) { // wait until JOIN is sent (above)
161
joined=true;
162                 view_installation_mutex.notifyAll();
163                 gms.installView(new_view, mems);
164                 gms.becomeParticipant();
165                 gms.passUp(new Event(Event.BECOME_SERVER));
166                 gms.passDown(new Event(Event.BECOME_SERVER));
167             }
168             synchronized(initial_mbrs) { // in case findInitialMembers() is still running:
169
initial_mbrs.notifyAll(); // this will unblock it
170
}
171         }
172         else
173             if(log.isWarnEnabled()) log.warn("am not member of " + mems + ", will not install view");
174     }
175
176
177     /**
178      * Returns immediately. Clients don't handle merge() requests
179      */

180     public View handleMerge(ViewId other_view, Vector JavaDoc other_members) {
181         wrongMethod("handleMerge");
182         return null;
183     }
184
185
186     /**
187      * Returns immediately. Clients don't handle suspect() requests
188      */

189     public void handleSuspect(Address mbr) {
190         wrongMethod("handleSuspect");
191         return;
192     }
193
194
195     public boolean handleUpEvent(Event evt) {
196         Vector JavaDoc tmp;
197
198         switch(evt.getType()) {
199
200             case Event.FIND_INITIAL_MBRS_OK:
201                 tmp=(Vector JavaDoc)evt.getArg();
202                 synchronized(initial_mbrs) {
203                     if(tmp != null && tmp.size() > 0)
204                         for(int i=0; i < tmp.size(); i++)
205                             initial_mbrs.addElement(tmp.elementAt(i));
206                     initial_mbrs.notifyAll();
207                 }
208                 return false; // don't pass up the stack
209
}
210
211         return true;
212     }
213
214
215
216
217
218     /* --------------------------- Private Methods ------------------------------------ */
219
220
221
222
223
224
225
226     /**
227      * Pings initial members. Removes self before returning vector of initial members.
228      * Uses IP multicast or gossiping, depending on parameters.
229      */

230     void findInitialMembers() {
231         PingRsp ping_rsp;
232
233         synchronized(initial_mbrs) {
234             initial_mbrs.removeAllElements();
235             gms.passDown(Event.FIND_INITIAL_MBRS_EVT);
236             if(initial_mbrs.size() == 0) {
237                 try {
238                     initial_mbrs.wait();
239                 }
240                 catch(Exception JavaDoc e) {
241                 }
242             }
243
244             for(int i=0; i < initial_mbrs.size(); i++) {
245                 ping_rsp=(PingRsp)initial_mbrs.elementAt(i);
246                 if(ping_rsp.own_addr != null && gms.local_addr != null &&
247                         ping_rsp.own_addr.equals(gms.local_addr)) {
248                     initial_mbrs.removeElementAt(i);
249                     break;
250                 }
251             }
252         }
253     }
254
255
256     /**
257      * The coordinator is determined by a majority vote. If there are an equal number of votes for
258      * more than 1 candidate, we determine the winner randomly.
259      */

260     Address determineCoord(Vector JavaDoc mbrs) {
261         PingRsp mbr;
262         Hashtable JavaDoc votes;
263         int count, most_votes;
264         Address winner=null, tmp;
265
266         if(mbrs == null || mbrs.size() < 1)
267             return null;
268
269         votes=new Hashtable JavaDoc(5);
270
271         // count *all* the votes (unlike the 2000 election)
272
for(int i=0; i < mbrs.size(); i++) {
273             mbr=(PingRsp)mbrs.elementAt(i);
274             if(mbr.coord_addr != null) {
275                 if(!votes.containsKey(mbr.coord_addr))
276                     votes.put(mbr.coord_addr, new Integer JavaDoc(1));
277                 else {
278                     count=((Integer JavaDoc)votes.get(mbr.coord_addr)).intValue();
279                     votes.put(mbr.coord_addr, new Integer JavaDoc(count + 1));
280                 }
281             }
282         }
283
284          {
285             if(votes.size() > 1)
286                 if(log.isWarnEnabled()) log.warn("there was more than 1 candidate for coordinator: " + votes);
287             else
288                 if(log.isInfoEnabled()) log.info("election results: " + votes);
289         }
290     
291
292         // determine who got the most votes
293
most_votes=0;
294         for(Enumeration JavaDoc e=votes.keys(); e.hasMoreElements();) {
295             tmp=(Address)e.nextElement();
296             count=((Integer JavaDoc)votes.get(tmp)).intValue();
297             if(count > most_votes) {
298                 winner=tmp;
299 // fixed July 15 2003 (patch submitted by Darren Hobbs, patch-id=771418)
300
most_votes=count;
301             }
302         }
303         votes.clear();
304         return winner;
305     }
306
307
308 }
309
Popular Tags