private void DemoteLocalGateways(IReadOnlyList<SiloAddress> activeGateways, ref MultiClusterData deltas) { var now = DateTime.UtcNow; // mark gateways as inactive if they have not recently advertised their existence, // and if they are not designated gateways as per membership table var toBeUpdated = this.localData.Current.Gateways.Values .Where(g => g.ClusterId == clusterId && g.Status == GatewayStatus.Active && (now - g.HeartbeatTimestamp > CleanupSilentGoneGatewaysAfter) && !activeGateways.Contains(g.SiloAddress)) .Select(g => new GatewayEntry() { ClusterId = g.ClusterId, SiloAddress = g.SiloAddress, Status = GatewayStatus.Inactive, HeartbeatTimestamp = g.HeartbeatTimestamp + CleanupSilentGoneGatewaysAfter, }).ToList(); if (toBeUpdated.Count == 0) return; var data = new MultiClusterData(toBeUpdated); if (logger.IsVerbose) logger.Verbose("-DemoteLocalGateways {0}", data.ToString()); var delta = this.localData.ApplyDataAndNotify(data); if (!delta.IsEmpty) { deltas = deltas.Merge(delta); } }
private void InjectLocalStatus(bool isGateway, ref MultiClusterData deltas) { var myStatus = new GatewayEntry() { ClusterId = clusterId, SiloAddress = Silo, Status = isGateway ? GatewayStatus.Active : GatewayStatus.Inactive, HeartbeatTimestamp = DateTime.UtcNow, }; GatewayEntry existingEntry; // do not update if we are reporting inactive status and entry is not already there if (!this.localData.Current.Gateways.TryGetValue(Silo, out existingEntry) && !isGateway) { return; } // send if status is changed, or we are active and haven't said so in a while if (existingEntry == null || existingEntry.Status != myStatus.Status || (myStatus.Status == GatewayStatus.Active && myStatus.HeartbeatTimestamp - existingEntry.HeartbeatTimestamp > this.resendActiveStatusAfter)) { logger.Info($"Report as {myStatus}"); // update current data with status var delta = this.localData.ApplyDataAndNotify(new MultiClusterData(myStatus)); if (!delta.IsEmpty) { deltas = deltas.Merge(delta); } } }
public IMultiClusterGossipData ApplyDataAndNotify(IMultiClusterGossipData data) { if (data.IsEmpty) { return(data); } MultiClusterData delta; MultiClusterData prev = this.localData; this.localData = prev.Merge(data, out delta); if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace("ApplyDataAndNotify: delta {0}", delta); } if (delta.IsEmpty) { return(delta); } if (delta.Gateways.Count > 0) { // some gateways have changed ComputeAvailableGatewaysPerCluster(); } if (delta.Configuration != null) { // notify configuration listeners of change List <IMultiClusterConfigurationListener> listenersToNotify; lock (confListeners) { // make a copy under the lock listenersToNotify = confListeners.ToList(); } foreach (var listener in listenersToNotify) { try { listener.OnMultiClusterConfigurationChange(delta.Configuration); } catch (Exception exc) { logger.Error(ErrorCode.MultiClusterNetwork_LocalSubscriberException, String.Format("IMultiClusterConfigurationListener {0} threw exception processing configuration {1}", listener, delta.Configuration), exc); } } } return(delta); }
public void Publish(MultiClusterData data) { // add the data to the data waiting to be published toPublish = toPublish.Merge(data); if (oracle.logger.IsVerbose) LogQueuedPublish(toPublish); Notify(); }
public void Publish(IMultiClusterGossipData data) { // add the data to the data waiting to be published toPublish = toPublish.Merge(data); if (oracle.logger.IsEnabled(LogLevel.Debug)) { LogQueuedPublish(toPublish); } Notify(); }
private void InjectConfiguration(ref MultiClusterData deltas) { if (this.injectedConfig == null) return; var data = new MultiClusterData(this.injectedConfig); this.injectedConfig = null; if (logger.IsVerbose) logger.Verbose("-InjectConfiguration {0}", data.Configuration.ToString()); var delta = this.localData.ApplyDataAndNotify(data); if (!delta.IsEmpty) deltas = deltas.Merge(delta); }
private void InjectConfiguration(ref MultiClusterData deltas) { if (this.injectedConfig == null) { return; } var data = new MultiClusterData(this.injectedConfig); this.injectedConfig = null; if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug("-InjectConfiguration {0}", data.Configuration.ToString()); } var delta = this.localData.ApplyDataAndNotify(data); if (!delta.IsEmpty) { deltas = deltas.Merge(delta); } }
public MultiClusterData ApplyDataAndNotify(MultiClusterData data) { if (data.IsEmpty) { return(data); } MultiClusterData delta; MultiClusterData prev = this.localData; this.localData = prev.Merge(data, out delta); if (logger.IsVerbose2) { logger.Verbose2("ApplyDataAndNotify: delta {0}", delta); } if (delta.IsEmpty) { return(delta); } if (delta.Gateways.Count > 0) { // some gateways have changed ComputeAvailableGatewaysPerCluster(); } if (delta.Configuration != null) { // notify configuration listeners of change // code will be added in separate PR } return(delta); }
public MultiClusterData ApplyDataAndNotify(MultiClusterData data) { if (data.IsEmpty) { return(data); } MultiClusterData delta; MultiClusterData prev = this.localData; this.localData = prev.Merge(data, out delta); if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace("ApplyDataAndNotify: delta {0}", delta); } if (delta.IsEmpty) { return(delta); } if (delta.Gateways.Count > 0) { // some gateways have changed ComputeAvailableGatewaysPerCluster(); } if (delta.Configuration != null) { // notify configuration listeners of change List <GrainReference> listenersToNotify; lock (confListeners) { // make a copy under the lock listenersToNotify = confListeners.ToList(); } foreach (var listener in listenersToNotify) { try { if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace("-NotificationWork: notify IProtocolParticipant {0} of configuration {1}", listener, delta.Configuration); } // enqueue conf change event as grain call var g = this.grainFactory.Cast <ILogConsistencyProtocolParticipant>(listener); g.OnMultiClusterConfigurationChange(delta.Configuration).Ignore(); } catch (Exception exc) { logger.Error(ErrorCode.MultiClusterNetwork_LocalSubscriberException, String.Format("IProtocolParticipant {0} threw exception processing configuration {1}", listener, delta.Configuration), exc); } } } return(delta); }