/// <summary> /// Maintenance task to ensure that the local node has valid successor node. Roughly equivalent /// to what is called out in the Chord paper. /// </summary> /// <param name="sender">The worker thread the task is running on.</param> /// <param name="ea">Args (ignored here).</param> private void StabilizeSuccessors(object sender, DoWorkEventArgs ea) { BackgroundWorker me = (BackgroundWorker)sender; while (!me.CancellationPending) { try { // check in successor and if it's bad, replace it with // the next live entry in the successor cache ChordNode succPredNode = ChordServer.GetPredecessor(this.Successor); if (succPredNode != null) { if (ChordServer.IsIDInRange(succPredNode.ID, this.ID, this.Successor.ID)) { this.Successor = succPredNode; } // ignoring return because bad node will be detected on next invocation ChordServer.CallNotify(this.Successor, ChordServer.LocalNode); GetSuccessorCache(this.Successor); } else { bool successorCacheHelped = false; foreach (ChordNode entry in this.m_SuccessorCache) { ChordInstance instance = ChordServer.GetInstance(entry); if (ChordServer.IsInstanceValid(instance)) { this.Successor = entry; ChordServer.CallNotify(this.Successor, ChordServer.LocalNode); GetSuccessorCache(this.Successor); successorCacheHelped = true; break; } } // if we get here, then we got no help and have no other recourse than to re-join using the initial seed... if (!successorCacheHelped) { ChordServer.Log(LogLevel.Error, "StabilizeSuccessors", "Ring consistency error, Re-Joining Chord ring."); Join(this.m_SeedNode, this.Host, this.Port); return; } } } catch (Exception e) { ChordServer.Log(LogLevel.Error, "Maintenance", "Error occured during StabilizeSuccessors ({0})", e.Message); } // TODO: this could be tweaked and/or made configurable elsewhere or passed in as arguments Thread.Sleep(5000); } }