示例#1
0
        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);
            }
        }
示例#2
0
        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);
        }
示例#4
0
            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();
            }
示例#5
0
            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();
            }
示例#6
0
        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);
        }
示例#7
0
        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);
            }
        }
示例#8
0
        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);
        }
示例#9
0
        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);
        }