Пример #1
0
 public void Enqueue(RedisMessage item, bool highPri)
 {
     lock (stdPriority)
     {
         if (closed)
         {
             throw new InvalidOperationException("The queue is closed");
         }
         if (highPri)
         {
             highPriority.Enqueue(item);
         }
         else
         {
             while (stdPriority.Count >= maxSize)
             {
                 Monitor.Wait(stdPriority);
             }
             stdPriority.Enqueue(item);
         }
         if (stdPriority.Count + highPriority.Count == 1)
         {
             // wake up any blocked dequeue
             Monitor.PulseAll(stdPriority);
         }
     }
 }
Пример #2
0
        Task IHashCommands.Set(int db, string key, Dictionary <string, byte[]> values, bool queueJump)
        {
            var keyAndFields = new RedisMessage.RedisParameter[(values.Count * 2) + 1];
            int index        = 0;

            keyAndFields[index++] = key;
            foreach (var pair in values)
            {
                keyAndFields[index++] = pair.Key;
                keyAndFields[index++] = pair.Value;
            }
            return(ExecuteVoid(RedisMessage.Create(db, RedisLiteral.HMSET, keyAndFields), queueJump));
        }
        Task <long> ISortedSetCommands.IntersectAndStore(int db, string destination, string[] keys,
                                                         RedisAggregate aggregate, bool queueJump)
        {
            var parameters = new string[keys.Length + 3];

            //prepend the number of keys and append the aggregate keyword and the aggregation type
            parameters[0] = keys.Length.ToString();
            keys.CopyTo(parameters, 1);
            parameters[keys.Length + 1] = "AGGREGATE";
            parameters[keys.Length + 2] = aggregate.ToString();

            return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.ZINTERSTORE, destination, parameters), queueJump));
        }
Пример #4
0
        void IMessageResult.Complete(RedisResult result, RedisMessage message, bool includeDetail)
        {
            if (result.IsCancellation)
            {
                RedisConnectionBase.Trace("transaction", "cancelled");
                SetInnerReplies(result);
                completion.TrySetCanceled();
            }
            else if (result.IsError)
            {
                RedisConnectionBase.Trace("transaction", "error");
                SetInnerReplies(result);
                completion.SafeSetException(result.Error());
            }
            else
            {
                try
                {
                    if (result.IsNil)
                    {   // aborted
                        RedisConnectionBase.Trace("transaction", "aborted");
                        SetInnerReplies(RedisResult.Cancelled);
                        completion.TrySetResult(false);
                    }
                    else
                    {
                        var items = result.ValueItems;
                        if (items.Length != (queued == null ? 0 : queued.Length))
                        {
                            throw new InvalidOperationException(string.Format("{0} results expected, {1} received", queued.Length, items.Length));
                        }

                        RedisConnectionBase.Trace("transaction", "success");
                        for (int i = 0; i < items.Length; i++)
                        {
                            RedisResult reply = items[i];
                            RedisConnectionBase.CallbackMode callbackMode;
                            var ctx = parent.ProcessReply(ref reply, queued[i].InnerMessage, out callbackMode);
                            RedisConnectionBase.Trace("transaction", "{0} = {1}", ctx, reply);
                            parent.ProcessCallbacks(ctx, reply, callbackMode);
                        }
                        completion.TrySetResult(true);
                    }
                }
                catch (Exception ex)
                {
                    completion.SafeSetException(ex);
                    throw;
                }
            }
        }
        /// <summary>
        ///     Attempts to open the connection to the remote server
        /// </summary>
        public async Task Open()
        {
            int foundState;

            if (
                (foundState =
                     Interlocked.CompareExchange(ref state, (int)ConnectionState.Opening, (int)ConnectionState.Shiny)) !=
                (int)ConnectionState.Shiny)
            {
                throw new InvalidOperationException("Connection is " + (ConnectionState)foundState);  // not shiny
            }
            try
            {
                OnOpening();
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                {
                    NoDelay     = true,
                    SendTimeout = ioTimeout
                };

                socket.Connect(host, port);
                redisStream             = new NetworkStream(socket);
                outBuffer               = new BufferedStream(redisStream, 512); // buffer up operations
                redisStream.ReadTimeout = redisStream.WriteTimeout = ioTimeout;

                var thread = new Thread(Outgoing)
                {
                    IsBackground = true, Name = "Redis:outgoing"
                };
                thread.Start();

                if (!string.IsNullOrEmpty(password))
                {
                    EnqueueMessage(RedisMessage.Create(-1, RedisLiteral.AUTH, password).ExpectOk().Critical(), true);
                }

                Task <string> info = GetInfo();
                OnInitConnection();
                ReadMoreAsync();

                var result = await info;

                ProcessInfo(result);
                //return ContinueWith(info, ProcessInfo);
            }
            catch
            {
                Interlocked.CompareExchange(ref state, (int)ConnectionState.Closed, (int)ConnectionState.Opening);
                throw;
            }
        }
Пример #6
0
            // avoid lots of delegate creations

            internal override sealed IEnumerable <RedisMessage> CreateMessages()
            {
                yield return(RedisMessage.Create(db, RedisLiteral.WATCH, key));

                IMessageResult msgResult = CreateMessageResult(this);

                msgResult.Task.ContinueWith(testEquality);
                RedisMessage message = hashField == null
                                           ? RedisMessage.Create(db, RedisLiteral.GET, key)
                                           : RedisMessage.Create(db, RedisLiteral.HGET, key, hashField);

                message.SetMessageResult(msgResult);
                yield return(message);
            }
Пример #7
0
 public RedisMessage[] DequeueAll()
 {
     lock (stdPriority)
     {
         RedisMessage[] result = new RedisMessage[highPriority.Count + stdPriority.Count];
         highPriority.CopyTo(result, 0);
         stdPriority.CopyTo(result, highPriority.Count);
         highPriority.Clear();
         stdPriority.Clear();
         // wake up any blocked enqueue
         Monitor.PulseAll(stdPriority);
         return result;
     }
 }
Пример #8
0
 public RedisMessage[] DequeueAll()
 {
     lock (stdPriority)
     {
         var result = new RedisMessage[highPriority.Count + stdPriority.Count];
         highPriority.CopyTo(result, 0);
         stdPriority.CopyTo(result, highPriority.Count);
         highPriority.Clear();
         stdPriority.Clear();
         // wake up any blocked enqueue
         Monitor.PulseAll(stdPriority);
         return(result);
     }
 }
Пример #9
0
        internal override void RecordSent(RedisMessage message, bool drainFirst)
        {
            base.RecordSent(message, drainFirst);

            lock (sent)
            {
                if (drainFirst && sent.Count != 0)
                {
                    // drain it down; the dequeuer will wake us
                    Monitor.Wait(sent);
                }
                sent.Enqueue(message);
            }
        }
Пример #10
0
 protected override void ProcessError(RedisResult result, RedisMessage message, bool includeDetail)
 {
     try {
         var msg = result.Error().Message;
         if (msg.StartsWith("NOSCRIPT"))
         {   // only way of unloading is to unload all ("SCRIPT FLUSH")... so our
             // existing cache is now completely toast
             connection.ResetScriptCache();
         }
     } catch {
         /* best efforts only */
     }
     base.ProcessError(result, message, includeDetail);
 }
Пример #11
0
            // avoid lots of delegate creations

            internal override IEnumerable <RedisMessage> CreateMessages()
            {
                yield return(RedisMessage.Create(db, RedisLiteral.WATCH, key));

                var msgResult = new MessageResultBoolean(this);

                msgResult.Task.ContinueWith(testExisted);
                RedisMessage message = hashField == null
                                           ? RedisMessage.Create(db, RedisLiteral.EXISTS, key)
                                           : RedisMessage.Create(db, RedisLiteral.HEXISTS, key, hashField);

                message.SetMessageResult(msgResult);
                yield return(message);
            }
Пример #12
0
        internal Task <Dictionary <string, string> > GetConfigImpl(string pattern, bool isInit)
        {
            if (string.IsNullOrEmpty(pattern))
            {
                pattern = "*";
            }
            var msg = RedisMessage.Create(-1, RedisLiteral.CONFIG, RedisLiteral.GET, pattern);

            if (isInit)
            {
                msg.DuringInit();
            }
            return(ExecuteStringPairs(msg, false));
        }
Пример #13
0
        Task <string> IListCommands.BlockingRemoveLastAndAddFirstString(int db, string source, string destination, int timeoutSeconds, bool queueJump)
        {
            var taskSource = new TaskCompletionSource <string>();
            var msg        = ExecuteRaw(RedisMessage.Create(db, RedisLiteral.BRPOPLPUSH, source, destination, timeoutSeconds), queueJump, taskSource);

            msg.ContinueWith(x => {
                var src = (TaskCompletionSource <string>)x.AsyncState;
                if (x.ShouldSetResult(src))
                {
                    src.TrySetResult(x.Result == null || x.Result is MultiRedisResult ? null : x.Result.ValueString);
                }
            });
            return(taskSource.Task);
        }
        private void ProcessInfo(string done)
        {
            try
            {
                // process this when available
                Dictionary <string, string> parsed = ParseInfo(done);
                string  s;
                Version version;
                if (parsed.TryGetValue("redis_version", out s) && TryParseVersion(s, out version))
                {
                    ServerVersion = version;
                }
                if (parsed.TryGetValue("redis_mode", out s) && s == "sentinel")
                {
                    ServerType = ServerType.Sentinel;
                }
                else if (parsed.TryGetValue("role", out s) && s != null)
                {
                    switch (s)
                    {
                    case "master":
                        ServerType = ServerType.Master;
                        break;

                    case "slave":
                        ServerType = ServerType.Slave;
                        break;
                    }
                    if (!string.IsNullOrEmpty(name))
                    {
                        RedisFeatures tmp = Features;
                        if (tmp != null && tmp.ClientName)
                        {
                            ExecuteVoid(
                                RedisMessage.Create(-1, RedisLiteral.CLIENT, RedisLiteral.SETNAME, name),
                                true);
                        }
                    }
                }
                Interlocked.CompareExchange(ref state, (int)ConnectionState.Open,
                                            (int)ConnectionState.Opening);
            }
            catch
            {
                Close(true);
                Interlocked.CompareExchange(ref state, (int)ConnectionState.Closed,
                                            (int)ConnectionState.Opening);
            }
        }
Пример #15
0
        private static RedisMessage CreateSortMessage(int db, string key, string byPattern, string[] getPattern,
                                                      long offset, long count, bool alpha, bool ascending,
                                                      string storeKey)
        {
            var items = new List <RedisMessage.RedisParameter> {
                key
            };

            if (!string.IsNullOrEmpty(byPattern))
            {
                items.Add(RedisLiteral.BY);
                items.Add(byPattern);
            }

            if (offset != 0 || (count != -1 && count != long.MaxValue))
            {
                items.Add(RedisLiteral.LIMIT);
                items.Add(offset);
                items.Add(count);
            }

            if (getPattern != null)
            {
                foreach (string pattern in getPattern)
                {
                    if (!string.IsNullOrEmpty(pattern))
                    {
                        items.Add(RedisLiteral.GET);
                        items.Add(pattern);
                    }
                }
            }

            if (!ascending)
            {
                items.Add(RedisLiteral.DESC);
            }
            if (alpha)
            {
                items.Add(RedisLiteral.ALPHA);
            }

            if (!string.IsNullOrEmpty(storeKey))
            {
                items.Add(RedisLiteral.STORE);
                items.Add(storeKey);
            }
            return(RedisMessage.Create(db, RedisLiteral.SORT, items.ToArray()));
        }
Пример #16
0
            internal override IEnumerable <RedisMessage> CreateMessages()
            {
                yield return(RedisMessage.Create(db, RedisLiteral.WATCH, key));

                var msgResult = new MessageResultBoolean(this);

                // we want this ExecuteSynchronously so that we can exploit the ordered nature of the reader to check all the
                // results efficiently
                msgResult.Task.ContinueWith(testExisted, TaskContinuationOptions.ExecuteSynchronously);
                var message = hashField == null?RedisMessage.Create(db, RedisLiteral.EXISTS, key)
                                  : RedisMessage.Create(db, RedisLiteral.HEXISTS, key, hashField);

                message.SetMessageResult(msgResult);
                yield return(message);
            }
        private void Outgoing()
        {
            try
            {
                OnOpened();
                int          db = 0;
                RedisMessage next;
                Trace.WriteLine("Redis send-pump is starting");
                bool isHigh, shouldFlush;
                while (unsent.TryDequeue(false, out next, out isHigh, out shouldFlush))
                {
                    if (abort)
                    {
                        CompleteMessage(next, RedisResult.Error("The system aborted before this message was sent"));
                        continue;
                    }
                    if (!next.ChangeState(MessageState.NotSent, MessageState.Sent))
                    {
                        // already cancelled; not our problem any more...
                        Interlocked.Increment(ref messagesCancelled);
                        continue;
                    }
                    if (isHigh)
                    {
                        Interlocked.Increment(ref queueJumpers);
                    }
                    WriteMessage(ref db, next, null);
                    Flush(shouldFlush);
                }
                Interlocked.CompareExchange(ref state, (int)ConnectionState.Closing, (int)ConnectionState.Open);
                if (redisStream != null)
                {
                    RedisMessage quit = RedisMessage.Create(-1, RedisLiteral.QUIT).ExpectOk().Critical();

                    RecordSent(quit, !abort);
                    quit.Write(outBuffer);
                    outBuffer.Flush();
                    redisStream.Flush();
                    Interlocked.Increment(ref messagesSent);
                }
                Trace.WriteLine("Redis send-pump is exiting");
            }
            catch (Exception ex)
            {
                OnError("Outgoing queue", ex, true);
            }
        }
Пример #18
0
        internal override object ProcessReply(ref RedisResult result, RedisMessage message)
        {
            byte[] expected;
            if (!result.IsError && (expected = message.Expected) != null)
            {
                result = result.IsMatch(expected)
                             ? RedisResult.Pass
                             : RedisResult.Error(result.ValueString);
            }


            if (result.IsError && message.MustSucceed)
            {
                throw new RedisException("A critical operation failed: " + message);
            }
            return(message);
        }
Пример #19
0
        Task <long> IncrementImpl(int db, string key, long value, bool queueJump)
        {
            switch (value)
            {
            case 1:
                return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.INCR, key), queueJump));

            case -1:
                return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.DECR, key), queueJump));
            }
            if (value >= 0)
            {
                return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.INCRBY, key, value), queueJump));
            }
            else
            {
                return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.DECRBY, key, -value), queueJump));
            }
        }
        Task <KeyValuePair <byte[], double>[]> ISortedSetCommands.Range(int db, string key, double min, double max,
                                                                        bool ascending, bool minInclusive,
                                                                        bool maxInclusive, long offset, long count,
                                                                        bool queueJump)
        {
            RedisMessage msg;

            if (minInclusive && maxInclusive && double.IsNegativeInfinity(min) && double.IsPositiveInfinity(max) &&
                offset >= 0 && count != 0)
            {
                // considering entire set; can be done more efficiently with ZRANGE/ZREVRANGE
                msg = RedisMessage.Create(db, ascending ? RedisLiteral.ZRANGE : RedisLiteral.ZREVRANGE, key, offset,
                                          (count < 0 || count == long.MaxValue) ? -1 : (offset + count - 1),
                                          RedisLiteral.WITHSCORES);
            }
            else if (offset == 0 && (count < 0 || count == long.MaxValue))
            {
                // no need for a LIMIT
                msg = RedisMessage.Create(db, ascending ? RedisLiteral.ZRANGEBYSCORE : RedisLiteral.ZREVRANGEBYSCORE,
                                          key,
                                          ascending
                                              ? RedisMessage.RedisParameter.Range(min, minInclusive)
                                              : RedisMessage.RedisParameter.Range(max, maxInclusive),
                                          ascending
                                              ? RedisMessage.RedisParameter.Range(max, maxInclusive)
                                              : RedisMessage.RedisParameter.Range(min, minInclusive),
                                          RedisLiteral.WITHSCORES);
            }
            else
            {
                msg = RedisMessage.Create(db, ascending ? RedisLiteral.ZRANGEBYSCORE : RedisLiteral.ZREVRANGEBYSCORE,
                                          key,
                                          ascending
                                              ? RedisMessage.RedisParameter.Range(min, minInclusive)
                                              : RedisMessage.RedisParameter.Range(max, maxInclusive),
                                          ascending
                                              ? RedisMessage.RedisParameter.Range(max, maxInclusive)
                                              : RedisMessage.RedisParameter.Range(min, minInclusive),
                                          RedisLiteral.WITHSCORES, RedisLiteral.LIMIT, offset,
                                          (count < 0 || count == long.MaxValue) ? -1 : count);
            }
            return(ExecutePairs(msg, queueJump));
        }
Пример #21
0
        internal virtual Task Prepare(string[] scripts)
        {
            if (scripts == null)
            {
                throw new ArgumentNullException();
            }
            var seenHashes = new HashSet <string>();
            List <Tuple <string, string> > fetch = new List <Tuple <string, string> >(scripts.Length);

            for (int i = 0; i < scripts.Length; i++)
            {
                string script = scripts[i];
                if (!scriptCache.ContainsKey(script))
                {
                    string hash = ComputeHash(script);
                    seenHashes.Add(hash);
                    fetch.Add(Tuple.Create(hash, script));
                }
            }
            if (fetch.Count == 0)
            {
                // no point checking, since we'd still be at the mercy of ad-hoc SCRIPT FLUSH timing
                return(AlwaysTrue);
            }

            RedisMessage.RedisParameter[] args = new RedisMessage.RedisParameter[1 + fetch.Count];
            args[0] = RedisLiteral.EXISTS;
            int idx = 1;

            foreach (var pair in fetch)
            {
                args[idx++] = pair.Item1; // hash
            }

            TaskCompletionSource <bool> result = new TaskCompletionSource <bool>();

            var state = Tuple.Create(result, this, fetch);

            ExecuteRaw(RedisMessage.Create(-1, RedisLiteral.SCRIPT, args), false, state).ContinueWith(scriptCompletionCallback);

            return(result.Task);
        }
Пример #22
0
        internal virtual string GetScriptHash(string script)
        {
            var hash = (string)scriptCache[script];

            if (hash == null)
            {   // double-checked
                lock (scriptCache)
                {
                    hash = (string)scriptCache[script];
                    if (hash == null)
                    {
                        // compute the hash and ensure it is loaded
                        hash = ComputeHash(script);
                        ExecuteVoid(RedisMessage.Create(-1, RedisLiteral.SCRIPT, RedisLiteral.LOAD, script), queueJump: true);
                        scriptCache[script] = hash;
                    }
                }
            }
            return(hash);
        }
Пример #23
0
        private Task <long> BitOp(int db, RedisLiteral operation, string destination, string[] keys, bool queueJump)
        {
            if (keys == null)
            {
                throw new ArgumentNullException("keys");
            }
            if (keys.Length == 0)
            {
                throw new ArgumentException("keys");
            }
            var args = new RedisMessage.RedisParameter[keys.Length + 2];

            args[0] = operation;
            args[1] = destination;
            for (int i = 0; i < keys.Length; i++)
            {
                args[i + 2] = keys[i];
            }
            return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.BITOP, args), queueJump));
        }
Пример #24
0
            Task <RedisResult> ReadNext(long cursor, bool running)
            {
                if (cursor == 0 && running)
                {
                    return(null);                        // end of the line
                }
                var          pending = new TaskCompletionSource <RedisResult>();
                RedisMessage msg;

                if (key == null)
                {
                    msg = (string.IsNullOrEmpty(pattern) || pattern == "*") ? RedisMessage.Create(db, command, cursor, RedisLiteral.COUNT, 100)
                        : RedisMessage.Create(db, command, cursor, RedisLiteral.MATCH, pattern, RedisLiteral.COUNT, 100);
                }
                else
                {
                    msg = (string.IsNullOrEmpty(pattern) || pattern == "*") ? RedisMessage.Create(db, command, key, cursor, RedisLiteral.COUNT, 100)
                        : RedisMessage.Create(db, command, key, cursor, RedisLiteral.MATCH, pattern, RedisLiteral.COUNT, 100);
                }
                connection.ExecuteRaw(msg, false, pending).ContinueWith(scanContinuation);
                return(pending.Task);
            }
Пример #25
0
        Task <ClientInfo[]> IServerCommands.ListClients()
        {
            CheckAdmin();
            var result = new TaskCompletionSource <ClientInfo[]>();

            ExecuteString(RedisMessage.Create(-1, RedisLiteral.CLIENT, RedisLiteral.LIST), false).ContinueWith(
                task =>
            {
                if (Condition.ShouldSetResult(task, result))
                {
                    try
                    {
                        result.TrySetResult(ClientInfo.Parse(task.Result));
                    }
                    catch (Exception ex)
                    {
                        result.TrySetException(ex);
                    }
                }
            });
            return(result.Task);
        }
Пример #26
0
        Task <object> IScriptingCommands.Eval(int db, string script, string[] keyArgs, object[] valueArgs, bool useCache,
                                              bool inferStrings, bool queueJump)
        {
            if (string.IsNullOrEmpty(script))
            {
                throw new ArgumentNullException("script");
            }
            var args =
                new RedisMessage.RedisParameter[
                    2 + (keyArgs == null ? 0 : keyArgs.Length) + (valueArgs == null ? 0 : valueArgs.Length)];

            args[1] = keyArgs == null ? 0 : keyArgs.Length;
            int idx = 2;

            if (keyArgs != null)
            {
                for (int i = 0; i < keyArgs.Length; i++)
                {
                    args[idx++] = keyArgs[i];
                }
            }
            if (valueArgs != null)
            {
                for (int i = 0; i < valueArgs.Length; i++)
                {
                    args[idx++] = RedisMessage.RedisParameter.Create(valueArgs[i]);
                }
            }
            if (!useCache)
            {
                args[0] = script;
                return(ExecuteScript(RedisMessage.Create(db, RedisLiteral.EVAL, args), inferStrings, queueJump));
            }

            // note this does a SCRIPT LOAD if it is the first time it is seen on this connection
            args[0] = GetScriptHash(script);
            return(ExecuteScript(RedisMessage.Create(db, RedisLiteral.EVALSHA, args), inferStrings, queueJump));
        }
Пример #27
0
        Task <bool> IStringCommands.TakeLock(int db, string key, string value, int expirySeconds, bool queueJump)
        {
            TaskCompletionSource <bool> result = new TaskCompletionSource <bool>();

            var features = Features;

            if (features != null && features.SetConditional)
            {
                var raw = ExecuteRaw(RedisMessage.Create(db, RedisLiteral.SET, key, value,
                                                         RedisLiteral.EX, expirySeconds, RedisLiteral.NX), queueJump, result);
                raw.ContinueWith(takeLockConditionalContinuation);
            }
            else
            {
                using (var tran = CreateTransaction())
                {
                    tran.AddCondition(Condition.KeyNotExists(db, key));
                    tran.Strings.Set(db, key, value, expirySeconds);
                    tran.Execute(queueJump, state: result).ContinueWith(takeLockContinuation);
                }
            }
            return(result.Task);
        }
Пример #28
0
 Task <long> IKeyCommands.GetLength(int db, bool queueJump)
 {
     return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.DBSIZE), queueJump));
 }
Пример #29
0
 Task <string> IKeyCommands.Type(int db, string key, bool queueJump)
 {
     return(ExecuteString(RedisMessage.Create(db, RedisLiteral.TYPE, key), queueJump));
 }
Пример #30
0
 public Task <long> TimeToLive(int db, string key, bool queueJump = false)
 {
     return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.TTL, key), queueJump));
 }
Пример #31
0
 public Task <bool> RenameIfNotExists(int db, string fromKey, string toKey, bool queueJump = false)
 {
     return(ExecuteBoolean(RedisMessage.Create(db, RedisLiteral.RENAMENX, fromKey, toKey), queueJump));
 }
Пример #32
0
 public Task Rename(int db, string fromKey, string toKey, bool queueJump = false)
 {
     return(ExecuteVoid(RedisMessage.Create(db, RedisLiteral.RENAME, fromKey, toKey).ExpectOk(), queueJump));
 }
 internal override object ProcessReply(ref RedisResult result, RedisMessage message)
 {
     return null;
 }
Пример #34
0
        internal override object ProcessReply(ref RedisResult result, RedisMessage message)
        {
            byte[] expected;
            if (!result.IsError && (expected = message.Expected) != null)
            {
                result = result.IsMatch(expected)
                ? RedisResult.Pass : RedisResult.Error(result.ValueString);
            }

            if (result.IsError && message.MustSucceed)
            {
                throw new RedisException("A critical operation failed: " + message.ToString());
            }
            return message;
        }
 internal Task<object> ExecuteScript(RedisMessage message, bool inferStrings, bool queueJump)
 {
     var msgResult = new MessageResultScript(this, inferStrings);
     message.SetMessageResult(msgResult);
     EnqueueMessage(message, queueJump);
     return msgResult.Task;
 }
Пример #36
0
 public MultiMessage(RedisConnection parent, RedisMessage[] messages)
     : base(-1, RedisLiteral.MULTI)
 {
     exec = new ExecMessage(parent);
     this.messages = messages;
     ExpectOk();
 }
Пример #37
0
        void IMessageResult.Complete(RedisResult result, RedisMessage message, bool includeDetail)
        {
            if (result.IsCancellation)
            {
                RedisConnectionBase.Trace("transaction", "cancelled");
                SetInnerReplies(result);
                completion.TrySetCanceled();
            }
            else if (result.IsError)
            {
                RedisConnectionBase.Trace("transaction", "error");
                SetInnerReplies(result);
                completion.SafeSetException(result.Error());
            }
            else
            {
                try
                {
                    if (result.IsNil)
                    {   // aborted
                        RedisConnectionBase.Trace("transaction", "aborted");
                        SetInnerReplies(RedisResult.Cancelled);
                        completion.TrySetResult(false);
                    }
                    else
                    {
                        var items = result.ValueItems;
                        if (items.Length != (queued == null ? 0 : queued.Length))
                            throw new InvalidOperationException(string.Format("{0} results expected, {1} received", queued.Length, items.Length));

                        RedisConnectionBase.Trace("transaction", "success");
                        for (int i = 0; i < items.Length; i++)
                        {
                            RedisResult reply = items[i];
                            RedisConnectionBase.CallbackMode callbackMode;
                            var ctx = parent.ProcessReply(ref reply, queued[i].InnerMessage, out callbackMode);
                            RedisConnectionBase.Trace("transaction", "{0} = {1}", ctx, reply);
                            parent.ProcessCallbacks(ctx, reply, callbackMode);
                        }
                        completion.TrySetResult(true);
                    }
                }
                catch (Exception ex)
                {
                    completion.SafeSetException(ex);
                    throw;
                }
            }
        }
Пример #38
0
 public MultiMessage(RedisConnection parent, RedisMessage[] messages, List<Condition> conditions, object state)
     : base(-1, RedisLiteral.MULTI)
 {
     exec = new ExecMessage(parent, state);
     this.conditions = conditions;
     this.messages = messages;
     ExpectOk().Critical();
 }
Пример #39
0
 public QueuedMessage(RedisMessage innnerMessage)
     : base(innnerMessage.Db, innnerMessage.Command)
 {
     if (innnerMessage == null) throw new ArgumentNullException("innnerMessage");
     this.innnerMessage = innnerMessage;
     Expect(RedisLiteral.QUEUED).Critical();
 }
Пример #40
0
 public void Abort(RedisMessage[] messages)
 {
     if (messages != null)
     {
         for (int i = 0; i < messages.Length; i++)
         {
             var reply = RedisResult.Cancelled;
             RedisConnectionBase.CallbackMode callbackMode;
             var ctx = parent.ProcessReply(ref reply, messages[i], out callbackMode);
             RedisConnectionBase.Trace("transaction", "{0} = {1}", ctx, reply);
             parent.ProcessCallbacks(ctx, reply, callbackMode);
         }
     }
 }
Пример #41
0
        public bool TryDequeue(bool noWait, out RedisMessage value, out bool isHigh, out bool shouldFlush)
        {
            lock (stdPriority)
            {
                int timeoutMilliseconds = this.keepAliveMilliseconds;
                while (highPriority.Count == 0 && stdPriority.Count == 0 && timeoutMilliseconds > 0)
                {
                    if (closed || noWait)
                    {
                        value = null;
                        isHigh = false;
                        shouldFlush = true;
                        return false;
                    }
                    if (timeoutMilliseconds == int.MaxValue)
                    {
                        Monitor.Wait(stdPriority);
                    }
                    else
                    {
                        var watch = Stopwatch.StartNew();
                        Monitor.Wait(stdPriority, timeoutMilliseconds);
                        watch.Stop();
                        timeoutMilliseconds -= (int) watch.ElapsedMilliseconds;
                    }
                }

                int loCount = stdPriority.Count, hiCount = highPriority.Count;
                isHigh = hiCount > 0;
                if (isHigh)
                {
                    value = highPriority.Dequeue();
                    hiCount--;
                    shouldFlush = hiCount == 0;
                }
                else if(loCount > 0)
                {
                    value = stdPriority.Dequeue();
                    loCount--;
                    shouldFlush = loCount == 0;
                } else
                { // nothing there! it must have been a KeepAlive timeout then
                    shouldFlush = true; // want this sent NOW
                    value = new PingMessage();
                }

                if ((!isHigh && loCount == maxSize - 1) || (loCount == 0 && hiCount == 0))
                {
                    // wake up any blocked enqueue
                    Monitor.PulseAll(stdPriority);
                }
                if (isHigh && loCount == 0) isHigh = false;//can't be high if it didn't overtake
                return true;
            }
        }
Пример #42
0
        internal override void RecordSent(RedisMessage message, bool drainFirst)
        {
            base.RecordSent(message, drainFirst);

            lock (sent)
            {
                if (drainFirst && sent.Count != 0)
                {
                    // drain it down; the dequeuer will wake us
                    Monitor.Wait(sent);
                }
                sent.Enqueue(message);
            }
        }
Пример #43
0
 public BatchMessage(RedisMessage[] messages)
     : base(-1, RedisLiteral.PING)
 {
     if (messages == null) throw new ArgumentNullException("messages");
     this.messages = messages;
 }