} // only processed by coords public virtual void handleMergeView(MergeData data, object merge_id) { ; } // only processed by coords
/// <summary> Sends the new view and digest to all subgroup coordinors in coords. Each coord will in turn /// <ol> /// <li>cast the new view and digest to all the members of its subgroup (MergeView) /// <li>on reception of the view, if it is a MergeView, each member will set the digest and install /// the new view /// </ol> /// </summary> internal virtual void sendMergeView(System.Collections.ArrayList coords, MergeData combined_merge_data) { Message msg; GMS.HDR hdr; Address coord; View v; Digest d; if (coords == null || combined_merge_data == null) return; v = combined_merge_data.view; d = combined_merge_data.digest; if (v == null || d == null) { gms.Stack.NCacheLog.Error("view or digest is null, cannot send consolidated merge view/digest"); return; } for (int i = 0; i < coords.Count; i++) { coord = (Address)coords[i]; msg = new Message(coord, null, null); hdr = new GMS.HDR(GMS.HDR.INSTALL_MERGE_VIEW); hdr.view = v; hdr.digest = d; hdr.merge_id = merge_id; msg.putHeader(HeaderType.GMS, hdr); gms.passDown(new Event(Event.MSG, msg)); } }
/// <summary> Merge all MergeData. All MergeData elements should be disjunct (both views and digests). However, /// this method is prepared to resolve duplicate entries (for the same member). Resolution strategy for /// views is to merge only 1 of the duplicate members. Resolution strategy for digests is to take the higher /// seqnos for duplicate digests.<p> /// After merging all members into a Membership and subsequent sorting, the first member of the sorted membership /// will be the new coordinator. /// </summary> /// <param name="v">A list of MergeData items. Elements with merge_rejected=true were removed before. Is guaranteed /// not to be null and to contain at least 1 member. /// </param> internal virtual MergeData consolidateMergeData(System.Collections.ArrayList v) { MergeData ret = null; MergeData tmp_data; long logical_time = 0; // for new_vid ViewId new_vid, tmp_vid; MergeView new_view; View tmp_view; Membership new_mbrs = new Membership(); int num_mbrs = 0; Digest new_digest = null; Address new_coord; System.Collections.ArrayList subgroups = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(11)); // contains a list of Views, each View is a subgroup for (int i = 0; i < v.Count; i++) { tmp_data = (MergeData)v[i]; gms.Stack.NCacheLog.Debug("merge data is " + tmp_data); tmp_view = tmp_data.View; if (tmp_view != null) { tmp_vid = tmp_view.Vid; if (tmp_vid != null) { // compute the new view id (max of all vids +1) logical_time = System.Math.Max(logical_time, tmp_vid.Id); } } // merge all membership lists into one (prevent duplicates) new_mbrs.add(tmp_view.Members); subgroups.Add(tmp_view.Clone()); } // the new coordinator is the first member of the consolidated & sorted membership list new_mbrs.sort(); num_mbrs = new_mbrs.size(); new_coord = num_mbrs > 0 ? (Address)new_mbrs.elementAt(0) : null; if (new_coord == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.consolodateMergeData", "new_coord is null."); return null; } // should be the highest view ID seen up to now plus 1 new_vid = new ViewId(new_coord, logical_time + 1); // determine the new view new_view = new MergeView(new_vid, new_mbrs.Members, subgroups); gms.Stack.NCacheLog.Debug("new merged view will be " + new_view); // determine the new digest new_digest = consolidateDigests(v, num_mbrs); if (new_digest == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.consolidateMergeData", "digest could not be consolidated."); return null; } gms.Stack.NCacheLog.Debug("consolidated digest=" + new_digest); ret = new MergeData(gms.local_addr, new_view, new_digest); return ret; }
/// <summary> If merge_id != this.merge_id --> discard /// Else cast the view/digest to all members of this group. /// </summary> public override void handleMergeView(MergeData data, object merge_id) { if (merge_id == null || this.merge_id == null || !this.merge_id.Equals(merge_id)) { gms.Stack.NCacheLog.Error("CoordGmsImpl.handleMergeView", "merge_ids don't match (or are null); merge view discarded"); return; } gms.castViewChange(data.view, data.digest); merging = false; merge_id = null; }
public override void handleMergeResponse(MergeData data, object merge_id) { if (data == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.handleMergeResponse", "merge data is null"); return; } if (merge_id == null || this.merge_id == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.handleMergeResponse", "merge_id (" + merge_id + ") or this.merge_id (" + this.merge_id + ") == null (sender=" + data.Sender + ")."); return; } if (!this.merge_id.Equals(merge_id)) { gms.Stack.NCacheLog.Error("CoordGmsImpl.handleMergeResponse", "this.merge_id (" + this.merge_id + ") is different from merge_id (" + merge_id + ')'); return; } lock (merge_rsps.SyncRoot) { if (!merge_rsps.Contains(data)) { merge_rsps.Add(data); System.Threading.Monitor.PulseAll(merge_rsps.SyncRoot); } } }
internal virtual MergeData getMergeResponse(Address sender, object merge_id) { Digest digest; View view; MergeData retval; if (sender == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.getMergeResponse", "sender == null; cannot send back a response"); return null; } if (merging) { gms.Stack.NCacheLog.Error("CoordGmsImpl.getMergeResponse", "merge already in progress"); retval = new MergeData(sender, null, null); retval.merge_rejected = true; return retval; } merging = true; this.merge_id = merge_id; gms.Stack.NCacheLog.Debug("sender=" + sender + ", merge_id=" + merge_id); digest = gms.Digest; view = new View(gms.view_id.Copy(), gms.members.Members); retval = new MergeData(sender, view, digest); retval.view = view; retval.digest = digest; return retval; }
public override void up(Event evt) { object obj; Message msg; HDR hdr; MergeData merge_data; switch (evt.Type) { case Event.MSG: msg = (Message)evt.Arg; obj = msg.getHeader(HeaderType.GMS); if (obj == null || !(obj is HDR)) break; hdr = (HDR)msg.removeHeader(HeaderType.GMS); switch (hdr.type) { case HDR.JOIN_REQ: object[] args = new object[4]; args[0] = hdr.mbr; args[1] = hdr.subGroup_name; args[2] = hdr.isStartedAsMirror; args[3] = hdr.GMSId; ThreadPool.QueueUserWorkItem(new WaitCallback(handleJoinrequestAsync), args); break; case HDR.SPECIAL_JOIN_REQUEST: HandleSpecialJoinRequest(hdr.mbr, hdr.GMSId); break; case HDR.JOIN_RSP: MarkStateTransferInProcess(); impl.handleJoinResponse(hdr.join_rsp); break; case HDR.LEAVE_REQ: Stack.NCacheLog.Debug("received LEAVE_REQ " + hdr + " from " + msg.Src); if (hdr.mbr == null) { Stack.NCacheLog.Error( "LEAVE_REQ's mbr field is null"); return; } if (isPartReplica && IsCoordinator) { //if replica node on the coordinator is leaving then send a special event to TCP //to mark himself leaving. This way other node asking for death status through keep //alive will get dead status. if (hdr.mbr != null && hdr.mbr.IpAddress.Equals(local_addr.IpAddress)) { down(new Event(Event.I_AM_LEAVING)); } } ThreadPool.QueueUserWorkItem(new WaitCallback(handleLeaveAsync), new object[] { hdr.mbr, false }); break; case HDR.LEAVE_RSP: impl.handleLeaveResponse(); break; case HDR.VIEW_RESPONSE: if (_promise != null) _promise.SetResult(hdr.arg); break; case HDR.VIEW: if (hdr.view == null) { Stack.NCacheLog.Error("[VIEW]: view == null"); return; } else Stack.NCacheLog.CriticalInfo("gms.Up", "received view from :" + msg.Src + " ; view = " + hdr.view); impl.handleViewChange(hdr.view, hdr.digest); break; case HDR.MERGE_REQ: impl.handleMergeRequest(msg.Src, hdr.merge_id); break; case HDR.MERGE_RSP: merge_data = new MergeData(msg.Src, hdr.view, hdr.digest); merge_data.merge_rejected = hdr.merge_rejected; impl.handleMergeResponse(merge_data, hdr.merge_id); break; case HDR.INSTALL_MERGE_VIEW: impl.handleMergeView(new MergeData(msg.Src, hdr.view, hdr.digest), hdr.merge_id); break; case HDR.CANCEL_MERGE: impl.handleMergeCancelled(hdr.merge_id); break; case HDR.CAN_NOT_CONNECT_TO: impl.handleCanNotConnectTo(msg.Src, hdr.nodeList); break; case HDR.LEAVE_CLUSTER: string gmsId = hdr.arg as string;//reported gms id string myGmsId = GetNodeGMSId(local_addr); if (gmsId != null && myGmsId != null && gmsId.Equals(myGmsId)) { ThreadPool.QueueUserWorkItem(new WaitCallback(handleLeaveClusterRequestAsync), hdr.mbr); } break; case HDR.CONNECTION_BROKEN: impl.handleConnectionBroken(msg.Src, hdr.mbr); break; case HDR.VIEW_REJECTED: impl.handleViewRejected(hdr.mbr); break; case HDR.INFORM_NODE_REJOINING: impl.handleInformNodeRejoining(msg.Src, hdr.mbr); break; case HDR.RESET_ON_NODE_REJOINING: impl.handleResetOnNodeRejoining(msg.Src, hdr.mbr, hdr.view); break; case HDR.RE_CHECK_CLUSTER_HEALTH: Thread t = new Thread(new ParameterizedThreadStart(impl.ReCheckClusterHealth)); t.Start(hdr.mbr); break; case HDR.INFORM_ABOUT_NODE_DEATH: //Replica is not supposed to handle this event if (isPartReplica && _startedAsMirror) break; impl.handleInformAboutNodeDeath(msg.Src, (Address)hdr.arg); break; case HDR.IS_NODE_IN_STATE_TRANSFER: impl.handleIsClusterInStateTransfer(msg.Src); break; case HDR.IS_NODE_IN_STATE_TRANSFER_RSP: if (_stateTransferPromise != null) { if(Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("gms.UP", "(state transfer rsp) sender: " + msg.Src + " ->" + hdr.arg); _stateTransferPromise.SetResult(hdr.arg); } break; default: Stack.NCacheLog.Error( "HDR with type=" + hdr.type + " not known"); break; } return; // don't pass up case Event.CONNECT_OK: // sent by someone else, but WE are responsible for sending this ! case Event.DISCONNECT_OK: // dito (e.g. sent by UDP layer). Don't send up the stack return; case Event.GET_NODE_STATUS_OK: lock (suspect_verify_mutex) { NodeStatus status = evt.Arg as NodeStatus; if (status.Node != null && status.Node.Equals(nodeTobeSuspect)) { nodeStatus = status; Monitor.PulseAll(suspect_verify_mutex); } } break; case Event.SET_LOCAL_ADDRESS: local_addr = (Address)evt.Arg; break; // pass up case Event.SUSPECT: ThreadPool.QueueUserWorkItem(new WaitCallback(handleSuspectAsync), evt.Arg); break; // pass up case Event.UNSUSPECT: impl.unsuspect((Address)evt.Arg); return; // discard case Event.MERGE: impl.merge((System.Collections.ArrayList)evt.Arg); return; // don't pass up case Event.CONNECTION_FAILURE: impl.handleConnectionFailure(evt.Arg as ArrayList); return;//dont passup case Event.NODE_REJOINING: impl.handleNodeRejoining(evt.Arg as Address); return; case Event.CONNECTION_BREAKAGE: Address node = evt.Arg as Address; if (!disconnected_nodes.Contains(node)) disconnected_nodes.Add(node); break; case Event.CONNECTION_RE_ESTABLISHED: node = evt.Arg as Address; if (disconnected_nodes.Contains(node)) disconnected_nodes.Remove(node); break; } if (impl.handleUpEvent(evt)) passUp(evt); }