private void GetSuccessorTable(CorrelationId operationId, NodeInfo applicantInfo) { var assembledReply = new GetSuccessorTableReply(_node.Identity, applicantInfo, operationId) { SuccessorTable = new RoutingTableEntry[_node.Config.SuccessorCount], }; var totalTimeout = _node.Config.SuccessorCount * _node.Config.AwaitSettings.NetworkQueryTimeout; var multiReplyHandler = _node.CreateAwaitAllResponsesHandler(); multiReplyHandler .PerformAction(() => { var thisNode = _node.Identity; var initialMessage = new GetSuccessorTable(thisNode, thisNode, operationId) { Applicant = applicantInfo, SuccessorTable = new RoutingTableEntry[_node.Config.SuccessorCount], HopCount = 0, }; _node.Log($"Sending {initialMessage.TypeName()} To {initialMessage.To} Id:{initialMessage.CorrelationId}"); _commMgr.SendInternal(initialMessage); }) .AndAwait(operationId, (GetSuccessorTableReply successorReply) => { assembledReply.SuccessorTable = successorReply.SuccessorTable; }) .ContinueWith(() => { // Merge the result back with the parent query _commMgr.SendInternal(assembledReply); }) .Run(operationId, totalTimeout); }
public void Handle(GetSuccessorTable message) { _node.LogMessage(message); _commMgr.SendAck(message, message.CorrelationId); var applicant = message.Applicant; if (_node.IsInDomain(applicant.RoutingHash)) { _node.Log($"{applicant} IsInDomain"); // the predecessors successor table will become the applicant's if the applicant node // becomes the new predecessor. The head of the predecessors table is this node. var nextSuccessor = _node.Identity; var returnAddress = message.From; var tableLength = _node.SuccessorTable.Length; var predecessorTable = new RoutingTableEntry[_node.SuccessorTable.Length]; if (tableLength > 1) { var thisTable = _node.SuccessorTable; for (int i = 0; i < predecessorTable.Length - 1; i++) { predecessorTable[i + 1] = thisTable[i]; } } predecessorTable[0] = new RoutingTableEntry(_node.Identity.RoutingHash, _node.Identity); var reply = new GetSuccessorTableReply(_node.Identity, returnAddress, message.CorrelationId) { SuccessorTable = predecessorTable, }; _node.Log($"Sending {reply.TypeName()}"); _commMgr.Send(reply); //message.SuccessorTable[message.HopCount] = new RoutingTableEntry(nextSuccessor.RoutingHash, nextSuccessor); //var hopMax = _node.Config.SuccessorCount - 1; //if (message.HopCount < hopMax) //{ // nextSuccessor = _node.Successor; // _node.Log($"Successor({message.HopCount}) found. Forwarding to {nextSuccessor}"); // var forwardMsg = message; // forwardMsg.To = nextSuccessor; // forwardMsg.HopCount++; // forwardMsg.Applicant = nextSuccessor; // we need to now follow a chain of successors // _commMgr.Send(forwardMsg); //} //else //{ // // we've collected all the successors. Now send them home // var returnAddress = message.From; // var reply = new GetSuccessorTableReply(_node.Identity, returnAddress, message.CorrelationId) // { // SuccessorTable = message.SuccessorTable, // }; // _node.Log($"Sending {reply.TypeName()} Successor({message.HopCount}) found."); // _commMgr.Send(reply); //} } else // Ask the network { var closestNode = _node.SuccessorTable.FindClosestPrecedingFinger(applicant.RoutingHash); message.To = closestNode; _node.Log($"Routing {message.TypeName()} {message.To}"); _commMgr.Send(message); } }