// internally, this is very similar to RawResult, except it is designed to be usable
        // outside of the IO-processing pipeline: the buffers are standalone, etc

        internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result)
        {
            try
            {
                switch (result.Type)
                {
                    case ResultType.Integer:
                    case ResultType.SimpleString:
                    case ResultType.BulkString:
                        return new SingleRedisResult(result.AsRedisValue());
                    case ResultType.MultiBulk:
                        var items = result.GetItems();
                        var arr = new RedisResult[items.Length];
                        for (int i = 0; i < arr.Length; i++)
                        {
                            var next = TryCreate(connection, items[i]);
                            if (next == null) return null; // means we didn't understand
                            arr[i] = next;
                        }
                        return new ArrayRedisResult(arr);
                    case ResultType.Error:
                        return new ErrorRedisResult(result.GetString());
                    default:
                        return null;
                }
            } catch(Exception ex)
            {
                connection?.OnInternalError(ex);
                return null; // will be logged as a protocol fail by the processor
            }
        }
 internal async Task OnConnectedAsync(PhysicalConnection connection, TextWriter log)
 {
     Trace("OnConnected");
     if (physical == connection && !isDisposed && ChangeState(State.Connecting, State.ConnectedEstablishing))
     {
         await ServerEndPoint.OnEstablishingAsync(connection, log).ForAwait();
     }
     else
     {
         try
         {
             connection.Dispose();
         }
         catch { }
     }
 }
Пример #3
0
        private void SelectDatabase(PhysicalConnection connection, Message message)
        {
            int db = message.Db;

            if (db >= 0)
            {
                var sel = connection.GetSelectDatabaseCommand(db, message);
                if (sel != null)
                {
                    connection.Enqueue(sel);
                    sel.WriteImpl(connection);
                    sel.SetRequestSent();
                    IncrementOpCount();
                }
            }
        }
Пример #4
0
 internal void WriteTo(PhysicalConnection physical)
 {
     try
     {
         WriteImpl(physical);
     }
     catch (RedisCommandException)
     { // these have specific meaning; don't wrap
         throw;
     }
     catch (Exception ex)
     {
         physical?.OnInternalError(ex);
         Fail(ConnectionFailureType.InternalFailure, ex);
     }
 }
Пример #5
0
 // note that top-level error messages still get handled by SetResult, but nested errors
 // (is that a thing?) will be wrapped in the RedisResult
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     switch (result.Type)
     {
     case ResultType.BulkString:
         var hash = result.GetBlob();
         var sl   = message as RedisDatabase.ScriptLoadMessage;
         if (sl != null)
         {
             connection.Bridge.ServerEndPoint.AddScript(sl.Script, hash);
         }
         SetResult(message, hash);
         return(true);
     }
     return(false);
 }
 internal void WriteDirectOrQueueFireAndForget <T>(PhysicalConnection connection, Message message, ResultProcessor <T> processor)
 {
     if (message != null)
     {
         message.SetSource(processor, null);
         if (connection == null)
         {
             multiplexer.Trace("Enqueue: " + message);
             GetBridge(message.Command).TryEnqueue(message, isSlave);
         }
         else
         {
             multiplexer.Trace("Writing direct: " + message);
             connection.Bridge.WriteMessageDirect(connection, message);
         }
     }
 }
Пример #7
0
 internal void OnConnected(PhysicalConnection connection, TextWriter log)
 {
     Trace("OnConnected");
     if (physical == connection && !isDisposed && ChangeState(State.Connecting, State.ConnectedEstablishing))
     {
         ServerEndPoint.OnEstablishing(connection, log);
     }
     else
     {
         try
         {
             connection.Dispose();
         }
         catch
         { }
     }
 }
Пример #8
0
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     switch (result.Type)
     {
     case ResultType.Integer:
     case ResultType.SimpleString:
     case ResultType.BulkString:
         long i64;
         if (result.TryGetInt64(out i64))
         {
             SetResult(message, i64);
             return(true);
         }
         break;
     }
     return(false);
 }
Пример #9
0
        private void WritePendingBacklogSync(PhysicalConnection connection)
        {
            if (connection != null)
            {
                Message next;
                do
                {
                    next = DequeueNextPendingBacklog();
#pragma warning disable CS0618
                    if (next != null)
                    {
                        WriteMessageTakingWriteLockSync(connection, next);
                    }
#pragma warning restore CS0618
                } while (next != null);
            }
        }
Пример #10
0
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     switch (result.Type)
     {
     case ResultType.Integer:
     case ResultType.SimpleString:
     case ResultType.BulkString:
         string nodes = result.GetString();
         try
         { ClusterNodesProcessor.Parse(connection, nodes); }
         catch
         { /* tralalalala */ }
         SetResult(message, nodes);
         return(true);
     }
     return(false);
 }
Пример #11
0
        // internally, this is very similar to RawResult, except it is designed to be usable
        // outside of the IO-processing pipeline: the buffers are standalone, etc

        internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result)
        {
            try
            {
                switch (result.Type)
                {
                case ResultType.Integer:
                case ResultType.SimpleString:
                case ResultType.BulkString:
                    return(new SingleRedisResult(result.AsRedisValue(), result.Type));

                case ResultType.MultiBulk:
                    if (result.IsNull)
                    {
                        return(NullArray);
                    }
                    var items = result.GetItems();
                    if (items.Length == 0)
                    {
                        return(EmptyArray);
                    }
                    var arr = new RedisResult[items.Length];
                    for (int i = 0; i < arr.Length; i++)
                    {
                        var next = TryCreate(connection, items[i]);
                        if (next == null)
                        {
                            return(null);                  // means we didn't understand
                        }
                        arr[i] = next;
                    }
                    return(new ArrayRedisResult(arr));

                case ResultType.Error:
                    return(new ErrorRedisResult(result.GetString()));

                default:
                    return(null);
                }
            }
            catch (Exception ex)
            {
                connection?.OnInternalError(ex);
                return(null); // will be logged as a protocol fail by the processor
            }
        }
Пример #12
0
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     switch (result.Type)
     {
     case ResultType.MultiBulk:
         var  arr = result.GetItems();
         long i64;
         if (arr.Length == 2 && arr[1].Type == ResultType.MultiBulk && arr[0].TryGetInt64(out i64))
         {
             var keysResult = new ScanResult(i64, arr[1].GetItemsAsKeys());
             SetResult(message, keysResult);
             return(true);
         }
         break;
     }
     return(false);
 }
 private static Action <Task <int> > EndReadFactory(PhysicalConnection physical)
 {
     return(result =>
     {   // can't capture AsyncState on SocketRead, so we'll do it once per physical instead
         try
         {
             physical.Multiplexer.Trace("Completed asynchronously: processing in callback", physical.physicalName);
             if (physical.EndReading(result))
             {
                 physical.BeginReading();
             }
         }
         catch (Exception ex)
         {
             physical.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
         }
     });
 }
 public override bool SetResult(PhysicalConnection connection, Message message, RawResult result)
 {
     if (result.IsError)
     {
         var tran = message as TransactionMessage;
         if (tran != null)
         {
             string error  = result.GetString();
             var    bridge = connection.Bridge;
             foreach (var op in tran.InnerOperations)
             {
                 ServerFail(op.Wrapped, error);
                 bridge.CompleteSyncOrAsync(op.Wrapped);
             }
         }
     }
     return(base.SetResult(connection, message, result));
 }
Пример #15
0
        private WriteResult WriteMessageInsideLock(PhysicalConnection physical, Message message)
        {
            WriteResult result;
            var         existingMessage = Interlocked.CompareExchange(ref _activeMesssage, message, null);

            if (existingMessage != null)
            {
                Multiplexer?.OnInfoMessage($"reentrant call to WriteMessageTakingWriteLock for {message.CommandAndKey}, {existingMessage.CommandAndKey} is still active");
                return(WriteResult.NoConnectionAvailable);
            }
            physical.SetWriting();
            var messageIsSent = false;

            if (message is IMultiMessage)
            {
                SelectDatabaseInsideWriteLock(physical, message); // need to switch database *before* the transaction
                foreach (var subCommand in ((IMultiMessage)message).GetMessages(physical))
                {
                    result = WriteMessageToServerInsideWriteLock(physical, subCommand);
                    if (result != WriteResult.Success)
                    {
                        // we screwed up; abort; note that WriteMessageToServer already
                        // killed the underlying connection
                        Trace("Unable to write to server");
                        message.Fail(ConnectionFailureType.ProtocolFailure, null, "failure before write: " + result.ToString());
                        this.CompleteSyncOrAsync(message);
                        return(result);
                    }
                    //The parent message (next) may be returned from GetMessages
                    //and should not be marked as sent again below
                    messageIsSent = messageIsSent || subCommand == message;
                }
                if (!messageIsSent)
                {
                    message.SetRequestSent(); // well, it was attempted, at least...
                }

                return(WriteResult.Success);
            }
            else
            {
                return(WriteMessageToServerInsideWriteLock(physical, message));
            }
        }
Пример #16
0
        internal WriteResult WriteMessageTakingWriteLockSync(PhysicalConnection physical, Message message)
        {
            Trace("Writing: " + message);
            message.SetEnqueued(physical); // this also records the read/write stats at this point

            LockToken token = default;

            try
            {
                token = _singleWriterMutex.TryWait(WaitOptions.NoDelay);
                if (!token.Success)
                {
                    // we can't get it *instantaneously*; is there
                    // perhaps a backlog and active backlog processor?
                    if (PushToBacklog(message, onlyIfExists: true))
                    {
                        return(WriteResult.Success);                                            // queued counts as success
                    }
                    // no backlog... try to wait with the timeout;
                    // if we *still* can't get it: that counts as
                    // an actual timeout
                    token = _singleWriterMutex.TryWait();
                    if (!token.Success)
                    {
                        return(TimedOutBeforeWrite(message));
                    }
                }

                var result = WriteMessageInsideLock(physical, message);

                if (result == WriteResult.Success)
                {
#pragma warning disable CS0618
                    result = physical.FlushSync(false, TimeoutMilliseconds);
#pragma warning restore CS0618
                }

                UnmarkActiveMessage(message);
                physical.SetIdle();
                return(result);
            }
            catch (Exception ex) { return(HandleWriteException(message, ex)); }
            finally { token.Dispose(); }
        }
Пример #17
0
 internal void OnFullyEstablished(PhysicalConnection connection)
 {
     Trace("OnFullyEstablished");
     if (physical == connection && !isDisposed && ChangeState(State.ConnectedEstablishing, State.ConnectedEstablished))
     {
         reportNextFailure = reconfigureNextFailure = true;
         Interlocked.Exchange(ref failConnectCount, 0);
         serverEndPoint.OnFullyEstablished(connection);
         multiplexer.RequestWrite(this, true);
         if (connectionType == ConnectionType.Interactive)
         {
             serverEndPoint.CheckInfoReplication();
         }
     }
     else
     {
         try { connection.Dispose(); } catch { }
     }
 }
Пример #18
0
 internal void OnFullyEstablished(PhysicalConnection connection)
 {
     try
     {
         if (connection == null)
         {
             return;
         }
         var bridge = connection.Bridge;
         if (bridge == subscription)
         {
             multiplexer.ResendSubscriptions(this);
         }
         multiplexer.OnConnectionRestored(endpoint, bridge.ConnectionType);
     }
     catch (Exception ex)
     {
         connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
     }
 }
Пример #19
0
            protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
            {
                long unixTime, micros;

                switch (result.Type)
                {
                case ResultType.Integer:
                    if (result.TryGetInt64(out unixTime))
                    {
                        var time = RedisBase.UnixEpoch.AddSeconds(unixTime);
                        SetResult(message, time);
                        return(true);
                    }
                    break;

                case ResultType.MultiBulk:
                    var arr = result.GetItems();
                    switch (arr.Length)
                    {
                    case 1:
                        if (arr[0].TryGetInt64(out unixTime))
                        {
                            var time = RedisBase.UnixEpoch.AddSeconds(unixTime);
                            SetResult(message, time);
                            return(true);
                        }
                        break;

                    case 2:
                        if (arr[0].TryGetInt64(out unixTime) && arr[1].TryGetInt64(out micros))
                        {
                            var time = RedisBase.UnixEpoch.AddSeconds(unixTime).AddTicks(micros * 10);         // datetime ticks are 100ns
                            SetResult(message, time);
                            return(true);
                        }
                        break;
                    }
                    break;
                }
                return(false);
            }
Пример #20
0
            protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
            {
                bool happy;

                switch (message.Command)
                {
                case RedisCommand.ECHO:
                    happy = result.Type == ResultType.BulkString && (!establishConnection || result.IsEqual(connection.Multiplexer.UniqueId));
                    break;

                case RedisCommand.PING:
                    happy = result.Type == ResultType.SimpleString && result.IsEqual(RedisLiterals.BytesPONG);
                    break;

                case RedisCommand.TIME:
                    happy = result.Type == ResultType.MultiBulk && result.GetItems().Length == 2;
                    break;

                case RedisCommand.EXISTS:
                    happy = result.Type == ResultType.Integer;
                    break;

                default:
                    happy = true;
                    break;
                }
                if (happy)
                {
                    if (establishConnection)
                    {
                        connection.Bridge.OnFullyEstablished(connection);
                    }
                    SetResult(message, happy);
                    return(true);
                }
                else
                {
                    connection.RecordConnectionFailed(ConnectionFailureType.ProtocolFailure);
                    return(false);
                }
            }
Пример #21
0
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     switch (result.Type)
     {
     case ResultType.SimpleString:
     case ResultType.BulkString:
         string    s = result.GetString();
         RedisType value;
         if (string.Equals(s, "zset", StringComparison.OrdinalIgnoreCase))
         {
             value = Redis.RedisType.SortedSet;
         }
         else if (!Enum.TryParse <RedisType>(s, true, out value))
         {
             value = global::StackExchange.Redis.RedisType.Unknown;
         }
         SetResult(message, value);
         return(true);
     }
     return(false);
 }
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     switch (result.Type)
     {
     case ResultType.MultiBulk:
         var            parts = result.GetItems();
         CommandTrace[] arr   = new CommandTrace[parts.Length];
         for (int i = 0; i < parts.Length; i++)
         {
             var subParts = parts[i].GetItems();
             if (!subParts[0].TryGetInt64(out long uniqueid) || !subParts[1].TryGetInt64(out long time) || !subParts[2].TryGetInt64(out long duration))
             {
                 return(false);
             }
             arr[i] = new CommandTrace(uniqueid, time, duration, subParts[3].GetItemsAsValues());
         }
         SetResult(message, arr);
         return(true);
     }
     return(false);
 }
Пример #23
0
            public override bool SetResult(PhysicalConnection connection, Message message, RawResult result)
            {
                var final = base.SetResult(connection, message, result);

                if (result.IsError)
                {
                    if (result.IsEqual(authFail))
                    {
                        connection.RecordConnectionFailed(ConnectionFailureType.AuthenticationFailure);
                    }
                    else if (result.AssertStarts(loading))
                    {
                        connection.RecordConnectionFailed(ConnectionFailureType.Loading);
                    }
                    else
                    {
                        connection.RecordConnectionFailed(ConnectionFailureType.ProtocolFailure);
                    }
                }
                return(final);
            }
Пример #24
0
        internal Task OnEstablishingAsync(PhysicalConnection connection, TextWriter log)
        {
            try
            {
                if (connection == null)
                {
                    return(Task.CompletedTask);
                }
                var handshake = HandshakeAsync(connection, log);

                if (handshake.Status != TaskStatus.RanToCompletion)
                {
                    return(OnEstablishingAsyncAwaited(connection, handshake));
                }
            }
            catch (Exception ex)
            {
                connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
            }
            return(Task.CompletedTask);
        }
Пример #25
0
        /// <summary>
        /// This writes a message to the output stream
        /// </summary>
        /// <param name="physical">The phsyical connection to write to.</param>
        /// <param name="message">The message to be written.</param>
        internal ValueTask <WriteResult> WriteMessageTakingWriteLockAsync(PhysicalConnection physical, Message message)
        {
            Trace("Writing: " + message);
            message.SetEnqueued(physical); // this also records the read/write stats at this point

            bool haveLock = false;

            try
            {
                // try to acquire it synchronously
                haveLock = _SingleWriterLock.Wait(0);
                if (!haveLock)
                {
                    return(new ValueTask <WriteResult>(WriteMessageTakingDelayedWriteLockAsync(physical, message)));
                }

                var result = WriteMessageInsideLock(physical, message);

                if (result == WriteResult.Success)
                {
                    var flush = physical.FlushAsync(false);
                    if (!flush.IsCompletedSuccessfully)
                    {
                        haveLock = false; // so we don't release prematurely
                        return(new ValueTask <WriteResult>(CompleteWriteAndReleaseLockAsync(flush, message)));
                    }

                    result = flush.Result; // we know it was completed, this is fine
                }
                physical.SetIdle();

                return(new ValueTask <WriteResult>(result));
            }
            catch (Exception ex) { return(new ValueTask <WriteResult>(HandleWriteException(message, ex))); }
            finally { if (haveLock)
                      {
                          ReleaseSingleWriterLock(message);
                      }
            }
        }
Пример #26
0
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     switch (result.Type)
     {
     case ResultType.Integer:
     case ResultType.SimpleString:
     case ResultType.BulkString:
         if (result.IsNull)
         {
             SetResult(message, null);
             return(true);
         }
         double val;
         if (result.TryGetDouble(out val))
         {
             SetResult(message, val);
             return(true);
         }
         break;
     }
     return(false);
 }
Пример #27
0
        internal void OnFullyEstablished(PhysicalConnection connection)
        {
            Trace("OnFullyEstablished");
            connection?.SetIdle();
            if (physical == connection && !isDisposed && ChangeState(State.ConnectedEstablishing, State.ConnectedEstablished))
            {
                reportNextFailure = reconfigureNextFailure = true;
                LastException     = null;
                Interlocked.Exchange(ref failConnectCount, 0);
                ServerEndPoint.OnFullyEstablished(connection);
                WritePendingBacklog(connection);

                if (ConnectionType == ConnectionType.Interactive)
                {
                    ServerEndPoint.CheckInfoReplication();
                }
            }
            else
            {
                try { connection.Dispose(); } catch { }
            }
        }
Пример #28
0
 internal void OnFullyEstablished(PhysicalConnection connection)
 {
     try
     {
         if (connection == null)
         {
             return;
         }
         var bridge = connection.BridgeCouldBeNull;
         if (bridge != null)
         {
             if (bridge == subscription)
             {
                 Multiplexer.ResendSubscriptions(this);
             }
             Multiplexer.OnConnectionRestored(EndPoint, bridge.ConnectionType, connection?.ToString());
         }
     }
     catch (Exception ex)
     {
         connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
     }
 }
Пример #29
0
        internal WriteResult WriteMessageTakingWriteLockSync(PhysicalConnection physical, Message message)
        {
            Trace("Writing: " + message);
            message.SetEnqueued(physical); // this also records the read/write stats at this point

            bool haveLock = false;

            try
            {
                haveLock = _SingleWriterLock.Wait(TimeoutMilliseconds);
                if (!haveLock)
                {
                    message.Cancel();
                    Multiplexer?.OnMessageFaulted(message, null);
                    this.CompleteSyncOrAsync(message);
                    return(WriteResult.TimeoutBeforeWrite);
                }

                var result = WriteMessageInsideLock(physical, message);

                if (result == WriteResult.Success)
                {
#pragma warning disable CS0618
                    result = physical.FlushSync(false, TimeoutMilliseconds);
#pragma warning restore CS0618
                }

                physical.SetIdle();
                return(result);
            }
            catch (Exception ex) { return(HandleWriteException(message, ex)); }
            finally { if (haveLock)
                      {
                          ReleaseSingleWriterLock(message);
                      }
            }
        }
Пример #30
0
        internal void OnDisconnected(ConnectionFailureType failureType, PhysicalConnection connection, out bool isCurrent, out State oldState)
        {
            Trace("OnDisconnected");

            // if the next thing in the pipe is a PING, we can tell it that we failed (this really helps spot doomed connects)
            // note that for simplicity we haven't removed it from the queue; that's OK
            int count;
            var ping = queue.PeekPing(out count);

            if (ping != null)
            {
                Trace("Marking PING as failed (queue length: " + count + ")");
                ping.Fail(failureType, null);
                CompleteSyncOrAsync(ping);
            }
            oldState = default(State); // only defined when isCurrent = true
            if (isCurrent = (physical == connection))
            {
                Trace("Bridge noting disconnect from active connection" + (isDisposed ? " (disposed)" : ""));
                oldState = ChangeState(State.Disconnected);
                physical = null;

                if (!isDisposed && Interlocked.Increment(ref failConnectCount) == 1)
                {
                    GetConnection(null); // try to connect immediately
                }
            }
            else if (physical == null)
            {
                Trace("Bridge noting disconnect (already terminated)");
            }
            else
            {
                Trace("Bridge noting disconnect, but from different connection");
            }
        }
Пример #31
0
 protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
 {
     if (result.Type == ResultType.BulkString)
     {
         string category = Normalize(null), line;
         var    list = new List <Tuple <string, KeyValuePair <string, string> > >();
         using (var reader = new StringReader(result.GetString()))
         {
             while ((line = reader.ReadLine()) != null)
             {
                 if (string.IsNullOrWhiteSpace(line))
                 {
                     continue;
                 }
                 if (line.StartsWith("# "))
                 {
                     category = Normalize(line.Substring(2));
                     continue;
                 }
                 int idx = line.IndexOf(':');
                 if (idx < 0)
                 {
                     continue;
                 }
                 var pair = new KeyValuePair <string, string>(
                     line.Substring(0, idx).Trim(),
                     line.Substring(idx + 1).Trim());
                 list.Add(Tuple.Create(category, pair));
             }
         }
         var final = list.GroupBy(x => x.Item1, x => x.Item2).ToArray();
         SetResult(message, final);
         return(true);
     }
     return(false);
 }
Пример #32
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
                if(connection != null) connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
                return false;
            }
        }
Пример #33
0
 private void SelectDatabase(PhysicalConnection connection, Message message)
 {
     int db = message.Db;
     if (db >= 0)
     {
         var sel = connection.GetSelectDatabaseCommand(db, message);
         if (sel != null)
         {
             connection.Enqueue(sel);
             sel.WriteImpl(connection);
             sel.SetRequestSent();
             IncrementOpCount();
         }
     }
 }
Пример #34
0
 private PhysicalConnection GetConnection(TextWriter log)
 {
     if (state == (int)State.Disconnected)
     {
         try
         {
             if (!multiplexer.IsDisposed)
             {
                 Multiplexer.LogLocked(log, "Connecting {0}...", Name);
                 Multiplexer.Trace("Connecting...", Name);
                 if (ChangeState(State.Disconnected, State.Connecting))
                 {
                     Interlocked.Increment(ref socketCount);
                     Interlocked.Exchange(ref connectStartTicks, Environment.TickCount);
                     // separate creation and connection for case when connection completes synchronously
                     // in that case PhysicalConnection will call back to PhysicalBridge, and most of  PhysicalBridge methods assumes that physical is not null;
                     physical = new PhysicalConnection(this);
                     physical.BeginConnect(log);
                 }
             }
             return null;
         }
         catch (Exception ex)
         {
             Multiplexer.LogLocked(log, "Connect {0} failed: {1}", Name, ex.Message);
             Multiplexer.Trace("Connect failed: " + ex.Message, Name);
             ChangeState(State.Disconnected);
             OnInternalError(ex);
             throw;
         }
     }
     return physical;
 }
Пример #35
0
        /// <summary>
        /// This writes a message **directly** to the output stream; note
        /// that this ignores the queue, so should only be used *either*
        /// from the regular dequeue loop, *or* from the "I've just
        /// connected" handshake (when there is no dequeue loop) - otherwise,
        /// you can pretty much assume you're going to destroy the stream
        /// </summary>
        internal bool WriteMessageDirect(PhysicalConnection tmp, Message next)
        {
            Trace("Writing: " + next);
            if (next is IMultiMessage)
            {
                SelectDatabase(tmp, next); // need to switch database *before* the transaction
                foreach (var subCommand in ((IMultiMessage)next).GetMessages(tmp))
                {
                    if (!WriteMessageToServer(tmp, subCommand))
                    {
                        // we screwed up; abort; note that WriteMessageToServer already
                        // killed the underlying connection
                        Trace("Unable to write to server");
                        next.Fail(ConnectionFailureType.ProtocolFailure, null);
                        CompleteSyncOrAsync(next);
                        return false;
                    }
                }

                next.SetRequestSent();

                return true;
            }
            else
            {
                return WriteMessageToServer(tmp, next);
            }
        }
Пример #36
0
        internal void RemovePhysical(PhysicalConnection connection)
        {
#pragma warning disable 0420
            Interlocked.CompareExchange(ref physical, null, connection);
#pragma warning restore 0420
        }
Пример #37
0
 internal void OnFullyEstablished(PhysicalConnection connection)
 {
     Trace("OnFullyEstablished");
     if (physical == connection && !isDisposed && ChangeState(State.ConnectedEstablishing, State.ConnectedEstablished))
     {
         reportNextFailure = reconfigureNextFailure = true;
         Interlocked.Exchange(ref failConnectCount, 0);
         serverEndPoint.OnFullyEstablished(connection);
         multiplexer.RequestWrite(this, true);
         if(connectionType == ConnectionType.Interactive) serverEndPoint.CheckInfoReplication();
     }
     else
     {
         try { connection.Dispose(); } catch { }
     }
 }
Пример #38
0
        internal void OnDisconnected(ConnectionFailureType failureType, PhysicalConnection connection, out bool isCurrent, out State oldState)
        {
            Trace("OnDisconnected");

            // if the next thing in the pipe is a PING, we can tell it that we failed (this really helps spot doomed connects)
            // note that for simplicity we haven't removed it from the queue; that's OK
            int count;
            var ping = queue.PeekPing(out count);
            if (ping != null)
            {
                Trace("Marking PING as failed (queue length: " + count + ")");
                ping.Fail(failureType, null);
                CompleteSyncOrAsync(ping);
            }
            oldState = default(State); // only defined when isCurrent = true
            if (isCurrent = (physical == connection))
            {
                Trace("Bridge noting disconnect from active connection" + (isDisposed ? " (disposed)" : ""));
                oldState = ChangeState(State.Disconnected);
                physical = null;

                if (!isDisposed && Interlocked.Increment(ref failConnectCount) == 1)
                {
                    GetConnection(null); // try to connect immediately
                }
            }
            else if (physical == null)
            {
                Trace("Bridge noting disconnect (already terminated)");
            }
            else
            {
                Trace("Bridge noting disconnect, but from different connection");
            }
        }
Пример #39
0
 internal void OnConnectionFailed(PhysicalConnection connection, ConnectionFailureType failureType, Exception innerException)
 {
     if (reportNextFailure)
     {
         reportNextFailure = false; // until it is restored
         var endpoint = serverEndPoint.EndPoint;
         multiplexer.OnConnectionFailed(endpoint, connectionType, failureType, innerException, reconfigureNextFailure);
     }
 }
Пример #40
0
 internal void OnConnected(PhysicalConnection connection, TextWriter log)
 {
     Trace("OnConnected");
     if (physical == connection && !isDisposed && ChangeState(State.Connecting, State.ConnectedEstablishing))
     {
         serverEndPoint.OnEstablishing(connection, log);
     }
     else
     {
         try
         {
             connection.Dispose();
         }
         catch
         { }
     }
 }
Пример #41
0
 public void Dispose()
 {
     isDisposed = true;
     using (var tmp = physical)
     {
         physical = null;
     }
 }
 private PhysicalConnection GetConnection()
 {
     if (state == (int)State.Disconnected)
     {
         try
         {
             if (!multiplexer.IsDisposed)
             {
                 Multiplexer.Trace("Connecting...", Name);
                 if (ChangeState(State.Disconnected, State.Connecting))
                 {
                     Interlocked.Increment(ref socketCount);
                     physical = new PhysicalConnection(this);
                 }
             }
             return null;
         }
         catch (Exception ex)
         {
             Multiplexer.Trace("Connect failed: " + ex.Message, Name);
             ChangeState(State.Disconnected);
             OnInternalError(ex);
             throw;
         }
     }
     return physical;
 }