コード例 #1
0
        internal static Exception ConnectionFailure(bool includeDetail, ConnectionFailureType failureType, string message, ServerEndPoint server)
        {
            var ex = new RedisConnectionException(failureType, message);

            if (includeDetail)
            {
                AddDetail(ex, null, server, null);
            }
            return(ex);
        }
コード例 #2
0
        internal static Exception Timeout(bool includeDetail, string errorMessage, Message message, ServerEndPoint server)
        {
            var ex = new TimeoutException(errorMessage);

            if (includeDetail)
            {
                AddDetail(ex, message, server, null);
            }
            return(ex);
        }
コード例 #3
0
        internal static Exception CommandDisabled(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server)
        {
            string s  = GetLabel(includeDetail, command, message);
            var    ex = new RedisCommandException("This operation has been disabled in the command-map and cannot be used: " + s);

            if (includeDetail)
            {
                AddDetail(ex, message, server, s);
            }
            return(ex);
        }
コード例 #4
0
        internal static Exception NoConnectionAvailable(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server, ServerEndPoint[] serverSnapshot)
        {
            string s = GetLabel(includeDetail, command, message);

            if (server != null)
            {
                //if we already have the serverEndpoint for connection failure use that
                //otherwise it would output state of all the endpoints
                serverSnapshot = new ServerEndPoint[] { server };
            }
            string exceptionmessage = "No connection is available to service this operation: " + s;
            var    ex = new RedisConnectionException(ConnectionFailureType.UnableToResolvePhysicalConnection, exceptionmessage, GetServerSnapshotInnerExceptions(serverSnapshot));

            if (includeDetail)
            {
                AddDetail(ex, message, server, s);
            }
            return(ex);
        }
コード例 #5
0
        internal static Exception AdminModeNotEnabled(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server)
        {
            string s  = GetLabel(includeDetail, command, message);
            var    ex = new RedisCommandException("This operation is not available unless admin mode is enabled: " + s);

            if (includeDetail)
            {
                AddDetail(ex, message, server, s);
            }
            return(ex);
        }
コード例 #6
0
 public static ProfileStorage NewWithContext(ConcurrentProfileStorageCollection pushTo, ServerEndPoint server)
 {
     return(new ProfileStorage(pushTo, server, null, null));
 }
コード例 #7
0
        internal void OnHeartbeat(bool ifConnectedOnly)
        {
            bool runThisTime = false;

            try
            {
                runThisTime = !isDisposed && Interlocked.CompareExchange(ref beating, 1, 0) == 0;
                if (!runThisTime)
                {
                    return;
                }

                uint index          = (uint)Interlocked.Increment(ref profileLogIndex);
                long newSampleCount = Interlocked.Read(ref operationCount);
                Interlocked.Exchange(ref profileLog[index % ProfileLogSamples], newSampleCount);
                Interlocked.Exchange(ref profileLastLog, newSampleCount);
                Trace("OnHeartbeat: " + (State)state);
                switch (state)
                {
                case (int)State.Connecting:
                    int connectTimeMilliseconds = unchecked (Environment.TickCount - VolatileWrapper.Read(ref connectStartTicks));
                    if (connectTimeMilliseconds >= Multiplexer.RawConfig.ConnectTimeout)
                    {
                        LastException = ExceptionFactory.UnableToConnect("ConnectTimeout");
                        Trace("Aborting connect");
                        // abort and reconnect
                        var   snapshot = physical;
                        bool  isCurrent;
                        State oldState;
                        OnDisconnected(ConnectionFailureType.UnableToConnect, snapshot, out isCurrent, out oldState);
                        using (snapshot) { }     // dispose etc
                        TryConnect(null);
                    }
                    if (!ifConnectedOnly)
                    {
                        AbortUnsent();
                    }
                    break;

                case (int)State.ConnectedEstablishing:
                case (int)State.ConnectedEstablished:
                    var tmp = physical;
                    if (tmp != null)
                    {
                        if (state == (int)State.ConnectedEstablished)
                        {
                            tmp.Bridge.ServerEndPoint.ClearUnselectable(UnselectableFlags.DidNotRespond);
                        }
                        tmp.OnHeartbeat();
                        int writeEverySeconds  = ServerEndPoint.WriteEverySeconds,
                            checkConfigSeconds = Multiplexer.RawConfig.ConfigCheckSeconds;

                        if (state == (int)State.ConnectedEstablished && ConnectionType == ConnectionType.Interactive &&
                            checkConfigSeconds > 0 && ServerEndPoint.LastInfoReplicationCheckSecondsAgo >= checkConfigSeconds &&
                            ServerEndPoint.CheckInfoReplication())
                        {
                            // that serves as a keep-alive, if it is accepted
                        }
                        else if (writeEverySeconds > 0 && tmp.LastWriteSecondsAgo >= writeEverySeconds)
                        {
                            Trace("OnHeartbeat - overdue");
                            if (state == (int)State.ConnectedEstablished)
                            {
                                KeepAlive();
                            }
                            else
                            {
                                bool  ignore;
                                State oldState;
                                OnDisconnected(ConnectionFailureType.SocketFailure, tmp, out ignore, out oldState);
                            }
                        }
                        else if (!queue.Any() && tmp.GetSentAwaitingResponseCount() != 0)
                        {
                            // there's a chance this is a dead socket; sending data will shake that
                            // up a bit, so if we have an empty unsent queue and a non-empty sent
                            // queue, test the socket
                            KeepAlive();
                        }
                    }
                    break;

                case (int)State.Disconnected:
                    if (!ifConnectedOnly)
                    {
                        AbortUnsent();
                        Multiplexer.Trace("Resurrecting " + this.ToString());
                        GetConnection(null);
                    }
                    break;

                default:
                    if (!ifConnectedOnly)
                    {
                        AbortUnsent();
                    }
                    break;
                }
            }
            catch (Exception ex)
            {
                OnInternalError(ex);
                Trace("OnHeartbeat error: " + ex.Message);
            }
            finally
            {
                if (runThisTime)
                {
                    Interlocked.Exchange(ref beating, 0);
                }
            }
        }
コード例 #8
0
        internal override Task <T> ExecuteAsync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null)
        {
            if (message == null)
            {
                return(CompletedTask <T> .Default(asyncState));
            }
            multiplexer.CheckMessage(message);

            multiplexer.Trace("Wrapping " + message.Command, "Transaction");
            // prepare the inner command as a task
            Task <T> task;

            if (message.IsFireAndForget)
            {
                task = CompletedTask <T> .Default(null); // F+F explicitly does not get async-state
            }
            else
            {
                var tcs    = TaskSource.CreateDenyExecSync <T>(asyncState);
                var source = ResultBox <T> .Get(tcs);

                message.SetSource(source, processor);
                task = tcs.Task;
            }

            // prepare an outer-command that decorates that, but expects QUEUED
            var queued    = new QueuedMessage(message);
            var wasQueued = ResultBox <bool> .Get(null);

            queued.SetSource(wasQueued, QueuedProcessor.Default);

            // store it, and return the task of the *outer* command
            // (there is no task for the inner command)
            (pending ?? (pending = new List <QueuedMessage>())).Add(queued);


            switch (message.Command)
            {
            case RedisCommand.EVAL:
            case RedisCommand.EVALSHA:
                // people can do very naughty things in an EVAL
                // including change the DB; change it back to what we
                // think it should be!
                var sel = PhysicalConnection.GetSelectDatabaseCommand(message.Db);
                queued    = new QueuedMessage(sel);
                wasQueued = ResultBox <bool> .Get(null);

                queued.SetSource(wasQueued, QueuedProcessor.Default);
                pending.Add(queued);
                break;
            }
            return(task);
        }
コード例 #9
0
 internal virtual Task <T> ExecuteAsync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null)
 {
     if (message == null)
     {
         return(CompletedTask <T> .Default(asyncState));
     }
     multiplexer.CheckMessage(message);
     return(multiplexer.ExecuteAsyncImpl <T>(message, processor, asyncState, server));
 }
コード例 #10
0
 internal override RedisFeatures GetFeatures(int db, RedisKey key, CommandFlags flags, out ServerEndPoint server)
 {
     server = this.server;
     return(new RedisFeatures(server.Version));
 }
コード例 #11
0
 internal override T ExecuteSync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null)
 {
     throw new NotSupportedException("ExecuteSync cannot be used inside a transaction");
 }
コード例 #12
0
 internal override T ExecuteSync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null)
 {   // inject our expected server automatically
     if (server == null)
     {
         server = this.server;
     }
     FixFlags(message, server);
     if (!server.IsConnected)
     {
         if (message == null || message.IsFireAndForget)
         {
             return(default(T));
         }
         throw ExceptionFactory.NoConnectionAvailable(multiplexer.IncludeDetailInExceptions, message.Command, message, server, multiplexer.GetServerSnapshot());
     }
     return(base.ExecuteSync <T>(message, processor, server));
 }
コード例 #13
0
 internal override Task <T> ExecuteAsync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null)
 {   // inject our expected server automatically
     if (server == null)
     {
         server = this.server;
     }
     FixFlags(message, server);
     if (!server.IsConnected)
     {
         if (message == null)
         {
             return(CompletedTask <T> .Default(asyncState));
         }
         if (message.IsFireAndForget)
         {
             return(CompletedTask <T> .Default(null));                       // F+F explicitly does not get async-state
         }
         // no need to deny exec-sync here; will be complete before they see if
         var tcs = TaskSource.Create <T>(asyncState);
         ConnectionMultiplexer.ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(multiplexer.IncludeDetailInExceptions, message.Command, message, server, multiplexer.GetServerSnapshot()));
         return(tcs.Task);
     }
     return(base.ExecuteAsync <T>(message, processor, server));
 }
コード例 #14
0
        private bool WriteMessageToServer(PhysicalConnection connection, Message message)
        {
            if (message == null)
            {
                return(true);
            }

            try
            {
                var  cmd          = message.Command;
                bool isMasterOnly = message.IsMasterOnly();
                if (isMasterOnly && ServerEndPoint.IsSlave && (ServerEndPoint.SlaveReadOnly || !ServerEndPoint.AllowSlaveWrites))
                {
                    throw ExceptionFactory.MasterOnly(Multiplexer.IncludeDetailInExceptions, message.Command, message, ServerEndPoint);
                }

                SelectDatabase(connection, message);

                if (!connection.TransactionActive)
                {
                    var readmode = connection.GetReadModeCommand(isMasterOnly);
                    if (readmode != null)
                    {
                        connection.Enqueue(readmode);
                        readmode.WriteTo(connection);
                        readmode.SetRequestSent();
                        IncrementOpCount();
                    }

                    if (message.IsAsking)
                    {
                        var asking = ReusableAskingCommand;
                        connection.Enqueue(asking);
                        asking.WriteImpl(connection);
                        asking.SetRequestSent();
                        IncrementOpCount();
                    }
                }
                switch (cmd)
                {
                case RedisCommand.WATCH:
                case RedisCommand.MULTI:
                    connection.TransactionActive = true;
                    break;

                case RedisCommand.UNWATCH:
                case RedisCommand.EXEC:
                case RedisCommand.DISCARD:
                    connection.TransactionActive = false;
                    break;
                }

                connection.Enqueue(message);
                message.WriteImpl(connection);
                message.SetRequestSent();
                IncrementOpCount();

                // some commands smash our ability to trust the database; some commands
                // demand an immediate flush
                switch (cmd)
                {
                case RedisCommand.EVAL:
                case RedisCommand.EVALSHA:
                    if (!ServerEndPoint.GetFeatures().ScriptingDatabaseSafe)
                    {
                        connection.SetUnknownDatabase();
                    }
                    break;

                case RedisCommand.DISCARD:
                case RedisCommand.EXEC:
                    connection.SetUnknownDatabase();
                    break;
                }
                return(true);
            }
            catch (RedisCommandException ex)
            {
                Trace("Write failed: " + ex.Message);
                message.Fail(ConnectionFailureType.ProtocolFailure, ex);
                CompleteSyncOrAsync(message);
                // this failed without actually writing; we're OK with that... unless there's a transaction

                if (connection != null && connection.TransactionActive)
                {
                    // we left it in a broken state; need to kill the connection
                    connection.RecordConnectionFailed(ConnectionFailureType.ProtocolFailure, ex);
                    return(false);
                }
                return(true);
            }
            catch (Exception ex)
            {
                Trace("Write failed: " + ex.Message);
                message.Fail(ConnectionFailureType.InternalFailure, ex);
                CompleteSyncOrAsync(message);

                // we're not sure *what* happened here; probably an IOException; kill the connection
                connection?.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
                return(false);
            }
        }
コード例 #15
0
        internal static Exception DatabaseOutfRange(bool includeDetail, int targetDatabase, Message message, ServerEndPoint server)
        {
            var ex = new RedisCommandException("The database does not exist on the server: " + targetDatabase);

            if (includeDetail)
            {
                AddDetail(ex, message, server, null);
            }
            return(ex);
        }
コード例 #16
0
 internal virtual T ExecuteSync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null)
 {
     if (message == null)
     {
         return(default(T));                 // no-op
     }
     multiplexer.CheckMessage(message);
     return(multiplexer.ExecuteSyncImpl <T>(message, processor, server));
 }
コード例 #17
0
        internal static Exception MasterOnly(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server)
        {
            string s  = GetLabel(includeDetail, command, message);
            var    ex = new RedisCommandException("Command cannot be issued to a slave: " + s);

            if (includeDetail)
            {
                AddDetail(ex, message, server, s);
            }
            return(ex);
        }
コード例 #18
0
        internal virtual RedisFeatures GetFeatures(int db, RedisKey key, CommandFlags flags, out ServerEndPoint server)
        {
            server = multiplexer.SelectServer(db, RedisCommand.PING, flags, key);
            var version = server == null ? multiplexer.RawConfig.DefaultVersion : server.Version;

            return(new RedisFeatures(version));
        }
コード例 #19
0
 public static ProfileStorage NewAttachedToSameContext(ProfileStorage resentFor, ServerEndPoint server, bool isMoved)
 {
     return(new ProfileStorage(resentFor.PushToWhenFinished, server, resentFor, isMoved ? RetransmissionReasonType.Moved : RetransmissionReasonType.Ask));
 }
コード例 #20
0
        internal override Task <T> ExecuteAsync <T>(Message message, ResultProcessor <T> processor, ServerEndPoint server = null)
        {
            if (message == null)
            {
                return(CompletedTask <T> .Default(asyncState));
            }
            multiplexer.CheckMessage(message);

            // prepare the inner command as a task
            Task <T> task;

            if (message.IsFireAndForget)
            {
                task = CompletedTask <T> .Default(null); // F+F explicitly does not get async-state
            }
            else
            {
                var tcs    = TaskSource.CreateDenyExecSync <T>(asyncState);
                var source = ResultBox <T> .Get(tcs);

                message.SetSource(source, processor);
                task = tcs.Task;
            }

            // store it
            (pending ?? (pending = new List <Message>())).Add(message);
            return(task);
        }