private FindKeySuccessorResult FindPredecessorForId(FindKeySuccessorArg id) { var result = FindClosestPrecedingFinger(id.Id); Log.Write(LogEvent.Debug, "FindSuccessorForId(from: {1}, for {2}): FindClosestPrecedingFinger returned node {0} and ...", result.Id, LocalNode.Id, id ); // stop recursion if (result.Equals(LocalNode)) { Log.Write(LogEvent.Debug, "FindSuccessorForId(from: {0}, for {1}): ... actually it is the same as local node {0}, so return it", LocalNode.Id, id ); return new FindKeySuccessorResult(LocalNode, false).CopyStatistics(id); } if (ChordOverlayHelper.IsInCircularInterval(id.Id, LocalNode.Id, LocalNode.Successor.Id, includeRight: true)) { Log.Write(LogEvent.Debug, "FindSuccessorForId(from: {0}, for {1}): ... OverlayHelper.IsInCircularInterval({1}, {0}, {2}, includeRight: true) is true, so return it", LocalNode.Id, id, LocalNode.Successor.Id ); return new FindKeySuccessorResult(result, true).CopyStatistics(id); } else { var resultNodeSrv = CommunicationMgr.GetChannel(result); try { Log.Write(LogEvent.Debug, "FindSuccessorForId(from: {0}, for {1}): ... OverlayHelper.IsInCircularInterval({1}, {0}, {2}, includeRight: true) is false, so call FindSuccessorForId(from: {3}, for {1})", LocalNode.Id, id, LocalNode.Successor.Id, result.Id ); // +1 hop, since we are calling the same method on the remote successor id.StatsCollector.IncreaseHopsCount(1); // if we call this recursively, we do not need to get the successor of the result inside return resultNodeSrv.Service.FindKeySuccessor(new FindKeySuccessorArg(id.Id, false).CopyStatistics(id)); } catch (Exception ex) { if (resultNodeSrv.IsUnavailable) { Log.Write( LogEvent.Warn, "Node {0} cannot propagate FindSuccessorForId for node {1} because the service is unaccessible, returning local node instead. Error details: \r\n {2}", LocalNode, result, ex.ToString() ); // TODO: correct? return new FindKeySuccessorResult(LocalNode, false).CopyStatistics(id); } else { throw; } } } }
public FindKeySuccessorResult FindKeySuccessor(FindKeySuccessorArg key) { Log.Write(LogEvent.Debug, "FindSuccessorForId(from: {0}, for {1})", LocalNode.Id, key); // check if my successor is actually the successor of this id if (ChordOverlayHelper.IsInCircularInterval(key.Id, LocalNode.Id, LocalNode.Successor.Id, includeRight: true)) { Log.Write(LogEvent.Debug, "FindSuccessorForId(from: {1}, for {0}): OverlayHelper.IsInCircularInterval({0}, {1}, {2}, includeRight: true) is true, returning LocalNode.Successor: {2}", key, LocalNode.Id, LocalNode.Successor.Id ); return new FindKeySuccessorResult(LocalNode.Successor, false).CopyStatistics(key); } // check if me is actually the successor of this id if (LocalNode.Predecessor != null && ChordOverlayHelper.IsInCircularInterval(key.Id, LocalNode.Predecessor.Id, LocalNode.Id, includeRight: true)) { Log.Write(LogEvent.Debug, "FindSuccessorForId(from: {2}, for {0}): OverlayHelper.IsInCircularInterval({0}, {1}, {2}, includeRight: true) is true, returning LocalNode: {2}", key, LocalNode.Predecessor.Id, LocalNode.Id ); return new FindKeySuccessorResult(LocalNode, false).CopyStatistics(key); } var pred = FindPredecessorForId(key); var predSrv = CommunicationMgr.GetChannel(pred.Node); try { var returnSuccessorAsResult = pred.ReturnSuccessorAsResult && key.ReturnSuccessorAsResult; var res = returnSuccessorAsResult ? predSrv.Service.GetSuccessor() : pred.Node; if (returnSuccessorAsResult) { key.StatsCollector.IncreaseHopsCount(1); // for GetSuccessor } Log.Write(LogEvent.Debug, returnSuccessorAsResult ? "FindSuccessorForId(from: {2}, for {3}): FindPredecessorForId returned node {0}, thus the result of FindSuccessorForId is {0}'s successor: {1}" : "FindSuccessorForId(from: {2}, for {3}): FindPredecessorForId returned node {0}, thus the result of FindSuccessorForId is {0}", pred.Node.Id, res.Id, LocalNode.Id, key ); return new FindKeySuccessorResult(res, false).CopyStatistics(key); } catch (Exception ex) { if (predSrv.IsUnavailable) { Log.Write( LogEvent.Warn, "Node {0} cannot call GetNodeSuccessor for node {1} because the service is unaccessible, returning local node instead. Error details: \r\n {2}", LocalNode, pred, ex.ToString() ); // TODO: correct? return new FindKeySuccessorResult(LocalNode, false).CopyStatistics(key); } else { throw; } } throw new NotImplementedException(); }