/// <summary> /// Creates the routing mechanism. Make sure to set the Max* fields. /// </summary> /// <param name="tcsResponses">The current task responses that are running.</param> /// <param name="tcsRoutingResponse">The response task from this routing request.</param> /// <param name="peerFilters"></param> public RoutingMechanism(VolatileReferenceArray<TaskCompletionSource<Message.Message>> tcsResponses, TcsRouting tcsRoutingResponse, ICollection<IPeerFilter> peerFilters) { TcsResponses = tcsResponses; TcsRoutingResponse = tcsRoutingResponse; _peerFilters = peerFilters; }
/// <summary> /// Creates the routing mechanism. Make sure to set the Max* fields. /// </summary> /// <param name="tcsResponses">The current task responses that are running.</param> /// <param name="tcsRoutingResponse">The response task from this routing request.</param> /// <param name="peerFilters"></param> public RoutingMechanism(VolatileReferenceArray <TaskCompletionSource <Message.Message> > tcsResponses, TcsRouting tcsRoutingResponse, ICollection <IPeerFilter> peerFilters) { TcsResponses = tcsResponses; TcsRoutingResponse = tcsRoutingResponse; _peerFilters = peerFilters; }
public RoutingMechanism CreateRoutingMechanism(TcsRouting tcsRouting) { var tcsResponses = new TaskCompletionSource<Message.Message>[Parallel]; var tcsResponseArray = new VolatileReferenceArray<TaskCompletionSource<Message.Message>>(tcsResponses); var routingMechanism = new RoutingMechanism(tcsResponseArray, tcsRouting, PeerFilters) { MaxDirectHits = MaxDirectHits, MaxFailures = MaxFailures, MaxNoNewInfo = MaxNoNewInfo, MaxSucess = MaxSuccess }; return routingMechanism; }
public RoutingMechanism CreateRoutingMechanism(TcsRouting tcsRouting) { var tcsResponses = new TaskCompletionSource <Message.Message> [Parallel]; var tcsResponseArray = new VolatileReferenceArray <TaskCompletionSource <Message.Message> >(tcsResponses); var routingMechanism = new RoutingMechanism(tcsResponseArray, tcsRouting, PeerFilters) { MaxDirectHits = MaxDirectHits, MaxFailures = MaxFailures, MaxNoNewInfo = MaxNoNewInfo, MaxSucess = MaxSuccess }; return(routingMechanism); }
/// <summary> /// Creates a TcsForkJoin object. /// </summary> /// <param name="nrFinishFuturesSuccess">The number of tasks expected to succeed.</param> /// <param name="cancelTasksOnFinish">Whether the remaining tasks should be cancelled. /// For Get() it makes sense, for Store() it dose not.</param> /// <param name="forks">The tasks that can also be modified outside this class. /// If a task is finished, the the task in that array will be set to null. /// A task may be initially null, which is considered a failure.</param> public TcsForkJoin(int nrFinishFuturesSuccess, bool cancelTasksOnFinish, VolatileReferenceArray <TTask> forks) { _nrFinishTaskSuccess = nrFinishFuturesSuccess; _cancelTasksOnFinish = cancelTasksOnFinish; _forks = forks; // the task array may have null entries, so count first _nrTasks = forks.Length; if (_nrTasks <= 0) { // "failed" SetException(new TaskFailedException("We have no tasks: " + _nrTasks)); } else { Join(); } // TODO self needed? }
private void RoutingRec(RoutingBuilder routingBuilder, RoutingMechanism routingMechanism, Message.Message.MessageType type, ChannelCreator channelCreator) { var randomSearch = routingBuilder.LocationKey == null; var active = 0; for (var i = 0; i < routingMechanism.Parallel; i++) { if (routingMechanism.GetTcsResponse(i) == null && !routingMechanism.IsStopCreatingNewFutures) { PeerAddress next; if (randomSearch) { next = routingMechanism.PollRandomInQueueToAsk(_rnd); } else { next = routingMechanism.PollFirstInQueueToAsk(); } if (next != null) { routingMechanism.AddToAlreadyAsked(next); active++; // If we search for a random peer, then the peer should // return the address farest away. var locationKey2 = randomSearch ? next.PeerId.Xor(Number160.MaxValue) : routingBuilder.LocationKey; routingBuilder.LocationKey = locationKey2; // routing is per default UDP, don't show warning if the other TCP/UDP is used // TODO find .NET-specific way to show sanity check warning routingMechanism.SetTcsResponse(i, _neighbors.CloseNeighborsTcs(next, routingBuilder.SearchValues(), type, channelCreator, routingBuilder)); Logger.Debug("Get close neighbours: {0} on {1}.", next, i); } } else if (routingMechanism.GetTcsResponse(i) != null) { Logger.Debug("Activity on {0}.", i); active++; } } if (active == 0) { Logger.Debug("No activity, closing."); routingMechanism.SetNeighbors(routingBuilder); routingMechanism.Cancel(); return; } // .NET-specific: // TODO move to TcsForkJoin as separate c'tor? var extractedTasks = new Task <Message.Message> [routingMechanism.TcsResponses.Length]; for (int i = 0; i < routingMechanism.TcsResponses.Length; i++) { extractedTasks[i] = routingMechanism.GetTcsResponse(i) != null?routingMechanism.GetTcsResponse(i).Task : null; } var volatileArray = new VolatileReferenceArray <Task <Message.Message> >(extractedTasks); bool last = active == 1; var tcsForkJoin = new TcsForkJoin <Task <Message.Message> >(1, false, volatileArray); tcsForkJoin.Task.ContinueWith(tfj => { bool finished; if (!tfj.IsFaulted) { var lastResponse = tcsForkJoin.Last.Result; var remotePeer = lastResponse.Sender; routingMechanism.AddPotentialHits(remotePeer); var newNeighbors = lastResponse.NeighborsSet(0).Neighbors; var resultSize = lastResponse.IntAt(0); var keyDigest = lastResponse.Key(0); var contentDigest = lastResponse.Key(1); var digestBean = new DigestInfo(keyDigest, contentDigest, resultSize); Logger.Debug("Peer ({0}) {1} reported {2} in message {3}.", (digestBean.Size > 0 ? "direct" : "none"), remotePeer, newNeighbors.Count, lastResponse); finished = routingMechanism.EvaluateSuccess(remotePeer, digestBean, newNeighbors, last, routingBuilder.LocationKey); Logger.Debug("Routing finished {0} / {1}.", finished, routingMechanism.IsStopCreatingNewFutures); } else { // if it failed but the failed is the closest one, it is good to try again, // since the peer might just be busy Logger.Debug("Routing error {0}.", tfj.Exception); finished = routingMechanism.EvaluateFailed(); routingMechanism.IsStopCreatingNewFutures = finished; } if (finished) { Logger.Debug("Routing finished. Direct hits: {0}. Potential hits: {1}.", routingMechanism.DirectHits.Count, routingMechanism.PotentialHits.Count); routingMechanism.SetNeighbors(routingBuilder); routingMechanism.Cancel(); // stop all operations, as we are finished, no need to go further } else { RoutingRec(routingBuilder, routingMechanism, type, channelCreator); } }); }
/// <summary> /// Facade if we expect everythin to return successfully. /// </summary> /// <param name="forks">The tasks that can also be modified outside this class. /// If a task is finished, the the task in that array will be set to null. /// A task may be initially null, which is considered a failure.</param> public TcsForkJoin(VolatileReferenceArray <TTask> forks) : this(forks.Length, false, forks) { }
private void RoutingRec(RoutingBuilder routingBuilder, RoutingMechanism routingMechanism, Message.Message.MessageType type, ChannelCreator channelCreator) { var randomSearch = routingBuilder.LocationKey == null; var active = 0; for (var i = 0; i < routingMechanism.Parallel; i++) { if (routingMechanism.GetTcsResponse(i) == null && !routingMechanism.IsStopCreatingNewFutures) { PeerAddress next; if (randomSearch) { next = routingMechanism.PollRandomInQueueToAsk(_rnd); } else { next = routingMechanism.PollFirstInQueueToAsk(); } if (next != null) { routingMechanism.AddToAlreadyAsked(next); active++; // If we search for a random peer, then the peer should // return the address farest away. var locationKey2 = randomSearch ? next.PeerId.Xor(Number160.MaxValue) : routingBuilder.LocationKey; routingBuilder.LocationKey = locationKey2; // routing is per default UDP, don't show warning if the other TCP/UDP is used // TODO find .NET-specific way to show sanity check warning routingMechanism.SetTcsResponse(i, _neighbors.CloseNeighborsTcs(next, routingBuilder.SearchValues(), type, channelCreator, routingBuilder)); Logger.Debug("Get close neighbours: {0} on {1}.", next, i); } } else if (routingMechanism.GetTcsResponse(i) != null) { Logger.Debug("Activity on {0}.", i); active++; } } if (active == 0) { Logger.Debug("No activity, closing."); routingMechanism.SetNeighbors(routingBuilder); routingMechanism.Cancel(); return; } // .NET-specific: // TODO move to TcsForkJoin as separate c'tor? var extractedTasks = new Task<Message.Message>[routingMechanism.TcsResponses.Length]; for (int i = 0; i < routingMechanism.TcsResponses.Length; i++) { extractedTasks[i] = routingMechanism.GetTcsResponse(i) != null ? routingMechanism.GetTcsResponse(i).Task : null; } var volatileArray = new VolatileReferenceArray<Task<Message.Message>>(extractedTasks); bool last = active == 1; var tcsForkJoin = new TcsForkJoin<Task<Message.Message>>(1, false, volatileArray); tcsForkJoin.Task.ContinueWith(tfj => { bool finished; if (!tfj.IsFaulted) { var lastResponse = tcsForkJoin.Last.Result; var remotePeer = lastResponse.Sender; routingMechanism.AddPotentialHits(remotePeer); var newNeighbors = lastResponse.NeighborsSet(0).Neighbors; var resultSize = lastResponse.IntAt(0); var keyDigest = lastResponse.Key(0); var contentDigest = lastResponse.Key(1); var digestBean = new DigestInfo(keyDigest, contentDigest, resultSize); Logger.Debug("Peer ({0}) {1} reported {2} in message {3}.", (digestBean.Size > 0 ? "direct" : "none"), remotePeer, newNeighbors.Count, lastResponse); finished = routingMechanism.EvaluateSuccess(remotePeer, digestBean, newNeighbors, last, routingBuilder.LocationKey); Logger.Debug("Routing finished {0} / {1}.", finished, routingMechanism.IsStopCreatingNewFutures); } else { // if it failed but the failed is the closest one, it is good to try again, // since the peer might just be busy Logger.Debug("Routing error {0}.", tfj.Exception); finished = routingMechanism.EvaluateFailed(); routingMechanism.IsStopCreatingNewFutures = finished; } if (finished) { Logger.Debug("Routing finished. Direct hits: {0}. Potential hits: {1}.", routingMechanism.DirectHits.Count, routingMechanism.PotentialHits.Count); routingMechanism.SetNeighbors(routingBuilder); routingMechanism.Cancel(); // stop all operations, as we are finished, no need to go further } else { RoutingRec(routingBuilder, routingMechanism, type, channelCreator); } }); }