internal virtual void becomeSingletonMember(Address mbr) { Digest initial_digest; ViewId view_id = null; ArrayList mbrs = ArrayList.Synchronized(new ArrayList(1)); // set the initial digest (since I'm the first member) initial_digest = new Digest(1); // 1 member (it's only me) initial_digest.add(gms.local_addr, 0, 0); // initial seqno mcast by me will be 1 (highest seen +1) gms.Digest = initial_digest; view_id = new ViewId(mbr); // create singleton view with mbr as only member mbrs.Add(mbr); View v = new View(view_id, mbrs); v.CoordinatorGmsId = gms.unique_id; ArrayList subgroupMbrs = new ArrayList(); subgroupMbrs.Add(mbr); gms._subGroupMbrsMap[gms.subGroup_addr] = subgroupMbrs; gms._mbrSubGroupMap[mbr] = gms.subGroup_addr; v.SequencerTbl = gms._subGroupMbrsMap.Clone() as Hashtable; v.MbrsSubgroupMap = gms._mbrSubGroupMap.Clone() as Hashtable; v.AddGmsId(mbr, gms.unique_id); gms.installView(v); gms.becomeCoordinator(); // not really necessary - installView() should do it gms.Stack.IsOperational = true; gms.Stack.NCacheLog.Debug("pb.ClientGmsImpl.becomeSingletonMember()", "created group (first member). My view is " + gms.view_id + ", impl is " + gms.Impl.GetType().FullName); }
public override void down(Event evt) { Message msg; long time_to_wait, start_time; switch (evt.Type) { case Event.FIND_INITIAL_MBRS: // sent by GMS layer, pass up a GET_MBRS_OK event //We pass this event down to tcp so that it can take some measures. passDown(evt); initial_members.Clear(); msg = new Message(null, null, null); msg.putHeader(HeaderType.TCPPING, new PingHeader(PingHeader.GET_MBRS_REQ, (System.Object)local_addr, group_addr)); // if intitial nodes have been specified and static is true, then only those // members will form the cluster, otherwise, nodes having the same IP Multicast and port // will form the cluster dyanamically. mbrDiscoveryInProcess = true; lock (members.SyncRoot) { if (initial_hosts != null) { for (System.Collections.IEnumerator it = initial_hosts.GetEnumerator(); it.MoveNext();) { Address addr = (Address)it.Current; msg.Dest = addr; if (Stack.NCacheLog.IsInfoEnabled) { Stack.NCacheLog.Info("[FIND_INITIAL_MBRS] sending PING request to " + msg.Dest); } passDown(new Event(Event.MSG_URGENT, msg.copy(), Priority.Critical)); } } } // 2. Wait 'timeout' ms or until 'num_initial_members' have been retrieved if (Stack.NCacheLog.IsInfoEnabled) { Stack.NCacheLog.Info("TcpPing.down()", "[FIND_INITIAL_MBRS] waiting for results..............."); } lock (initial_members.SyncRoot) { start_time = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; time_to_wait = timeout; while (initial_members.Count < num_initial_members && time_to_wait > 0) { try { if (Stack.NCacheLog.IsInfoEnabled) { Stack.NCacheLog.Info("TcpPing.down()", "initial_members Count: " + initial_members.Count + "initialHosts Count: " + num_initial_members); } if (Stack.NCacheLog.IsInfoEnabled) { Stack.NCacheLog.Info("TcpPing.down()", "Time to wait for next response: " + time_to_wait); } ///Big_clusterd: initial members will be pulsed in case connection is not available. ///so here we dont have to wait till each member is timed out. ///this significantly improves time for initial member discovery. bool timeExpire = System.Threading.Monitor.Wait(initial_members.SyncRoot, TimeSpan.FromMilliseconds(time_to_wait)); } catch (System.Exception e) { Stack.NCacheLog.Error("TCPPing.down(FIND_INITIAL_MBRS)", e.ToString()); } time_to_wait = timeout - ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start_time); } mbrDiscoveryInProcess = false; } if (Stack.NCacheLog.IsInfoEnabled) { Stack.NCacheLog.Info("TcpPing.down()", "[FIND_INITIAL_MBRS] initial members are " + Global.CollectionToString(initial_members)); } if (Stack.NCacheLog.IsInfoEnabled) { Stack.NCacheLog.Info("TcpPing.down()", "[FIND_INITIAL_MBRS] initial members count " + initial_members.Count); } //remove those which are not functional due to twoPhaseConnect for (int i = initial_members.Count - 1; i >= 0; i--) { PingRsp rsp = initial_members[i] as PingRsp; if (!rsp.IsStarted) { initial_members.RemoveAt(i); } } // 3. Send response passUp(new Event(Event.FIND_INITIAL_MBRS_OK, initial_members)); break; case Event.TMP_VIEW: case Event.VIEW_CHANGE: System.Collections.ArrayList tmp; if ((tmp = ((View)evt.Arg).Members) != null) { lock (members.SyncRoot) { members.Clear(); members.AddRange(tmp); } } passDown(evt); break; /****************************After removal of NackAck *********************************/ //TCPPING emulates a GET_DIGEST call, which is required by GMS. This is needed //since we have now removed NAKACK from the stack! case Event.GET_DIGEST: pbcast.Digest digest = new pbcast.Digest(members.Count); for (int i = 0; i < members.Count; i++) { Address sender = (Address)members[i]; digest.add(sender, 0, 0); } passUp(new Event(Event.GET_DIGEST_OK, digest)); return; case Event.SET_DIGEST: // Not needed! Just here to let you know that it is needed by GMS! return; /********************************************************************************/ case Event.BECOME_SERVER: // called after client has joined and is fully working group member if (Stack.NCacheLog.IsInfoEnabled) { Stack.NCacheLog.Info("TcpPing.down()", "received BECOME_SERVER event"); } passDown(evt); is_server = true; break; case Event.CONNECT: object[] addrs = ((object[])evt.Arg); group_addr = (string)addrs[0]; subGroup_addr = (string)addrs[1]; twoPhaseConnect = (bool)addrs[3]; if (twoPhaseConnect) { timeout = 1000; } passDown(evt); break; case Event.DISCONNECT: passDown(evt); break; case Event.HAS_STARTED: hasStarted = true; passDown(evt); break; default: passDown(evt); // Pass on to the layer below us break; } }
public override void down(Event evt) { Message msg; long time_to_wait, start_time; switch (evt.Type) { case Event.FIND_INITIAL_MBRS: // sent by GMS layer, pass up a GET_MBRS_OK event //We pass this event down to tcp so that it can take some measures. passDown(evt); initial_members.Clear(); msg = new Message(null, null, null); msg.putHeader(HeaderType.TCPPING, new PingHeader(PingHeader.GET_MBRS_REQ, (System.Object)local_addr,group_addr)); // if intitial nodes have been specified and static is true, then only those // members will form the cluster, otherwise, nodes having the same IP Multicast and port // will form the cluster dyanamically. mbrDiscoveryInProcess = true; lock (members.SyncRoot) { if( initial_hosts != null) { for (System.Collections.IEnumerator it = initial_hosts.GetEnumerator(); it.MoveNext(); ) { Address addr = (Address) it.Current; msg.Dest = addr; if(Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("[FIND_INITIAL_MBRS] sending PING request to " + msg.Dest); passDown(new Event(Event.MSG_URGENT, msg.copy(), Priority.Critical)); } } } // 2. Wait 'timeout' ms or until 'num_initial_members' have been retrieved if(Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("TcpPing.down()", "[FIND_INITIAL_MBRS] waiting for results..............."); lock (initial_members.SyncRoot) { start_time = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; time_to_wait = timeout; while (initial_members.Count < num_initial_members && time_to_wait > 0) { try { if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("TcpPing.down()", "initial_members Count: " + initial_members.Count + "initialHosts Count: " + num_initial_members); if (Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("TcpPing.down()", "Time to wait for next response: " + time_to_wait); ///Big_clusterd: initial members will be pulsed in case connection is not available. ///so here we dont have to wait till each member is timed out. ///this significantly improves time for initial member discovery. bool timeExpire = System.Threading.Monitor.Wait(initial_members.SyncRoot, TimeSpan.FromMilliseconds(time_to_wait)); } catch (System.Exception e) { Stack.NCacheLog.Error("TCPPing.down(FIND_INITIAL_MBRS)", e.ToString()); } time_to_wait = timeout - ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start_time); } mbrDiscoveryInProcess = false; } if(Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("TcpPing.down()", "[FIND_INITIAL_MBRS] initial members are " + Global.CollectionToString(initial_members)); if(Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("TcpPing.down()", "[FIND_INITIAL_MBRS] initial members count " + initial_members.Count); //remove those which are not functional due to twoPhaseConnect for (int i = initial_members.Count - 1; i >= 0; i--) { PingRsp rsp = initial_members[i] as PingRsp; if (!rsp.IsStarted) initial_members.RemoveAt(i); } // 3. Send response passUp(new Event(Event.FIND_INITIAL_MBRS_OK, initial_members)); break; case Event.TMP_VIEW: case Event.VIEW_CHANGE: System.Collections.ArrayList tmp; if ((tmp = ((View) evt.Arg).Members) != null) { lock (members.SyncRoot) { members.Clear(); members.AddRange(tmp); } } passDown(evt); break; /****************************After removal of NackAck *********************************/ //TCPPING emulates a GET_DIGEST call, which is required by GMS. This is needed //since we have now removed NAKACK from the stack! case Event.GET_DIGEST: pbcast.Digest digest = new pbcast.Digest(members.Count); for (int i = 0; i < members.Count; i++) { Address sender = (Address)members[i]; digest.add(sender, 0, 0); } passUp(new Event(Event.GET_DIGEST_OK, digest)); return; case Event.SET_DIGEST: // Not needed! Just here to let you know that it is needed by GMS! return; /********************************************************************************/ case Event.BECOME_SERVER: // called after client has joined and is fully working group member if(Stack.NCacheLog.IsInfoEnabled) Stack.NCacheLog.Info("TcpPing.down()", "received BECOME_SERVER event"); passDown(evt); is_server = true; break; case Event.CONNECT: object[] addrs = ((object[])evt.Arg); group_addr = (string)addrs[0]; subGroup_addr = (string)addrs[1]; twoPhaseConnect = (bool)addrs[3]; if (twoPhaseConnect) timeout = 1000; passDown(evt); break; case Event.DISCONNECT: passDown(evt); break; case Event.HAS_STARTED: hasStarted = true; passDown(evt); break; default: passDown(evt); // Pass on to the layer below us break; } }
/// <summary> Computes the new view (including the newly joined member) and get the digest from PBCAST. /// Returns both in the form of a JoinRsp /// </summary> public override JoinRsp handleJoin(Address mbr, string subGroup_name, bool isStartedAsMirror, string gmsId, ref bool acquireHashmap) { lock (this) { System.Collections.ArrayList new_mbrs = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1)); View v = null; Digest d, tmp; gms.Stack.NCacheLog.CriticalInfo("CoordGmsImpl.handleJoin", "mbr=" + mbr); if (gms.local_addr.Equals(mbr)) { gms.Stack.NCacheLog.Error("CoordGmsImpl.handleJoin", "cannot join myself !"); return null; } if (gms.members.contains(mbr)) { gms.Stack.NCacheLog.Error("CoordGmsImpl.handleJoin()", "member " + mbr + " already present; returning existing view " + Global.CollectionToString(gms.members.Members)); acquireHashmap = false; View view = new View(gms.view_id, gms.members.Members); view.CoordinatorGmsId = gms.unique_id; JoinRsp rsp = new JoinRsp(view, gms.Digest); rsp.View.SequencerTbl = gms._subGroupMbrsMap; rsp.View.MbrsSubgroupMap = gms._mbrSubGroupMap; return rsp; // already joined: return current digest and membership } new_mbrs.Add(mbr); //===================================== // update the subGroupMbrsMap and mbrSubGroupMap if (gms._subGroupMbrsMap.Contains(subGroup_name)) { lock (gms._subGroupMbrsMap.SyncRoot) { System.Collections.ArrayList groupMbrs = (System.Collections.ArrayList)gms._subGroupMbrsMap[subGroup_name]; if (!groupMbrs.Contains(mbr)) groupMbrs.Add(mbr); } } else { lock (gms._subGroupMbrsMap.SyncRoot) { System.Collections.ArrayList groupMbrs = new System.Collections.ArrayList(); groupMbrs.Add(mbr); gms._subGroupMbrsMap[subGroup_name] = groupMbrs; } } if (!gms._mbrSubGroupMap.Contains(mbr)) { lock (gms._mbrSubGroupMap.SyncRoot) { gms._mbrSubGroupMap[mbr] = subGroup_name; } } //===================================== tmp = gms.Digest; // get existing digest if (tmp == null) { gms.Stack.NCacheLog.Error("CoordGmsImpl.handleJoin", "received null digest from GET_DIGEST: will cause JOIN to fail"); return null; } gms.Stack.NCacheLog.Debug("got digest=" + tmp); d = new Digest(tmp.size() + 1); // create a new digest, which contains 1 more member d.add(tmp); // add the existing digest to the new one d.add(mbr, 0, 0); // ... and add the new member. it's first seqno will be 1 v = gms.getNextView(new_mbrs, null, null); v.SequencerTbl = gms._subGroupMbrsMap; v.MbrsSubgroupMap = gms._mbrSubGroupMap; v.AddGmsId(mbr, gmsId); //add coordinator own's gms id[bug fix]; so that new member could know cordinator id v.AddGmsId(gms.local_addr, gms.unique_id); if (gms.GmsIds != null) { Hashtable gmsIds = gms.GmsIds.Clone() as Hashtable; IDictionaryEnumerator ide = gmsIds.GetEnumerator(); while (ide.MoveNext()) { v.AddGmsId((Address)ide.Key,(string) ide.Value); } } gms.Stack.NCacheLog.Debug("joined member " + mbr + ", view is " + v); return new JoinRsp(v, d); } }