예제 #1
0
        private bool ChangeState([NotNull] ClientHolderState currentState, [NotNull] ClientHolderState newState)
        {
            if (Interlocked.CompareExchange(ref state, newState, currentState) != currentState)
            {
                return(false);
            }

            SendOnConnectionStateChanged();

            currentState.NextState.TrySetResult(newState);

            log.Info("Connection state changed. Old: '{OldState}'. New: '{NewState}'.", currentState, newState);

            if (newState.ConnectionState == ConnectionState.Expired)
            {
                ResetClient(newState);
            }
            else if (!newState.IsConnected)
            {
                Task.Run(() => WaitAndResetClient(newState));
            }
            else
            {
                suspendedManager.ResetDelay();
            }

            return(true);
        }
예제 #2
0
        private void ProcessEvent(ConnectionEvent connectionEvent)
        {
            log.Debug("Processing connection state event '{ConnectionEvent}'.", connectionEvent);

            var currentState = state;

            if (currentState == null || !ReferenceEquals(connectionEvent.EventFrom, currentState.ConnectionWatcher))
            {
                return;
            }

            var newState = new ClientHolderState(
                currentState.LazyClient,
                currentState.ConnectionWatcher,
                connectionEvent.NewConnectionState,
                currentState.ConnectionString);

            if (!ChangeState(currentState, newState))
            {
                return;
            }

            if (newState.ConnectionState == ConnectionState.Expired)
            {
                ResetClient(newState);
            }
        }
예제 #3
0
        private bool ResetClientIfNeeded([CanBeNull] ClientHolderState currentState)
        {
            if (currentState != null && NeedToResetClient(currentState))
            {
                return(ResetClient(currentState));
            }

            return(true);
        }
예제 #4
0
        public ClientHolder(ZooKeeperClientSettings settings, ILog log)
        {
            this.log      = log;
            this.settings = settings;

            state = new ClientHolderState(null, null, ConnectionState.Disconnected, null);

            ZooKeeperLogInjector.Register(this, this.log);
        }
예제 #5
0
        public ClientHolder(ZooKeeperClientSettings settings, ILog log)
        {
            this.log      = log;
            this.settings = settings;

            state            = ClientHolderState.CreateActive(null, null, ConnectionState.Disconnected, null, settings);
            suspendedManager = new SuspendedManager(settings.Timeout, settings.Timeout.Multiply(settings.MaximumConnectPeriodMultiplier), -3);

            ZooKeeperLogInjector.Register(this, this.log);
        }
예제 #6
0
        private async Task WaitAndResetClient([NotNull] ClientHolderState currentState)
        {
            try
            {
                await Task.Delay(currentState.TimeBeforeReset.Remaining).ConfigureAwait(false);

                if (ReferenceEquals(state, currentState))
                {
                    ResetClient(currentState);
                }
            }
            catch (Exception e)
            {
                log.Error(e, "Failed to reset client.");
            }
        }
예제 #7
0
        private bool ResetClient([NotNull] ClientHolderState currentState)
        {
            log.Info("Resetting client. Current state: '{CurrentState}'.", currentState);

            var newConnectionString = settings.ConnectionStringProvider();

            if (string.IsNullOrEmpty(newConnectionString))
            {
                log.Error("Failed to resolve any ZooKeeper replicas.");
                return(false);
            }

            var newConnectionWatcher = new ConnectionWatcher(ProcessEvent);
            var newClient            = new Lazy <ZooKeeperNetExClient>(
                () =>
            {
                using (ExecutionContext.SuppressFlow())
                {
                    return(new ZooKeeperNetExClient(
                               newConnectionString,
                               settings.ToInnerConnectionTimeout(),
                               newConnectionWatcher,
                               settings.CanBeReadOnly));
                }
            },
                LazyThreadSafetyMode.ExecutionAndPublication);

            var suspendedFor = suspendedManager.GetNextDelay();
            var newState     = suspendedFor != null && !currentState.IsSuspended
                ? ClientHolderState.CreateSuspended(suspendedFor)
                : ClientHolderState.CreateActive(newClient, newConnectionWatcher, ConnectionState.Disconnected, newConnectionString, settings);

            if (ChangeState(currentState, newState))
            {
                newState.Client?.Touch();

                // Note(kungurtsev): increase delay for each active (not suspended) client creation.
                if (!currentState.IsSuspended)
                {
                    suspendedManager.IncreaseDelay();
                }

                currentState.Dispose();
            }

            return(true);
        }
예제 #8
0
        private bool ChangeState([NotNull] ClientHolderState currentState, [NotNull] ClientHolderState newState)
        {
            if (Interlocked.CompareExchange(ref state, newState, currentState) != currentState)
            {
                return(false);
            }

            SendOnConnectionStateChanged();

            currentState.NextState.TrySetResult(newState);

            if (currentState.ConnectionState != newState.ConnectionState)
            {
                log.Info("Connection state changed. Old: '{OldState}'. New: '{NewState}'.", currentState, newState);
            }

            return(true);
        }
예제 #9
0
        private bool NeedToResetClient([NotNull] ClientHolderState currentState)
        {
            if (currentState.IsSuspended)
            {
                return(currentState.TimeBeforeReset.HasExpired);
            }

            if (currentState.ConnectionString != settings.ConnectionStringProvider())
            {
                return(true);
            }

            if (!currentState.IsConnected)
            {
                return(currentState.TimeBeforeReset.HasExpired);
            }

            return(false);
        }
예제 #10
0
        private bool ResetClient([NotNull] ClientHolderState currentState)
        {
            log.Info("Resetting client. Current state: '{CurrentState}'.", currentState);

            var newConnectionString = settings.ConnectionStringProvider();

            if (string.IsNullOrEmpty(newConnectionString))
            {
                log.Error("Failed to resolve any ZooKeeper replicas.");
                return(false);
            }

            var newConnectionWatcher = new ConnectionWatcher(ProcessEvent);
            var newClient            = new Lazy <ZooKeeperNetExClient>(
                () =>
            {
                using (ExecutionContext.SuppressFlow())
                {
                    return(new ZooKeeperNetExClient(
                               newConnectionString,
                               settings.ToInnerConnectionTimeout(),
                               newConnectionWatcher,
                               settings.CanBeReadOnly));
                }
            },
                LazyThreadSafetyMode.ExecutionAndPublication);

            var newState = new ClientHolderState(newClient, newConnectionWatcher, ConnectionState.Disconnected, newConnectionString);

            if (ChangeState(currentState, newState))
            {
                newState.Client?.Touch();

                currentState.Dispose();
            }

            return(true);
        }