protected void AddServer(SiloAddress silo) { lock (membershipCache) { if (membershipCache.Contains(silo)) { // we have already cached this silo return; } membershipCache.Add(silo); // insert new silo in the sorted order long hash = silo.GetConsistentHashCode(); // Find the last silo with hash smaller than the new silo, and insert the latter after (this is why we have +1 here) the former. // Notice that FindLastIndex might return -1 if this should be the first silo in the list, but then // 'index' will get 0, as needed. int index = membershipRingList.FindLastIndex(siloAddr => siloAddr.GetConsistentHashCode() < hash) + 1; membershipRingList.Insert(index, silo); HandoffManager.ProcessSiloAddEvent(silo); if (log.IsVerbose) { log.Verbose("Silo {0} added silo {1}", MyAddress, silo); } } }
protected void AddServer(SiloAddress silo) { lock (this.writeLock) { var existing = this.directoryMembership; if (existing.MembershipCache.Contains(silo)) { // we have already cached this silo return; } // insert new silo in the sorted order long hash = silo.GetConsistentHashCode(); // Find the last silo with hash smaller than the new silo, and insert the latter after (this is why we have +1 here) the former. // Notice that FindLastIndex might return -1 if this should be the first silo in the list, but then // 'index' will get 0, as needed. int index = existing.MembershipRingList.FindLastIndex(siloAddr => siloAddr.GetConsistentHashCode() < hash) + 1; this.directoryMembership = new DirectoryMembership( existing.MembershipRingList.Insert(index, silo), existing.MembershipCache.Add(silo)); HandoffManager.ProcessSiloAddEvent(silo); AdjustLocalDirectory(silo, dead: false); AdjustLocalCache(silo, dead: false); if (log.IsEnabled(LogLevel.Debug)) { log.Debug("Silo {0} added silo {1}", MyAddress, silo); } } }
/// <summary> /// For testing purposes only. /// Returns the directory information held by the local silo for the provided grain ID. /// The result will be null if no information is held. /// </summary> /// <param name="grain"></param> /// <param name="isPrimary"></param> /// <returns></returns> public List <ActivationAddress> GetLocalDataForGrain(GrainId grain, out bool isPrimary) { var primary = CalculateTargetSilo(grain); List <ActivationAddress> backupData = HandoffManager.GetHandedOffInfo(grain); if (MyAddress.Equals(primary)) { log.Assert(ErrorCode.DirectoryBothPrimaryAndBackupForGrain, backupData == null, "Silo contains both primary and backup directory data for grain " + grain); isPrimary = true; return(GetLocalDirectoryData(grain)); } isPrimary = false; return(backupData); }
// Note that this implementation stops processing directory change requests (Register, Unregister, etc.) when the Stop event is raised. // This means that there may be a short period during which no silo believes that it is the owner of directory information for a set of // grains (for update purposes), which could cause application requests that require a new activation to be created to time out. // The alternative would be to allow the silo to process requests after it has handed off its partition, in which case those changes // would receive successful responses but would not be reflected in the eventual state of the directory. // It's easy to change this, if we think the trade-off is better the other way. public void Stop(bool doOnStopHandoff) { // This will cause remote write requests to be forwarded to the silo that will become the new owner. // Requests might bounce back and forth for a while as membership stabilizes, but they will either be served by the // new owner of the grain, or will wind up failing. In either case, we avoid requests succeeding at this silo after we've // begun stopping, which could cause them to not get handed off to the new owner. Running = false; if (doOnStopHandoff) { HandoffManager.ProcessSiloStoppingEvent(); } else { MarkStopPreparationCompleted(); } if (maintainer != null) { maintainer.Stop(); } DirectoryCache.Clear(); }
protected void RemoveServer(SiloAddress silo, SiloStatus status) { lock (membershipCache) { if (!membershipCache.Contains(silo)) { // we have already removed this silo return; } if (CatalogSiloStatusListener != null) { try { // only call SiloStatusChangeNotification once on the catalog and the order is important: call BEFORE updating membershipRingList. CatalogSiloStatusListener.SiloStatusChangeNotification(silo, status); } catch (Exception exc) { log.Error(ErrorCode.Directory_SiloStatusChangeNotification_Exception, String.Format("CatalogSiloStatusListener.SiloStatusChangeNotification has thrown an exception when notified about removed silo {0}.", silo.ToStringWithHashCode()), exc); } } // the call order is important HandoffManager.ProcessSiloRemoveEvent(silo); membershipCache.Remove(silo); membershipRingList.Remove(silo); AdjustLocalDirectory(silo); AdjustLocalCache(silo); if (log.IsVerbose) { log.Verbose("Silo {0} removed silo {1}", MyAddress, silo); } } }
protected void RemoveServer(SiloAddress silo, SiloStatus status) { lock (this.writeLock) { try { // Only notify the catalog once. Order is important: call BEFORE updating membershipRingList. this.catalogOnSiloRemoved?.Invoke(silo, status); } catch (Exception exc) { log.Error(ErrorCode.Directory_SiloStatusChangeNotification_Exception, String.Format("CatalogSiloStatusListener.SiloStatusChangeNotification has thrown an exception when notified about removed silo {0}.", silo.ToStringWithHashCode()), exc); } var existing = this.directoryMembership; if (!existing.MembershipCache.Contains(silo)) { // we have already removed this silo return; } // the call order is important HandoffManager.ProcessSiloRemoveEvent(silo); this.directoryMembership = new DirectoryMembership( existing.MembershipRingList.Remove(silo), existing.MembershipCache.Remove(silo)); AdjustLocalDirectory(silo, dead: true); AdjustLocalCache(silo, dead: true); if (log.IsEnabled(LogLevel.Debug)) { log.Debug("Silo {0} removed silo {1}", MyAddress, silo); } } }