001: // $Id: ParticipantGmsImpl.java,v 1.22 2006/08/03 09:20:58 belaban Exp $
002:
003: package org.jgroups.protocols.pbcast;
004:
005: import org.jgroups.*;
006: import org.jgroups.util.Promise;
007:
008: import java.util.Vector;
009: import java.util.Iterator;
010: import java.util.Collection;
011: import java.util.LinkedHashSet;
012:
013: public class ParticipantGmsImpl extends GmsImpl {
014: private final Vector suspected_mbrs = new Vector(11);
015: private final Promise leave_promise = new Promise();
016:
017: public ParticipantGmsImpl(GMS g) {
018: super (g);
019: }
020:
021: public void init() throws Exception {
022: super .init();
023: suspected_mbrs.removeAllElements();
024: leave_promise.reset();
025: }
026:
027: public void join(Address mbr) {
028: wrongMethod("join");
029: }
030:
031: /**
032: * Loop: determine coord. If coord is me --> handleLeave().
033: * Else send handleLeave() to coord until success
034: */
035: public void leave(Address mbr) {
036: Address coord;
037: int max_tries = 3;
038: Object result;
039:
040: leave_promise.reset();
041:
042: if (mbr.equals(gms.local_addr))
043: leaving = true;
044:
045: while ((coord = gms.determineCoordinator()) != null
046: && max_tries-- > 0) {
047: if (gms.local_addr.equals(coord)) { // I'm the coordinator
048: gms.becomeCoordinator();
049: // gms.getImpl().handleLeave(mbr, false); // regular leave
050: gms.getImpl().leave(mbr); // regular leave
051: return;
052: }
053:
054: if (log.isDebugEnabled())
055: log.debug("sending LEAVE request to " + coord
056: + " (local_addr=" + gms.local_addr + ")");
057: sendLeaveMessage(coord, mbr);
058: synchronized (leave_promise) {
059: result = leave_promise.getResult(gms.leave_timeout);
060: if (result != null)
061: break;
062: }
063: }
064: gms.becomeClient();
065: }
066:
067: /** In case we get a different JOIN_RSP from a previous JOIN_REQ sent by us (as a client), we simply apply the
068: * new view if it is greater than ours
069: *
070: * @param join_rsp
071: */
072: public void handleJoinResponse(JoinRsp join_rsp) {
073: View v = join_rsp.getView();
074: ViewId tmp_vid = v != null ? v.getVid() : null;
075: if (tmp_vid != null && gms.view_id != null
076: && tmp_vid.compareTo(gms.view_id) > 0) {
077: gms.installView(v);
078: }
079: }
080:
081: public void handleLeaveResponse() {
082: if (leave_promise == null) {
083: if (log.isErrorEnabled())
084: log.error("leave_promise is null");
085: return;
086: }
087: synchronized (leave_promise) {
088: leave_promise.setResult(Boolean.TRUE); // unblocks thread waiting in leave()
089: }
090: }
091:
092: public void suspect(Address mbr) {
093: Collection emptyVector = new LinkedHashSet(0);
094: Collection suspected = new LinkedHashSet(1);
095: suspected.add(mbr);
096: handleMembershipChange(emptyVector, emptyVector, suspected);
097: }
098:
099: /** Removes previously suspected member from list of currently suspected members */
100: public void unsuspect(Address mbr) {
101: if (mbr != null)
102: suspected_mbrs.remove(mbr);
103: }
104:
105: public void handleMembershipChange(Collection newMembers,
106: Collection leavingMembers, Collection suspectedMembers) {
107: if (suspectedMembers == null || suspectedMembers.isEmpty())
108: return;
109:
110: for (Iterator i = suspectedMembers.iterator(); i.hasNext();) {
111: Address mbr = (Address) i.next();
112: if (!suspected_mbrs.contains(mbr))
113: suspected_mbrs.addElement(mbr);
114: }
115:
116: if (log.isDebugEnabled())
117: log.debug("suspected members=" + suspectedMembers
118: + ", suspected_mbrs=" + suspected_mbrs);
119:
120: if (wouldIBeCoordinator()) {
121: if (log.isDebugEnabled())
122: log.debug("members are " + gms.members + ", coord="
123: + gms.local_addr + ": I'm the new coord !");
124:
125: suspected_mbrs.removeAllElements();
126: gms.becomeCoordinator();
127: for (Iterator i = suspectedMembers.iterator(); i.hasNext();) {
128: Address mbr = (Address) i.next();
129: gms.getViewHandler().add(
130: new GMS.Request(GMS.Request.SUSPECT, mbr, true,
131: null));
132: gms.ack_collector.suspect(mbr);
133: }
134: }
135: }
136:
137: /**
138: * If we are leaving, we have to wait for the view change (last msg in the current view) that
139: * excludes us before we can leave.
140: * @param new_view The view to be installed
141: * @param digest If view is a MergeView, digest contains the seqno digest of all members and has to
142: * be set by GMS
143: */
144: public void handleViewChange(View new_view, Digest digest) {
145: Vector mbrs = new_view.getMembers();
146: if (log.isDebugEnabled())
147: log.debug("view=" + new_view);
148: suspected_mbrs.removeAllElements();
149: if (leaving && !mbrs.contains(gms.local_addr)) { // received a view in which I'm not member: ignore
150: return;
151: }
152: gms.installView(new_view, digest);
153: }
154:
155: /* public void handleSuspect(Address mbr) {
156: if(mbr == null) return;
157: if(!suspected_mbrs.contains(mbr))
158: suspected_mbrs.addElement(mbr);
159:
160: if(log.isDebugEnabled()) log.debug("suspected mbr=" + mbr + ", suspected_mbrs=" + suspected_mbrs);
161:
162: if(wouldIBeCoordinator()) {
163: if(log.isDebugEnabled()) log.debug("suspected mbr=" + mbr + "), members are " +
164: gms.members + ", coord=" + gms.local_addr + ": I'm the new coord !");
165:
166: suspected_mbrs.removeAllElements();
167: gms.becomeCoordinator();
168: // gms.getImpl().suspect(mbr);
169: gms.getViewHandler().add(new GMS.Request(GMS.Request.SUSPECT, mbr, true, null));
170: gms.ack_collector.suspect(mbr);
171: }
172: }*/
173:
174: public void handleMergeRequest(Address sender, ViewId merge_id) {
175: // only coords handle this method; reject it if we're not coord
176: sendMergeRejectedResponse(sender, merge_id);
177: }
178:
179: /* ---------------------------------- Private Methods --------------------------------------- */
180:
181: /**
182: * Determines whether this member is the new coordinator given a list of suspected members. This is
183: * computed as follows: the list of currently suspected members (suspected_mbrs) is removed from the current
184: * membership. If the first member of the resulting list is equals to the local_addr, then it is true,
185: * otherwise false. Example: own address is B, current membership is {A, B, C, D}, suspected members are {A,
186: * D}. The resulting list is {B, C}. The first member of {B, C} is B, which is equal to the
187: * local_addr. Therefore, true is returned.
188: */
189: boolean wouldIBeCoordinator() {
190: Address new_coord;
191: Vector mbrs = gms.members.getMembers(); // getMembers() returns a *copy* of the membership vector
192: mbrs.removeAll(suspected_mbrs);
193: if (mbrs.size() < 1)
194: return false;
195: new_coord = (Address) mbrs.elementAt(0);
196: return gms.local_addr.equals(new_coord);
197: }
198:
199: void sendLeaveMessage(Address coord, Address mbr) {
200: Message msg = new Message(coord, null, null);
201: GMS.GmsHeader hdr = new GMS.GmsHeader(GMS.GmsHeader.LEAVE_REQ,
202: mbr);
203:
204: msg.putHeader(gms.getName(), hdr);
205: gms.passDown(new Event(Event.MSG, msg));
206: }
207:
208: /* ------------------------------ End of Private Methods ------------------------------------ */
209:
210: }
|