public IEnumerator<ITask> PreJoinProdecure(List<BootstrapServer> BootstrapServerList) { bool attached = false; ulong bsTransId = 0; if (m_topology.LocalNode.Id == null) yield break; ReloadMessage reloadSendMsg; ReloadMessage reloadRcvMsg = null; /* This is the begin of populating the neighbor table convert local node to resource id + 1 and sent an attach to it */ Destination dest = new Destination(new ResourceId( m_topology.LocalNode.Id + (byte)1)); Destination last_destination = null; Node NextHopNode = null; int succSize = m_ReloadConfig.IamClient ? 1 : ReloadGlobals.SUCCESSOR_CACHE_SIZE; for (int i = 0; i < succSize; i++) { //if (last_destination != null && last_destination == dest) if (last_destination != null && last_destination.Equals(dest)) // markus: we have to use Equals method break; if (m_ReloadConfig.IamClient) reloadSendMsg = create_attach_req(dest, false); else reloadSendMsg = create_attach_req(dest, true); //we do not know the bootstrap peer's node id so far so we leave that parameter empty Node(null) ReloadDialog reloadDialog = null; int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; /* Modification for Clients out of draft, TLS stack will take some time * to initialize, add another 10s waiting */ if (m_ReloadConfig.IamClient && i == 0) RetransmissionTime += 10000; int iRetrans = ReloadGlobals.MaxRetransmissions; int iCycleBootstrap = 0; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { /* This is the first bootstrap contacting sequence if NextHopNode * is still zero, in any other case * use an attach to the node where we got the last answer from */ if (NextHopNode == null) { /* we could use a foreach loop, but CCR would multitask it, but we * want serialize that here */ if (iCycleBootstrap >= BootstrapServerList.Count()) iCycleBootstrap = 0; BootstrapServer bss = BootstrapServerList[iCycleBootstrap++]; if (attached == true) break; //TKTODO Rejoin of bootstrap server not solved List<IceCandidate> ics = new List<IceCandidate>(); IceCandidate ice = new IceCandidate(new IpAddressPort( AddressType.IPv4_Address, ReloadGlobals.IPAddressFromHost( m_ReloadConfig, bss.Host), (UInt16)bss.Port), Overlay_Link.TLS_TCP_FH_NO_ICE); // markus: change cand_type to bootstrap ice.cand_type = CandType.tcp_bootstrap; ics.Add(ice); NextHopNode = new Node(reloadRcvMsg == null ? null : reloadRcvMsg.OriginatorID, ics); } try { /* use a new ReloadDialog instance for every usage, Monitor requires it */ reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, NextHopNode); if (iCycleBootstrap > 0) { // save transaction id from request to bootstrap if (NextHopNode.IceCandidates[0].addr_port.ipaddr.ToString() == BootstrapServerList[iCycleBootstrap - 1].Host && NextHopNode.IceCandidates[0].addr_port.port == BootstrapServerList[iCycleBootstrap - 1].Port) bsTransId = reloadSendMsg.TransactionID; } m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} Dest={2} TransId={3:x16}", RELOAD_MessageCode.Attach_Request.ToString().PadRight(16, ' '), NextHopNode, dest.ToString(), reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>( reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: " + ex.Message); } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { if (reloadDialog.ReceivedMessage.TransactionID == bsTransId) { if (reloadDialog.ReceivedMessage.forwarding_header.via_list.Count == 1) { BootstrapServer bsServer = BootstrapServerList[iCycleBootstrap - 1]; bsServer.NodeId = reloadDialog.ReceivedMessage.forwarding_header.via_list[0].destination_data.node_id; BootstrapServerList.RemoveAt(iCycleBootstrap - 1); BootstrapServerList.Insert(iCycleBootstrap - 1, bsServer); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[0].destination_data.node_id)); //Console.WriteLine("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[0].destination_data.node_id); } else if (reloadDialog.ReceivedMessage.forwarding_header.via_list.Count == 2) { BootstrapServer bsServer = BootstrapServerList[iCycleBootstrap - 1]; bsServer.NodeId = reloadDialog.ReceivedMessage.forwarding_header.via_list[1].destination_data.node_id; BootstrapServerList.RemoveAt(iCycleBootstrap - 1); BootstrapServerList.Insert(iCycleBootstrap - 1, bsServer); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[1].destination_data.node_id)); //Console.WriteLine("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[1].destination_data.node_id); } bsTransId = 0; } break; } /* still bootstrapping, allow cycling trough different bootstraps by * resetting NextHopNode */ if (i == 0) NextHopNode = null; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; if (iRetrans >= 0) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Retrans {0} Attach {1} TransId={2:x16}", iRetrans, NextHopNode, reloadSendMsg.TransactionID)); m_statistics.IncRetransmission(); } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Failed! Attach {0} TransId={1:x16}", NextHopNode, reloadSendMsg.TransactionID)); m_statistics.IncTransmissionError(); if (ReloadGlobals.AutoExe) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoin: Exit because initial Attach Faild!"); m_machine.SendCommand("Exit"); } } } try { if (reloadDialog != null && !reloadDialog.Error && reloadDialog.ReceivedMessage != null) { //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message reloadRcvMsg = reloadDialog.ReceivedMessage; RELOAD_MessageCode msgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode; if (reloadRcvMsg != null) { if (msgCode == RELOAD_MessageCode.Attach_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} last={2} TransId={3:x16}", msgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.LastHopNodeId, reloadRcvMsg.TransactionID)); AttachReqAns answ = (AttachReqAns)reloadRcvMsg.reload_message_body; if (answ != null) { m_ReloadConfig.State = ReloadConfig.RELOAD_State.PreJoin; m_machine.StateUpdates(ReloadConfig.RELOAD_State.PreJoin); /* An Attach in and of itself does not result in updating the routing * table of either node. * Note: We use the routing table here only for storing ice candidates * for later use, we will not update successor or predecessor list */ NextHopNode = new Node(reloadRcvMsg.OriginatorID, answ.ice_candidates); /* An Attach in and of itself does not result in updating the routing * table of either node. * Note: We use the routing table here only for storing ice candidates * for later use, we will not update successor or predecessor list */ m_topology.routing_table.AddNode(NextHopNode); m_topology.routing_table.SetNodeState(NextHopNode.Id, NodeState.attached); if (CheckAndSetAdmittingPeer(NextHopNode) && NextHopNode.Id != reloadRcvMsg.LastHopNodeId) // Send ping to establish a physical connection Arbiter.Activate(m_DispatcherQueue, new IterativeTask<Destination, PingOption>(new Destination( NextHopNode.Id), PingOption.direct, SendPing)); if (m_ReloadConfig.IamClient) { m_ReloadConfig.LastJoinedTime = DateTime2.Now; TimeSpan joiningTime = m_ReloadConfig.LastJoinedTime - m_ReloadConfig.StartJoinMobile; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, "Join:" + joiningTime.TotalSeconds.ToString()); } attached = true; } } else if (msgCode == RELOAD_MessageCode.Error) { if (dest.type == DestinationType.node) { ErrorResponse error = (ErrorResponse)reloadRcvMsg.reload_message_body; if (error != null) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Prejoin: Got Error {0} from {1} deleting {2}", error.ErrorMsg, reloadRcvMsg.OriginatorID, dest.destination_data.node_id)); m_topology.routing_table.Leave(dest.destination_data.node_id); } } } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: reloadRcvMsg == null!!"); } last_destination = dest; dest = new Destination(new ResourceId(reloadRcvMsg.OriginatorID) + (byte)1); } else break; } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: " + ex.Message); } } // End Successor Search // FingerTable enrichment if (!m_ReloadConfig.IamClient) { List<FTEntry> fingers = m_topology.routing_table.AttachFingers(); Port<bool> attachNextPort = null; Boolean attachNext = true; /* JP SHOULD send Attach requests to initiate connections to each of * the peers in the neighbor table as well as to the desired finger * table entries. */ foreach (FTEntry finger in fingers) { attachNextPort = new Port<bool>(); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<FTEntry, Port<bool>>( finger, attachNextPort, AttachFinger)); /* Wait for finger attach */ yield return Arbiter.Receive(false, attachNextPort, next => { attachNext = next; }); if (!attachNext) break; } } /* see base -18 p.106 /* 4. JP MUST enter all the peers it has contacted into its routing /* table. */ m_topology.routing_table.Conn2Route(); /* Once JP has a reasonable set of connections it is ready to take its * place in the DHT. It does this by sending a Join to AP. */ if (m_ReloadConfig.AdmittingPeer != null) if (!m_ReloadConfig.IamClient) { m_ReloadConfig.State = ReloadConfig.RELOAD_State.Joining; m_machine.StateUpdates(ReloadConfig.RELOAD_State.Joining); m_topology.routing_table.SetWaitForJoinAnsw( m_ReloadConfig.AdmittingPeer.Id, true); reloadSendMsg = create_join_req( new Destination(m_ReloadConfig.AdmittingPeer.Id)); ReloadDialog reloadDialog = null; int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, m_ReloadConfig.AdmittingPeer); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", RELOAD_MessageCode.Join_Request.ToString().PadRight(16, ' '), m_ReloadConfig.AdmittingPeer, reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; if (iRetrans >= 0) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Retrans {0} Join {1} TransId={2:x16}", iRetrans, m_ReloadConfig.AdmittingPeer, reloadSendMsg.TransactionID)); m_statistics.IncRetransmission(); } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Failed! Join {0} TransId={1:x16}", m_ReloadConfig.AdmittingPeer, reloadSendMsg.TransactionID)); m_statistics.IncTransmissionError(); } } try { if (!reloadDialog.Error) { reloadRcvMsg = reloadDialog.ReceivedMessage; RELOAD_MessageCode msgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode; if (reloadRcvMsg != null) { if (msgCode == RELOAD_MessageCode.Join_Answer) { m_topology.routing_table.SetWaitForJoinAnsw(reloadRcvMsg.OriginatorID, false); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} TransId={2:x16}", msgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); NodeState nodestate = m_topology.routing_table.GetNodeState(reloadRcvMsg.OriginatorID); if (nodestate == NodeState.updates_received) { /* we previously received an update from admitting peer (maybe * race condition), now joining is complete in any other case * wait for updates to come from this node */ m_ReloadConfig.State = ReloadConfig.RELOAD_State.Joined; m_machine.StateUpdates(ReloadConfig.RELOAD_State.Joined); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("Joining completed")); m_ReloadConfig.LastJoinedTime = DateTime.Now; TimeSpan joiningTime = m_ReloadConfig.LastJoinedTime - m_ReloadConfig.StartJoining; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("Join:{0}", joiningTime.TotalSeconds.ToString())); m_topology.routing_table.SendUpdateToAllNeighbors(); } else { m_ReloadConfig.LastJoinedTime = DateTime.Now; TimeSpan joiningTime = m_ReloadConfig.LastJoinedTime - m_ReloadConfig.StartTime; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("Join:{0}", joiningTime.TotalSeconds.ToString())); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Prejoin: nodestate != update_recv at Node {0}", m_machine.ReloadConfig.ListenPort)); } //m_topology.routing_table.SendUpdatesToAllFingers(); } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: reloadRcvMsg == null!!"); } } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: " + ex.Message); } } else { if (m_ReloadConfig.SipUri == "") m_ReloadConfig.SipUri = String.Format("{0}@{1}", ReloadGlobals.HostName, m_ReloadConfig.OverlayName); if (m_ReloadConfig.SipUri != null && m_ReloadConfig.SipUri != "") { // explictite SIP registration as minimal config for RELOAD clients IUsage sipRegistration = m_machine.UsageManager.CreateUsage(Usage_Code_Point.SIP_REGISTRATION, 2, m_ReloadConfig.SipUri); sipRegistration.ResourceName = m_ReloadConfig.SipUri; List<StoreKindData> clientRegistrationList = new List<StoreKindData>(); StoreKindData sipKindData = new StoreKindData(sipRegistration.KindId, 0, new StoredData(sipRegistration.Encapsulate(true))); clientRegistrationList.Add(sipKindData); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<string, List<StoreKindData>>(m_ReloadConfig.SipUri, clientRegistrationList, Store)); } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("PreJoinPredure => Node {0} has no admitting peer = {1}!", m_machine.ReloadConfig.ListenPort, m_ReloadConfig.AdmittingPeer)); if (ReloadGlobals.AutoExe) { m_machine.SendCommand("Exit"); } } } // End PreJoin
public IEnumerator<ITask> AttachProcedure(Destination dest, NodeId NextHopId, AttachOption attach_option) { ReloadMessage reloadSendMsg; /* 9.5.1 * When a peer needs to Attach to a new peer in its neighbor table, it MUST source-route the Attach request through the peer from which it learned the new peer's Node-ID. Source-routing these requests allows the overlay to recover from instability. */ reloadSendMsg = create_attach_req(dest, (attach_option & AttachOption.forceupdate) != 0); if (dest.type == DestinationType.node) { NodeState nodestate = m_topology.routing_table.GetNodeState(dest.destination_data.node_id); if (nodestate == NodeState.attaching) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Ignoring redundant Attach for {0}", dest)); yield break; } } Boolean NextHopIsDestination = false; Node NextHopNode = null; if (NextHopId != null) NextHopNode = m_topology.routing_table.GetNode(NextHopId); if (NextHopNode == null) NextHopNode = NextHopToDestination(dest, ref NextHopIsDestination); if (NextHopNode == null) yield break; if (dest.type == DestinationType.node) m_topology.routing_table.SetNodeState(dest.destination_data.node_id, NodeState.attaching); ReloadDialog reloadDialog = null; int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { try { /* use a new ReloadDialog instance for every usage, Monitor requires it */ reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, NextHopNode); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} via {1} ==> Dest={2} TransId={3:x16}", RELOAD_MessageCode.Attach_Request.ToString().PadRight(16, ' '), NextHopNode, dest.ToString(), reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "AttachProcedure: " + ex.Message); yield break; } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (dest.type == DestinationType.node) { if (reloadRcvMsg.OriginatorID != dest.destination_data.node_id) { // drop message and retransmit request m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Received answer from unexpected peer")); reloadRcvMsg = null; } } else if (dest.type == DestinationType.resource) { int suc = m_topology.routing_table.GetSuccessorCount(false); int pre = m_topology.routing_table.GetPredecessorCount(false); if (suc >= 2 && pre >= 2) { // check if resource is mapping to a node in my routing table if (dest.destination_data.ressource_id.ElementOfInterval( m_topology.routing_table.Predecessors[pre - 2], m_topology.routing_table.Successors[suc - 1], true) ) { if (reloadRcvMsg.OriginatorID < m_topology.routing_table.Predecessors[pre - 2] && reloadRcvMsg.OriginatorID > m_topology.routing_table.Successors[suc - 1]) { // drop message and retransmit request m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Received answer from unexpected peer")); reloadRcvMsg = null; } } } } if (reloadRcvMsg != null) break; } /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; if (iRetrans >= 0) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Retrans {0} SendAttach via {1} TransId={2:x16}", iRetrans, NextHopNode, reloadSendMsg.TransactionID)); m_ReloadConfig.Statistics.IncRetransmission(); } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Failed! SendAttach via {0} TransId={1:x16}", NextHopNode, reloadSendMsg.TransactionID)); m_ReloadConfig.Statistics.IncTransmissionError(); if (dest.destination_data.node_id != null) { //m_topology.routing_table.SetNodeState(dest.destination_data.node_id, NodeState.unknown); m_topology.routing_table.Leave(dest.destination_data.node_id); } } } try { if (reloadDialog != null && !reloadDialog.Error && reloadDialog.ReceivedMessage != null) { /*the SourceNodeID delivered from reloadDialog comes from connection * table and is the last hop of the message */ ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; RELOAD_MessageCode msgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode; AttachReqAns answ = (AttachReqAns)reloadRcvMsg.reload_message_body; if (msgCode == RELOAD_MessageCode.Attach_Answer) { /* TKTODO * 1. The response to a message sent to a specific Node-ID MUST have been sent by that Node-ID. 2. The response to a message sent to a Resource-Id MUST have been sent by a Node-ID which is as close to or closer to the target Resource-Id than any node in the requesting node's neighbor table. */ if (answ != null) { Node Originator = new Node(reloadRcvMsg.OriginatorID, answ.ice_candidates); /* An Attach in and of itself does not result in updating the routing * table of either node. * Note: We use the routing table here only for storing ice candidates * for later use, we will not update successor or predecessor list */ m_topology.routing_table.AddNode(Originator); m_topology.routing_table.SetNodeState(Originator.Id, NodeState.attached); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} last={2} TransId={3:x16}", msgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.LastHopNodeId, reloadRcvMsg.TransactionID)); if ((CheckAndSetAdmittingPeer(Originator) && Originator.Id != reloadRcvMsg.LastHopNodeId) || (attach_option & AttachOption.sendping) != 0) { // Send ping to get a physical connection Arbiter.Activate(m_DispatcherQueue, new IterativeTask<Destination, PingOption>(new Destination(Originator.Id), PingOption.direct, SendPing)); } } } else if (msgCode == RELOAD_MessageCode.Error) { if (dest.type == DestinationType.node) { ErrorResponse error = (ErrorResponse)reloadRcvMsg.reload_message_body; if (error != null) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("AttachProcedure: Got Error {0} from {1} deleting {2}", error.ErrorMsg, reloadRcvMsg.OriginatorID, dest.destination_data.node_id)); m_topology.routing_table.Leave(dest.destination_data.node_id); } } } } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "AttachProcedure: " + ex.Message); if (dest.destination_data.node_id != null) m_topology.routing_table.SetNodeState(dest.destination_data.node_id, NodeState.unknown); } }
public IEnumerator<ITask> AppAttachProcedure(Destination dest) { ReloadMessage reloadSendMsg; reloadSendMsg = create_app_attach_req(dest); if (dest.type != DestinationType.node) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("AppAttachProcedure failed: unexpected destination type")); yield break; } if (dest.destination_data.node_id == m_topology.Id) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("local AppAttachProcedure dropped")); yield break; } Node node = m_topology.routing_table.FindNextHopTo(dest.destination_data.node_id, true, false); if (node == null) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("AppAttachProcedure: failed, did not found next hop to {0}", dest.destination_data.node_id)); yield break; } ReloadDialog reloadDialog = null; int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; m_topology.routing_table.SetNodeState(dest.destination_data.node_id, NodeState.attaching); while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { try { /* use a new ReloadDialog instance for every usage, Monitor requires it */ reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, node); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} via {1} ==> Dest={2} TransId={3:x16}", RELOAD_MessageCode.App_Attach_Request.ToString().PadRight(16, ' '), node, dest.ToString(), reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>( reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "AppAttachProcedure: " + ex.Message); } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (reloadRcvMsg.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.App_Attach_Answer) { AppAttachReqAns answ = (AppAttachReqAns)reloadRcvMsg.reload_message_body; if (answ != null) { node = new Node(reloadRcvMsg.OriginatorID, answ.ice_candidates); /* An Attach in and of itself does not result in updating the routing * table of either node. * Note: We use the routing table here only for storing ice candidates * for later use, we will not update successor or predecessor list */ m_topology.routing_table.AddNode(node); if (m_topology.routing_table.GetNodeState(node.Id) < NodeState.attached) m_topology.routing_table.SetNodeState(node.Id, NodeState.attached); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} last={2} TransId={3:x16}", reloadRcvMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.LastHopNodeId, reloadRcvMsg.TransactionID)); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_USAGE, String.Format("AppAttach returns IP: {0}", answ.ice_candidates[0].addr_port.ipaddr.ToString())); /* Proprietary registry interface function to support external clients */ ReloadGlobals.StoreRegAnswer("sip:" + answ.ice_candidates[0].addr_port.ipaddr.ToString() + ":5060"); m_ReloadConfig.ConnEstEnd = DateTime.Now; if (AppAttachDone != null) appAttachDone.Post(answ.ice_candidates[0]); if (ReloadGlobals.AutoExe) { TimeSpan appAttachTime = DateTime.Now - m_ReloadConfig.StartFetchAttach; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("Fetch:{0}", appAttachTime.TotalSeconds)); } } } else if (reloadRcvMsg.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Error) { // TODO } } else { m_topology.routing_table.SetNodeState(dest.destination_data.node_id, NodeState.unknown); } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "AppAttachProcedure: " + ex.Message); m_topology.routing_table.SetNodeState(dest.destination_data.node_id, NodeState.unknown); } }
/// <summary> /// The Fetch request retrieves one or more data elements stored at a /// given Resource-ID. A single Fetch request can retrieve multiple /// different kinds. /// /// RELOAD base -13 p.92 /// --alex /// </summary> /// <param name="resourceName">The resouces name (human readable)</param> /// <param name="specifiers">StoredSpecifier objects</param> /// <returns></returns> public IEnumerator<ITask> Fetch(string resourceName, List<StoredDataSpecifier> specifiers) { ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg; List<IUsage> recUsages = new List<IUsage>(); ResourceId res_id = new ResourceId(resourceName); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Fetch {0} as ResID: {1}", resourceName, res_id)); Node node = m_topology.routing_table.FindNextHopTo(new NodeId(res_id), true, false); if (m_ReloadConfig.IamClient && node == null) { node = m_ReloadConfig.AdmittingPeer; } List<Destination> dest_list = new List<Destination>(); dest_list.Add(new Destination(m_topology.LocalNode.Id)); List<FetchKindResponse> fetchKindResponses = new List<FetchKindResponse>(); FetchKindResponse fetchKindResponse = null; if (node == null || node.Id == m_ReloadConfig.LocalNodeID) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "Local Fetch."); m_ReloadConfig.StartFetchAttach = DateTime.Now; foreach (StoredDataSpecifier specifier in specifiers) { var responses = new List<FetchKindResponse>(); if (m_topology.Fetch(res_id, specifier, out fetchKindResponse)) { responses.Add(fetchKindResponse); foreach (StoredData sd in fetchKindResponse.values) { if (m_ReloadConfig.AccessController.validateDataSignature(res_id, fetchKindResponse.kind, sd)) recUsages.Add(sd.Value.GetUsageValue); else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "DATA SIGNATURE INVALID!!"); } m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Fetch successful, got {0}", sd.Value.GetUsageValue.Report())); } m_ReloadConfig.ConnEstEnd = DateTime.Now; } OnFetchedData(res_id, responses); } if (fetchDone != null) { if (recUsages.Count == 0) { foreach (StoredDataSpecifier specifier in specifiers) recUsages.Add(new NoResultUsage(specifier.ResourceName)); } fetchDone.Post(recUsages); } yield break; } else { reloadSendMsg = create_fetch_req(new Destination(res_id), specifiers); } int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, node); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("{0} ==> {1} TransId={2:x16}", reloadSendMsg.reload_message_body.RELOAD_MsgCode.ToString(). PadRight(16, ' '), node.Id, reloadSendMsg.TransactionID)); m_ReloadConfig.StartFetchAttach = DateTime.Now; Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>( reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { fetchDone.Post(new List<IUsage> { new NullUsage() }); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Fetch: " + ex.Message); } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; RELOAD_MessageCode recMsgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode; if (recMsgCode == RELOAD_MessageCode.Fetch_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} TransId={2:x16}", recMsgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); FetchAns answ = (FetchAns)reloadRcvMsg.reload_message_body; // TODO: For now add certificate to global PKC Store, but they are only temporarilly needed in validateDataSignature m_ReloadConfig.AccessController.SetPKCs(reloadRcvMsg.security_block.Certificates); if (answ != null) { fetchKindResponses = answ.KindResponses; foreach (FetchKindResponse kind in fetchKindResponses) { foreach (StoredData sd in kind.values) { if (m_ReloadConfig.AccessController.validateDataSignature(res_id, kind.kind, sd)) recUsages.Add(sd.Value.GetUsageValue); else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "DATA SIGNATURE INVALID!!"); } m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Fetch successful, got {0}", sd.Value.GetUsageValue.Report())); } } OnFetchedData(res_id, fetchKindResponses); if (fetchDone != null) { if (recUsages.Count == 0) { foreach (StoredDataSpecifier specifier in specifiers) recUsages.Add(new NoResultUsage(specifier.ResourceName)); } fetchDone.Post(recUsages); } } } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Fetch failed")); foreach (StoredDataSpecifier specifier in specifiers) recUsages.Add(new NoResultUsage(specifier.ResourceName)); fetchDone.Post(recUsages); m_statistics.IncTransmissionError(); } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Fetch: " + ex.Message); } }
public IEnumerator<ITask> SendUpdate(Node node, Node nexthopnode) { ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg; /*if (m_topology.routing_table.isFinger(node.Id)) m_topology.routing_table.AddFinger(node);*/ if (nexthopnode == null) nexthopnode = node; Destination dest = new Destination(node.Id); reloadSendMsg = create_update_req(dest, m_topology.routing_table, ChordUpdateType.neighbors); int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, nexthopnode); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", RELOAD_MessageCode.Update_Request.ToString().PadRight(16, ' '), node.Id, reloadSendMsg.TransactionID)); //m_ReloadConfig.start Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>( reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Update: " + ex.Message); yield break; } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; if (iRetrans > 0) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Retrans {0} SendUpdate {1}:{2} TransId={3:x16}", iRetrans, node, nexthopnode, reloadSendMsg.TransactionID)); m_statistics.IncRetransmission(); } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Failed! SendUpdate {0}:{1} TransId={2:x16}", node, nexthopnode, reloadSendMsg.TransactionID)); m_statistics.IncTransmissionError(); } } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; RELOAD_MessageCode msgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode; if (msgCode == RELOAD_MessageCode.Update_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} TransId={2:x16}", msgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); UpdateReqAns answ = (UpdateReqAns)reloadRcvMsg.reload_message_body; if (answ != null) { NodeId originator = reloadRcvMsg.OriginatorID; if (m_topology.routing_table.FingerSuccessors.Contains(originator)) { //m_topology.routing_table.GetNode(originator).Successors = answ.Successors; //m_topology.routing_table.GetNode(originator).Predecessors = answ.Predecessors; m_topology.routing_table.SetFingerState(originator, NodeState.updates_received); } if (m_topology.routing_table.RtTable.ContainsKey(originator.ToString())) { m_topology.routing_table.SetNodeState(originator, NodeState.updates_received); m_topology.routing_table.GetNode(originator).Successors = answ.Successors; m_topology.routing_table.GetNode(originator).Predecessors = answ.Predecessors; } } } } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Update: " + ex.Message); } }
/// <summary> /// Store Replicas: My next two successors have changed. Replicate my data /// </summary> /// <param name="node"></param> /// <returns></returns> public IEnumerator<ITask> StoreReplicas(NodeId node) { // For each Resource stored at this Peer, handover StoredData List<string> storedKeys; if ((storedKeys = m_topology.Storage.StoredKeys) != null && storedKeys.Count > 0) { m_topology.Storage.RemoveExpired(); Dictionary<ResourceId, List<StoreKindData>> nodes = new Dictionary<ResourceId, List<StoreKindData>>(); foreach (string key in storedKeys) { ResourceId res_id = new ResourceId(ReloadGlobals.HexToBytes(key)); if (!m_topology.Replicas.Contains(key)) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "Store Replicas - will send store requests"); if (!nodes.ContainsKey(res_id)) { nodes.Add(res_id, new List<StoreKindData>()); nodes[res_id].AddRange(m_topology.Storage.GetStoreKindData(key)); } else { nodes[res_id].AddRange(m_topology.Storage.GetStoreKindData(key)); } } } ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg; List<StoreKindData> storeKindData; foreach (ResourceId res_id in nodes.Keys) { storeKindData = nodes[res_id]; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "GOING TO REPLICATE UNDER RES_ID: " + res_id + " AT NODE: " + node); List<SignerIdentity> signers = new List<SignerIdentity>(); foreach (StoreKindData skd in storeKindData) { foreach (StoredData sd in skd.Values) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "STOREDATA: " + sd.Value.GetUsageValue.Report()); // add certificate if (!signers.Contains(sd.Signature.Identity)) signers.Add(sd.Signature.Identity); } } reloadSendMsg = create_store_req(new Destination(node), res_id, storeKindData, true); // get certificates for this data List<GenericCertificate> certs = new List<GenericCertificate>(); certs.AddRange(m_ReloadConfig.AccessController.GetPKCs(signers)); // add certificates to fetch answer reloadSendMsg.security_block.Certificates.AddRange(certs); int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Exit) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, m_topology.routing_table.FindNextHopTo(node, false, false)); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", reloadSendMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), node, reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store: " + ex.Message); } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (reloadRcvMsg.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Store_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} TransId={2:x16}", reloadRcvMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); //StoreReqAns answ = (StoreReqAns)reloadRcvMsg.reload_message_body; --old StoreAns answ = (StoreAns)reloadRcvMsg.reload_message_body; // --alex if (answ != null) { } } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Store Replica failed")); m_statistics.IncTransmissionError(); } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store Replica: " + ex.Message); } } } }
/// <summary> /// Handover key if: 1. leave overlay 2. I'm AP while a join req happens. /// </summary> /// <param name="fSendLeaveFirst"></param> /// <returns></returns> public IEnumerator<ITask> HandoverKeys(bool fSendLeaveFirst) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "Handover Keys!"); if (fSendLeaveFirst) { yield return Arbiter.ExecuteToCompletion(m_DispatcherQueue, new IterativeTask(Leave)); } // For each Resource stored at this Peer, handover StoredData List<string> storedKeys; if ((storedKeys = m_topology.Storage.StoredKeys) != null && storedKeys.Count > 0) { m_topology.Storage.RemoveExpired(); Dictionary<ResourceId, List<StoreKindData>> nodes = new Dictionary<ResourceId, List<StoreKindData>>(); Dictionary<ResourceId, Node> destinations = new Dictionary<ResourceId, Node>(); foreach (string key in storedKeys) { ResourceId res_id = new ResourceId(ReloadGlobals.HexToBytes(key)); Node currentNode = m_topology.routing_table.FindNextHopTo(new NodeId(res_id), true, fSendLeaveFirst); if (currentNode == null || currentNode.Id == m_ReloadConfig.LocalNodeID) { //everything's fine, key still belongs to me continue; } // REPLICATEST // peer is no longer in the replica set for the resource else if (m_topology.routing_table.Predecessors.Count > 2 && !res_id.ElementOfInterval(m_topology.routing_table.Predecessors[2], m_topology.LocalNode.Id, false)) { m_topology.Storage.Remove(res_id.ToString()); m_topology.Replicas.Remove(res_id.ToString()); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ALL, String.Format("Data {0} no longer in range. Delete replica", res_id.ToString())); } else { if (!m_topology.Replicas.Contains(key)) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "Handover Keys - will send store requests"); if (!nodes.ContainsKey(res_id)) { nodes.Add(res_id, new List<StoreKindData>()); nodes[res_id].AddRange(m_topology.Storage.GetStoreKindData(key)); destinations.Add(res_id, currentNode); } else { nodes[res_id].AddRange(m_topology.Storage.GetStoreKindData(key)); } } } } ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg; List<StoreKindData> storeKindData; foreach (ResourceId res_id in nodes.Keys) { Node node = destinations[res_id]; storeKindData = nodes[res_id]; List<SignerIdentity> signers = new List<SignerIdentity>(); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "GOING TO STORE UNDER RES_ID: " + res_id); foreach (StoreKindData skd in storeKindData) { foreach (StoredData sd in skd.Values) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, "STOREDATA: " + sd.Value.GetUsageValue.Report()); // add certificate if (!signers.Contains(sd.Signature.Identity)) signers.Add(sd.Signature.Identity); } } if (m_machine.ReloadConfig.State == ReloadConfig.RELOAD_State.Leave) { node = m_topology.routing_table.GetSuccessor(0); reloadSendMsg = create_store_req(new Destination(node.Id), res_id, storeKindData, false); } else { reloadSendMsg = create_store_req(new Destination(res_id), storeKindData, false); } // get certificates for this data List<GenericCertificate> certs = new List<GenericCertificate>(); certs.AddRange(m_ReloadConfig.AccessController.GetPKCs(signers)); // add certificates to fetch answer reloadSendMsg.security_block.Certificates.AddRange(certs); int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Exit) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, node); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", reloadSendMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), node.Id, reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store: " + ex.Message); } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (reloadRcvMsg.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Store_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} TransId={2:x16}", reloadRcvMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); //StoreReqAns answ = (StoreReqAns)reloadRcvMsg.reload_message_body; --old StoreAns answ = (StoreAns)reloadRcvMsg.reload_message_body; // --alex if (answ != null) { // m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Delete Key {0}", res_id)); // m_topology.StoredValues.Remove(StoredKey); --old // REPLICATEST // Keep stored data but mark it as replica if (!m_topology.Replicas.Contains(res_id.ToString())) m_topology.Replicas.Add(res_id.ToString()); //m_topology.Storage.Remove(res_id.ToString()); } } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Store failed")); m_statistics.IncTransmissionError(); } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store: " + ex.Message); } } } // this code might be redundant to code in RoutingTable.Leave() //// check if there are replicas I should be responsible for //if (m_topology.routing_table.Predecessors.Count == 0) //{ // m_topology.Replicas.Clear(); //} //else //{ // List<string> removeReplicas = new List<string>(); // foreach (string replica in m_topology.Replicas) // { // // Convert the Resource String in a ResourceId // int NumberChars = replica.Length; // byte[] bytes = new byte[NumberChars / 2]; // for (int i = 0; i < NumberChars; i += 2) // bytes[i / 2] = Convert.ToByte(replica.Substring(i, 2), 16); // ResourceId id = new ResourceId(bytes); // if (id.ElementOfInterval(m_topology.routing_table.Predecessors[0], m_topology.LocalNode.Id, false)) // { // m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ALL, String.Format("ResId: {0} is in interval [{1} - {2}]", id, m_topology.routing_table.Predecessors[0], m_topology.LocalNode.Id)); // removeReplicas.Add(replica); // } // } // foreach (string removeRep in removeReplicas) // { // m_topology.Replicas.Remove(removeRep); // Arbiter.Activate(m_ReloadConfig.DispatcherQueue, new IterativeTask<NodeId>(m_topology.routing_table.Successors[0], StoreReplicas)); // if(m_topology.routing_table.Successors.Count > 1) // Arbiter.Activate(m_ReloadConfig.DispatcherQueue, new IterativeTask<NodeId>(m_topology.routing_table.Successors[1], StoreReplicas)); // } //} if (m_ReloadConfig.State == ReloadConfig.RELOAD_State.Leave) m_machine.SendCommand("Exit"); if (fSendLeaveFirst) //this will reset neighbor tables m_topology.Leave(); }
/// <summary> /// Just the leaving Procedure /// </summary> /// <returns></returns> public IEnumerator<ITask> Leave() { m_ReloadConfig.State = ReloadConfig.RELOAD_State.Leave; foreach (ReloadConnectionTableInfoElement rce in m_flm.ConnectionTable) { if (m_topology.routing_table.RtTable.ContainsKey(rce.NodeID.ToString())) { ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg = create_leave_req(new Destination(rce.NodeID)); int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Exit) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, m_topology.routing_table.GetNode(rce.NodeID)); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", reloadSendMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), rce.NodeID, reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Leave: " + ex.Message); } if (reloadDialog != null) { yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; } /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { /*the SourceNodeID delivered from reloadDialog comes from * connection table and is the last hop of the message */ ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; RELOAD_MessageCode code = reloadRcvMsg.reload_message_body.RELOAD_MsgCode; if (code == RELOAD_MessageCode.Leave_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} TransId={2:x16}", code.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Leave failed")); m_statistics.IncTransmissionError(); } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Leave: " + ex.Message); } } } //m_machine.SendCommand("Exit"); // Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, Node>(reloadSendMsg, m_topology.routing_table.GetNode(rce.NodeID), Send)); // m_ReloadConfig.State = ReloadConfig.RELOAD_State.PreJoin; // m_machine.StateUpdates(ReloadConfig.RELOAD_State.PreJoin); }
// --josch /// <summary> /// Proprietary: Stores the Usage data in a different RELOAD overlay using viaGateWay as gateway /// </summary> /// <param name="ResourceName"></param> /// <param name="kind_data"></param> /// <param name="viaGateWay"></param> /// <returns></returns> public IEnumerator<ITask> Store(string ResourceName, List<StoreKindData> kind_data, NodeId viaGateWay) { if (m_ReloadConfig.IamClient) m_ReloadConfig.StartStoreMobile = DateTime2.Now; else m_ReloadConfig.StartStore = DateTime.Now; ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg; ResourceId res_id = new ResourceId(ResourceName); //List<StoreKindData> kind_data = new List<StoreKindData>(); Node node = null; if (viaGateWay != null) { //NodeId gateway = new ResourceId(viaGateWay); node = m_topology.routing_table.FindNextHopTo(viaGateWay, true, false); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_USAGE, String.Format("Store {0} as ResID: {1} via Gateway {2}", ResourceName, res_id, viaGateWay)); if (m_ReloadConfig.IamClient && node == null) { node = m_ReloadConfig.AdmittingPeer; } foreach (StoreKindData storeKindData in kind_data) { if (node == null || node.Id == m_ReloadConfig.LocalNodeID) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Local storage at NodeId {0}", node.Id)); m_topology.Store(res_id, storeKindData); yield break; } } Destination gateway = new Destination(new NodeId(viaGateWay.Data)); Destination storeDestination = new Destination(res_id); StoreReq storeRequest = new StoreReq(storeDestination.destination_data.ressource_id, kind_data, m_machine.UsageManager, false); reloadSendMsg = create_reload_message(gateway, ++m_ReloadConfig.TransactionID, storeRequest); reloadSendMsg.forwarding_header.destination_list.Add(storeDestination); //this is the real destination if (reloadSendMsg.AddDestinationOverlay(ResourceName)) m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "AddDestinationOverlay successful"); } else { res_id = new ResourceId(ResourceName); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_USAGE, String.Format("Store {0} as ResID: {1}", ResourceName, res_id)); node = m_topology.routing_table.FindNextHopTo(new NodeId(res_id), true, false); if (m_ReloadConfig.IamClient && node == null) { node = m_ReloadConfig.AdmittingPeer; } if (node == null || node.Id == m_ReloadConfig.LocalNodeID) { foreach (StoreKindData storeKindData in kind_data) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Local storage at NodeId {0}", node.Id)); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, "Store:0,011111"); m_topology.Store(res_id, storeKindData); } if (storeDone != null) storeDone.Post(reloadDialog); yield break; } reloadSendMsg = create_store_req(new Destination(res_id), kind_data, false); } int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Exit) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, node); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", reloadSendMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), node.Id, reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { storeDone.Post(reloadDialog); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store: " + ex.Message); ReloadGlobals.PrintException(m_ReloadConfig, ex); } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (reloadRcvMsg.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Store_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_USAGE, String.Format("Store successful:{0} <== {1} TransId={2:x16}", reloadRcvMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); m_ReloadConfig.EndStore = DateTime.Now; TimeSpan storeSpan = storeSpan = m_ReloadConfig.EndStore - m_ReloadConfig.StartStore; if (m_ReloadConfig.IamClient) storeSpan = DateTime2.Now - m_ReloadConfig.StartStoreMobile; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("Store:{0}", storeSpan.TotalSeconds.ToString())); if (storeDone != null) storeDone.Post(reloadDialog); } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Store failed")); m_statistics.IncTransmissionError(); } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store 2: " + ex.Message); ReloadGlobals.PrintException(m_ReloadConfig, ex); } if (m_ReloadConfig.State == ReloadConfig.RELOAD_State.Shutdown) m_machine.Finish(); }
public IEnumerator<ITask> SendPing(Destination dest, PingOption pingOption) { ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg; reloadSendMsg = create_ping_req(dest); int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; Boolean NextHopIsDestination = false; Node NextHopNode = NextHopToDestination(dest, ref NextHopIsDestination); if (NextHopNode == null) yield break; if (NextHopNode.Id == m_topology.LocalNode.Id) yield break; if (dest.type == DestinationType.node) { /* This code assumes, that a node we want to ping is already attached and added to the routing table */ NodeState nodestate = m_topology.routing_table.GetNodeState(dest.destination_data.node_id); bool pinging = m_topology.routing_table.GetPing(dest.destination_data.node_id); if (((pingOption & PingOption.standard | PingOption.finger) != 0) && nodestate == NodeState.unknown && !pinging) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Ignoring redundant Ping for {0}", dest)); yield break; } m_topology.routing_table.SetPinging(dest.destination_data.node_id, true, false); } else if (!NextHopIsDestination && ((pingOption & PingOption.direct) != 0)) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Direct Ping for {0} ignored, no entry in routing table", dest)); yield break; } /* Don't spend too much time on connectivity checks */ int iRetrans = 3; while (iRetrans > 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, NextHopNode); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", reloadSendMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), NextHopNode.Id, reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Ping: " + ex.Message); yield break; } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { PingReqAns answ = null; if (reloadDialog != null && !reloadDialog.Error && reloadDialog.ReceivedMessage != null) { //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (reloadRcvMsg.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Ping_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} <== {1} TransId={2:x16}", reloadRcvMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); answ = (PingReqAns)reloadRcvMsg.reload_message_body; if (answ != null) { if ((pingOption & PingOption.finger) != 0) { foreach (Topology.TopologyPlugin.RoutingTable.FTableEntry fte in m_topology.routing_table.FingerTable) { if (fte.Finger == dest.destination_data.ressource_id) { fte.dtLastSuccessfullFinger = DateTime.Now; fte.Successor = reloadRcvMsg.OriginatorID; fte.pinging = true; } } /* Attach if not attached */ if (!m_topology.routing_table.IsAttached(reloadRcvMsg.OriginatorID)) Arbiter.Activate(m_DispatcherQueue, new IterativeTask<Destination, NodeId, AttachOption>(new Destination(reloadRcvMsg.OriginatorID), reloadRcvMsg.LastHopNodeId, AttachOption.sendping, AttachProcedure)); else if (reloadRcvMsg.OriginatorID != reloadRcvMsg.LastHopNodeId)// Send ping to get/keep a physical connection Arbiter.Activate(m_DispatcherQueue, new IterativeTask<Destination, PingOption>(new Destination(reloadRcvMsg.OriginatorID), PingOption.direct, SendPing)); } } } } else { if (dest.type == DestinationType.node) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Ping failed: removing node {0}", dest.destination_data.node_id)); m_topology.routing_table.Leave(dest.destination_data.node_id); } m_statistics.IncTransmissionError(); } if (dest.type == DestinationType.node) m_topology.routing_table.SetPinging(dest.destination_data.node_id, false, answ != null); } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Ping: " + ex.Message); } }
/// <summary> /// Stores the Usage data in the RELOAD overlay /// </summary> /// <param name="ResourceName"></param> /// <param name="DestUrl"></param> /// <param name="exists">if true, stores the values, else stores a "non-existent" value.</param> /// <param name="usages">The Usage data to be stored.</param> /// <returns></returns> public IEnumerator<ITask> Store(string ResourceName, List<StoreKindData> kind_data) { if (m_ReloadConfig.IamClient) m_ReloadConfig.StartStoreMobile = DateTime2.Now; else m_ReloadConfig.StartStore = DateTime.Now; ReloadDialog reloadDialog = null; ReloadMessage reloadSendMsg; ResourceId res_id = new ResourceId(ResourceName); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_USAGE, String.Format("Store {0} as ResID: {1}", ResourceName, res_id)); Node node = m_topology.routing_table.FindNextHopTo(new NodeId(res_id), true, false); if (m_ReloadConfig.IamClient && node == null) { node = m_ReloadConfig.AdmittingPeer; } if (node == null || node.Id == m_ReloadConfig.LocalNodeID) { foreach (StoreKindData storeKindData in kind_data) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Local storage at NodeId {0}", node.Id)); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, "Store:0,011111"); m_topology.Store(res_id, storeKindData); } // REPLICATEST // incoming store request is not a replication request int numberReplicas = m_topology.routing_table.Successors.Count >= 2 ? 2 : m_topology.routing_table.Successors.Count; // Replica number is max 2 // send replica to all successors for (int i = 0; i < numberReplicas; i++) { NodeId successorNode = m_topology.routing_table.Successors[i]; ReloadMessage replica = create_store_req(new Destination(successorNode), res_id, kind_data, true); send(replica, m_topology.routing_table.GetNode(successorNode)); } if (storeDone != null) storeDone.Post(reloadDialog); yield break; } Destination dest = new Destination(res_id); reloadSendMsg = create_store_req(dest, kind_data, false); int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Exit) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, node); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", reloadSendMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), node.Id, reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception ex) { storeDone.Post(reloadDialog); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store: " + ex.Message); ReloadGlobals.PrintException(m_ReloadConfig, ex); break; } yield return Arbiter.Receive(false, reloadDialog.Done, done => { }); //if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null && reloadDialog.ReceivedMessage.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Store_Answer) // break; if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null && reloadDialog.ReceivedMessage.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Store_Answer) { ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (dest.type == DestinationType.node) { if (reloadRcvMsg.OriginatorID != dest.destination_data.node_id) { // drop message and retransmit request reloadRcvMsg = null; } } else if (dest.type == DestinationType.resource) { int suc = m_topology.routing_table.GetSuccessorCount(false); int pre = m_topology.routing_table.GetPredecessorCount(false); if (suc >= 2 && pre >= 2) { // check if resource is mapping to a node in my routing table if (dest.destination_data.ressource_id.ElementOfInterval( m_topology.routing_table.Predecessors[pre - 2], m_topology.routing_table.Successors[suc - 1], true) ) { if (reloadRcvMsg.OriginatorID < m_topology.routing_table.Predecessors[pre - 2] && reloadRcvMsg.OriginatorID > m_topology.routing_table.Successors[suc - 1]) { // drop message and retransmit request reloadRcvMsg = null; } } } } if (reloadRcvMsg != null) break; } /* If a response has not been received when the timer fires, the request is retransmitted with the same transaction identifier. */ --iRetrans; } try { if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) { //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; if (reloadRcvMsg.reload_message_body.RELOAD_MsgCode == RELOAD_MessageCode.Store_Answer) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_USAGE, String.Format("Store successful:{0} <== {1} TransId={2:x16}", reloadRcvMsg.reload_message_body.RELOAD_MsgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); m_ReloadConfig.EndStore = DateTime.Now; TimeSpan storeSpan = storeSpan = m_ReloadConfig.EndStore - m_ReloadConfig.StartStore; if (m_ReloadConfig.IamClient) storeSpan = DateTime2.Now - m_ReloadConfig.StartStoreMobile; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("Store:{0}", storeSpan.TotalSeconds.ToString())); if (storeDone != null) storeDone.Post(reloadDialog); } } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Store failed")); m_statistics.IncTransmissionError(); } } catch (Exception ex) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "Send Store 2: " + ex.Message); ReloadGlobals.PrintException(m_ReloadConfig, ex); } if (m_ReloadConfig.State == ReloadConfig.RELOAD_State.Shutdown) m_machine.Finish(); }
} // End PreJoin /// <summary> /// Attaches to a node needed to enrich the finger table. /// </summary> /// <param name="finger"></param> /// <returns></returns> public IEnumerator<ITask> AttachFinger(FTEntry finger, Port<bool> attachNext) { Destination dest = new Destination(finger.Finger); ReloadMessage reloadSendMsg = create_attach_req(dest, false); ReloadDialog reloadDialog = null; int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket; int iRetrans = ReloadGlobals.MaxRetransmissions; Boolean NextHopIsDestination = false; var myNodeId = m_topology.LocalNode.Id; Node nextHopNode = NextHopToDestination(dest, ref NextHopIsDestination); if (nextHopNode == null || nextHopNode.Id == m_ReloadConfig.LocalNodeID) nextHopNode = m_ReloadConfig.AdmittingPeer; if (nextHopNode == null) //{ m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("No Route to Finger! {0}", finger.Finger)); //attachNext.Post(true); // yield break; //} //else { while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown) { try { reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, nextHopNode); m_forwarding.LoopedTrans = new Port<UInt64>(); if (reloadDialog == null) m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, "ReloadDialog null!"); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Finger-{0} via {1} ==> Dest={2} TransId={3:x16}", RELOAD_MessageCode.Attach_Request.ToString().PadRight(16, ' '), nextHopNode, dest.ToString(), reloadSendMsg.TransactionID)); Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute)); } catch (Exception e) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("AttachFinger: " + e)); attachNext.Post(true); yield break; } bool gotLoop = false; yield return Arbiter.Choice( /* Success, Attached to finger */ Arbiter.Receive(false, reloadDialog.Done, done => { }), /* Loop detected */ Arbiter.Receive(false, m_forwarding.LoopedTrans, transId => { if (transId == reloadSendMsg.TransactionID) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Not re-sending transaction: {0:x16}=> a loopback detected!", reloadSendMsg.TransactionID)); gotLoop = true; m_forwarding.LoopedTrans = new Port<ulong>(); } })); if (gotLoop) { attachNext.Post(true); yield break; ; } if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null) break; // If a response has not been received when the timer fires, the request // is retransmitted with the same transaction identifier. --iRetrans; if (iRetrans >= 0) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Retrans {0} SendAttach via {1} TransId={2:x16}", iRetrans, nextHopNode, reloadSendMsg.TransactionID)); m_ReloadConfig.Statistics.IncRetransmission(); } else { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Failed! SendAttach via {0} TransId={1:x16}", nextHopNode, reloadSendMsg.TransactionID)); m_ReloadConfig.Statistics.IncTransmissionError(); if (dest.destination_data.node_id != null) m_topology.routing_table.SetNodeState(dest.destination_data.node_id, NodeState.unknown); } // } } try { if (reloadDialog != null && !reloadDialog.Error && reloadDialog.ReceivedMessage != null) { /*the SourceNodeID delivered from reloadDialog comes from connection * table and is the last hop of the message */ ReloadMessage reloadRcvMsg = reloadDialog.ReceivedMessage; RELOAD_MessageCode msgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode; AttachReqAns answ = null; if (msgCode == RELOAD_MessageCode.Attach_Answer) { answ = (AttachReqAns)reloadRcvMsg.reload_message_body; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TOPO, String.Format("Finger-{0} <== {1} TransId={2:x16}", msgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID, reloadRcvMsg.TransactionID)); Node originator = new Node(reloadRcvMsg.OriginatorID, answ.ice_candidates); NodeState nodeState = m_topology.routing_table.GetNodeState(originator.Id); if (nodeState == NodeState.unknown) { attachNext.Post(true); m_topology.routing_table.AddNode(originator); m_topology.routing_table.SetNodeState(originator.Id, NodeState.attached); m_topology.routing_table.AddFinger(originator, NodeState.attached); m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_USAGE, String.Format("Got a finger! {0}", originator.Id)); } /* we know this peer, further Attaches will return same peer */ else attachNext.Post(false); } } } catch (Exception e) { m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("AttachFingers:" + e)); } }