/// <summary>
        /// Computes the hash-slot that would be used by the given key
        /// </summary>
        public unsafe int HashSlot(RedisKey key)
        {
            //HASH_SLOT = CRC16(key) mod 16384
            if (key.IsNull) return NoSlot;
            unchecked
            {
                var blob = (byte[])key;
                fixed (byte* ptr = blob)
                {
                    int offset = 0, count = blob.Length, start, end;
                    if ((start = IndexOf(ptr, (byte)'{', 0, count - 1)) >= 0
                        && (end = IndexOf(ptr, (byte)'}', start + 1, count)) >= 0
                        && --end != start)
                    {
                        offset = start + 1;
                        count = end - start; // note we already subtracted one via --end
                    }

                    uint crc = 0;
                    for (int i = 0; i < count; i++)
                        crc = ((crc << 8) ^ crc16tab[((crc >> 8) ^ ptr[offset++]) & 0x00FF]) & 0x0000FFFF;
                    return (int)(crc % RedisClusterSlotCount);
                }
            }
        }
        public object Eval(string script, string[] keyArgs, object[] valueArgs)
        {
            RedisKey[] redisKeyArgs = new RedisKey[keyArgs.Length];
            RedisValue[] redisValueArgs = new RedisValue[valueArgs.Length];

            int i = 0;
            foreach (string key in keyArgs)
            {
                redisKeyArgs[i] = key;
                i++;
            }

            i = 0;
            foreach (object val in valueArgs)
            {
                if (val.GetType() == typeof(byte[]))
                {
                    // User data is always in bytes
                    redisValueArgs[i] = (byte[])val;
                }
                else
                {
                    // Internal data like session timeout and indexes are stored as strings
                    redisValueArgs[i] = val.ToString();
                }
                i++;
            }
            return RetryLogic(() => _connection.ScriptEvaluate(script, redisKeyArgs, redisValueArgs));
        }
示例#3
0
        /// <summary>
        ///     Creates a new <see cref="IDatabase"/> instance that provides an isolated key space
        ///     of the specified underyling database instance.
        /// </summary>
        /// <param name="database">
        ///     The underlying database instance that the returned instance shall use.
        /// </param>
        /// <param name="keyPrefix">
        ///     The prefix that defines a key space isolation for the returned database instance.
        /// </param>
        /// <returns>
        ///     A new <see cref="IDatabase"/> instance that invokes the specified underlying
        ///     <paramref name="database"/> but prepends the specified <paramref name="keyPrefix"/>
        ///     to all key paramters and thus forms a logical key space isolation.
        /// </returns>
        /// <remarks>
        /// <para>
        ///     The following methods are not supported in a key space isolated database and
        ///     will throw an <see cref="NotSupportedException"/> when invoked:
        /// </para>    
        /// <list type="bullet">
        ///     <item><see cref="IDatabaseAsync.KeyRandomAsync(CommandFlags)"/></item>
        ///     <item><see cref="IDatabase.KeyRandom(CommandFlags)"/></item>
        /// </list>
        /// <para>
        ///     Please notice that keys passed to a script are prefixed (as normal) but care must
        ///     be taken when a script returns the name of a key as that will (currently) not be
        ///     "unprefixed".
        /// </para>
        /// </remarks>
        public static IDatabase WithKeyPrefix(this IDatabase database, RedisKey keyPrefix)
        {
            if (database == null)
            {
                throw new ArgumentNullException("database");
            }

            if (keyPrefix.IsNull)
            {
                throw new ArgumentNullException("keyPrefix");
            }

            if (keyPrefix.IsEmpty)
            {
                return database; // fine - you can keep using the original, then
            }

            if(database is DatabaseWrapper)
            {
                // combine the key in advance to minimize indirection
                var wrapper = (DatabaseWrapper)database;
                keyPrefix = wrapper.ToInner(keyPrefix);
                database = wrapper.Inner;
            }

            return new DatabaseWrapper(database, keyPrefix.AsPrefix());
        }
 public RedisSchtickWrapper(Func<IDatabase> getRedisDb, string machineName = null, string keyPrefix = "schyntax")
 {
     _getRedisDb = getRedisDb;
     _keyPrefix = keyPrefix;
     _lastKey = keyPrefix + "_last";
     _machineName = machineName ?? Environment.MachineName;
 }
        public void CanHandleCommands()
        {
            RedisServiceFactory.Register<IRedisCommandHandler, TestCommandHandler>();
            TestCommandHandler cmdHandler = (TestCommandHandler)RedisServiceFactory.CommandHandlers.First();

            bool onExecutingDone = false;
            bool onExecutedDone = false;
            RedisKey[] testKeys = new RedisKey[] { "test" };
            RedisValue[] testValues = new RedisValue[] { "test value" };
            object testResult = (RedisValue)"hello world";

            cmdHandler.onExecuting = (command, involvedKeys, involvedValues) =>
            {
                Assert.AreEqual(RedisCommand.SET, command);
                Assert.AreEqual(1, testKeys.Intersect(involvedKeys).Count());
                Assert.AreEqual(1, testValues.Intersect(involvedValues).Count());
                onExecutingDone = true;
            };
            cmdHandler.onExecuted = (RedisCommand command, ref object result, RedisKey[] involvedKeys) =>
            {
                Assert.AreEqual(RedisCommand.HMSET, command);
                Assert.AreEqual(1, testKeys.Intersect(involvedKeys).Count());
                Assert.AreEqual(testResult, result);
                onExecutedDone = true;
            };

            RedisServiceFactory.CommandHandlers.ExecuteBeforeHandlers(RedisCommand.SET, new RedisKey[] { "test" }, new RedisValue[] { "test value" });
            RedisServiceFactory.CommandHandlers.ExecuteAfterHandlers(RedisCommand.HMSET, new RedisKey[] { "test" }, ref testResult);

            Assert.IsTrue(onExecutingDone);
            Assert.IsTrue(onExecutedDone);
        }
        public RedisLock([NotNull]IDatabase redis, [NotNull]RedisKey key, [NotNull]RedisValue owner, [NotNull]TimeSpan timeOut)
        {
            _redis = redis;
            _key = key;
            _owner = owner;

            //The comparison below uses timeOut as a max timeSpan in waiting Lock
            int i = 0;
            DateTime lockExpirationTime = DateTime.UtcNow +timeOut;
            while (DateTime.UtcNow < lockExpirationTime)
            {
                if (_redis.LockTake(key, owner, timeOut))
                    return;
                //assumes that a second call made by the same owner means an extension request
                var lockOwner = _redis.LockQuery(key);
                
                if (lockOwner.Equals(owner))
                {
                    //extends the lock only for the remaining time
                    var ttl = redis.KeyTimeToLive(key) ?? TimeSpan.Zero;
                    var extensionTTL = lockExpirationTime - DateTime.UtcNow;
                    if (extensionTTL > ttl)
                        _redis.LockExtend(key, owner, extensionTTL - ttl);
                    isRoot = false;
                    return;
                }
                SleepBackOffMultiplier(i);
                i++;
            }
            throw new TimeoutException(string.Format("Lock on {0} with owner identifier {1} Exceeded timeout of {2}", key, owner.ToString(), timeOut));
        }
示例#7
0
                /// <summary>
                /// Removes the specified fields from the hash stored at key. Non-existing fields are ignored. Non-existing keys
                /// are treated as empty hashes and this command returns 0.
                /// </summary>
                /// <param name="key">
                /// The key.
                /// </param>
                /// <param name="field">
                /// The field.
                /// </param>
                /// <remarks>
                /// http://redis.io/commands/hdel
                /// </remarks>
                /// <returns>
                /// The number of fields that were removed.
                /// </returns>
                public static bool Delete(RedisKey key, RedisValue field)
                {
                    bool result = SharedCache.Instance.GetWriteConnection(key)
                        .GetDatabase(SharedCache.Instance.Db)
                        .HashDelete(key, field);

                    return result;
                }
示例#8
0
                /// <summary>
                /// Removes the specified key. A key is ignored if it does not exist.
                /// </summary>
                /// <param name="key">
                /// The key.
                /// </param>
                /// <returns>
                /// True if the key was removed.
                /// </returns>
                /// <remarks>
                /// http://redis.io/commands/del
                /// </remarks>
                public static bool Delete(RedisKey key)
                {
                    bool result = SharedCache.Instance.GetWriteConnection(key)
                        .GetDatabase(SharedCache.Instance.Db)
                        .KeyDelete(key);

                    return result;
                }
示例#9
0
                /// <summary>
                /// Removes the specified key. A key is ignored if it does not exist.
                /// </summary>
                /// <param name="key">
                /// The key.
                /// </param>
                /// <returns>
                /// True if the key was removed.
                /// </returns>
                /// <remarks>
                /// http://redis.io/commands/del
                /// </remarks>
                public static Task<bool> DeleteAsync(RedisKey key)
                {
                    Task<bool> result = SharedCache.Instance.GetWriteConnection(key)
                        .GetDatabase(SharedCache.Instance.Db)
                        .KeyDeleteAsync(key);

                    return result;
                }
示例#10
0
                /// <summary>
                /// If key already exists and is a string, this command appends the value at the end of the string. If key does
                /// not exist it is created and set as an empty string, so APPEND will be similar to SET in this special case.
                /// </summary>
                /// <param name="key">
                /// The key.
                /// </param>
                /// <param name="value">
                /// The value.
                /// </param>
                /// <returns>
                /// the length of the string after the append operation.
                /// </returns>
                /// <remarks>
                /// http://redis.io/commands/append
                /// </remarks>
                public static Task<long> AppendAsync(RedisKey key, RedisValue value)
                {
                    Task<long> result = SharedCache.Instance.GetWriteConnection(key)
                        .GetDatabase(SharedCache.Instance.Db)
                        .StringAppendAsync(key, value);

                    return result;
                }
示例#11
0
 public bool Lock(RedisKey resource, TimeSpan ttl, out Lock lockObject)
 {
     var task = LockAsync(resource, ttl);
     task.Wait();
     var result = task.Result;
     lockObject = result.Item2;
     return result.Item1;
 }
                /// <summary>
                /// Returns the value associated with field in the hash stored at key.
                /// </summary>
                /// <returns>
                /// the value associated with field, or nil when field is not present in the hash or key does not exist.
                /// </returns>
                /// <remarks>http://redis.io/commands/hget</remarks>
                public static Task<RedisValue> GetString(RedisKey key, RedisValue field)
                {
                    Task<RedisValue> result = SharedCache.Instance.GetReadConnection(key)
                        .GetDatabase(SharedCache.Instance.Db)
                        .HashGetAsync(key, field);

                    return result;
                }
        public void CommandStart(RedisSettings usedSettings, string command, RedisKey key)
        {
            if (TimerStrategy == null) return;
            this.start = TimerStrategy.Start();

            this.usedSettings = usedSettings;
            this.command = command;
            this.key = key;
        }
 public async Task<IEnumerable<DeviceToken>> GetUserDeviceTokensAsync(IEnumerable<string> userIds)
 {
     var keys = new RedisKey[userIds.Count()];
     for (int i = 0; i < userIds.Count(); i++)
     {
         keys[i] = userIds.ElementAt(i);
     }
     var dtJsons = await pubsubRedis.GetDatabase().StringGetAsync(keys.ToArray(), CommandFlags.PreferSlave);
     return from item in dtJsons select JsonToDeviceToken(item);
 }
        internal static void SetUniqueVal(RedisKey hashKey, RedisValue hashField, RedisValue value, RedisKey indexKey)
        {
            var result = Store.Database.ScriptEvaluate(Script, new {hashKey, hashField, finalVal = value, indexKey});
            if ((bool)result)
            {
                return;
            }

            throw new UniqueConstraintViolatedException();
        }
        /// <summary>
        /// Executes all Redis command handlers, running behaviors that must run before some given command is about to get executed.
        /// </summary>
        /// <param name="handlers">The sequence of Redis command handlers</param>
        /// <param name="command">The Redis command</param>
        /// <param name="involvedKeys">An array of involved Redis keys in the command</param>
        /// <param name="involvedValues">An array of involved Redis values in the command</param>
        /// <returns>True if handlers could be executed. Otherwise, false.</returns>
        public static bool ExecuteBeforeHandlers(this IEnumerable<IRedisCommandHandler> handlers, RedisCommand command, RedisKey[] involvedKeys = null, RedisValue[] involvedValues = null)
        {
            bool canExecute = CanExecuteHandlers(handlers, command);

            if (canExecute)
                foreach (IRedisCommandHandler handler in handlers)
                    handler.OnExecuting(command, involvedKeys, involvedValues);

            return canExecute;
        }
        /// <summary>
        /// Executes all Redis command handlers, running behaviors that must run after some given command has been already executed.
        /// </summary>
        /// <typeparam name="TResult">The type of Redis command result</typeparam>
        /// <param name="handlers">The sequence of Redis command handlers</param>
        /// <param name="command">The Redis command</param>
        /// <param name="involvedKeys">An array of involved Redis keys in the command</param>
        /// <param name="result">The result of the Redis command execution</param>
        /// <returns>True if handlers could be executed. Otherwise, false.</returns>
        public static bool ExecuteAfterHandlers(this IEnumerable<IRedisCommandHandler> handlers, RedisCommand command, RedisKey[] involvedKeys, ref object result)
        {
            bool canExecute = CanExecuteHandlers(handlers, command);

            if (canExecute)
                foreach (IRedisCommandHandler handler in handlers)
                    handler.OnExecuted(command, ref result, involvedKeys);

            return canExecute;
        }
 public RedisTimelineMessage(RedisSettings usedSettings, string command, RedisKey key, object sentObject, long sentSize, object receivedObject, long receivedSize, bool isError)
 {
     UsedSettings = usedSettings;
     Command = command;
     Key = key;
     SentObject = sentObject;
     SentSize = sentSize;
     ReceivedObject = receivedObject;
     ReceivedSize = receivedSize;
     IsError = isError;
 }
 /// <summary>
 /// Removes the specified fields from the hash stored at key. Non-existing fields are ignored. Non-existing keys
 /// are treated as empty hashes and this command returns 0.
 /// </summary>
 /// <remarks>http://redis.io/commands/hdel</remarks>
 /// <returns>The number of fields that were removed.</returns>
 public static Task<long> Remove(RedisKey key, RedisValue[] fields)
 {
     var connections = SharedCache.Instance.GetWriteConnections(key);
     Task<long> result = null;
     foreach (var connection in connections)
     {
         var task = connection.GetDatabase(SharedCache.Instance.Db)
             .HashDeleteAsync(key, fields);
         if (null == result)
             result = task;
     }
     return result;
 }
示例#20
0
                /// <summary>
                /// Removes the specified keys. A key is ignored if it does not exist.
                /// </summary>
                /// <param name="keys">
                /// The keys.
                /// </param>
                /// <returns>
                /// The number of keys that were removed.
                /// </returns>
                /// <remarks>
                /// http://redis.io/commands/del
                /// </remarks>
                public static long Delete(RedisKey[] keys)
                {
                    var dictionary = SharedCache.Instance.GetWriteConnection(keys);
                    long removed = 0;
                    foreach (KeyValuePair<ConnectionMultiplexer, RedisKey[]> kvp in dictionary)
                    {
                        removed += kvp.Key
                            .GetDatabase(SharedCache.Instance.Db)
                            .KeyDelete(kvp.Value);
                    }

                    return removed;
                }
示例#21
0
        public Task ScriptEvaluateAsync(int database, string script, string key, byte[] messageArguments)
        {
            if (_connection == null)
            {
                throw new InvalidOperationException(Resources.Error_RedisConnectionNotStarted);
            }

            var keys = new RedisKey[] { key };

            var arguments = new RedisValue[] { messageArguments };

          return _connection.GetDatabase(database).ScriptEvaluateAsync(script, keys, arguments);
        }
 /// <summary>
 /// Returns if field is an existing field in the hash stored at key.
 /// </summary>
 /// <returns>
 /// 1 if the hash contains field. 0 if the hash does not contain field, or key does not exist.
 /// </returns>
 /// <remarks>http://redis.io/commands/hexists</remarks>
 public static Task<bool> Exists(RedisKey key, RedisValue field)
 {
     var connections = SharedCache.Instance.GetWriteConnections(key);
     Task<bool> result = null;
     foreach (var connection in connections)
     {
         var task = connection.GetDatabase(SharedCache.Instance.Db)
             .HashExistsAsync(key, field);
         if (null == result)
             result = task;
     }
     return result;
 }
		public static RedisLock AcquireLock(this IDatabase redis, RedisKey key, RedisValue value, TimeSpan timeout)
		{
			DateTime enterTime = DateTime.UtcNow;
			while (DateTime.UtcNow.Subtract(enterTime)<timeout)
			{
				//TODO: Should update the timeout on lock
				if (redis.LockTake(key, value, timeout))
				{
					return new RedisLock(redis, key, value);
				}
			}
			throw new Exception(String.Format("Unable to take the lock key={0} value={1} in {2}, key already exists ?", key, value, timeout));
			
		}
        internal static Task SetUniqueValAsync(RedisKey hashKey, RedisValue hashField, RedisValue value, RedisKey indexKey)
        {
            return Store.Database
                .ScriptEvaluateAsync(Script, new {hashKey, hashField, finalVal = value, indexKey})
                .ContinueWith(r =>
                {
                    if ((bool) r.Result)
                    {
                        return;
                    }

                    throw new UniqueConstraintViolatedException();
                });
        }
示例#25
0
        public bool Lock(RedisKey resource, TimeSpan ttl, out Lock lockObject)
        {
            var val = CreateUniqueLockId();
            Lock innerLock = null;
            bool successfull = retry(DefaultRetryCount, DefaultRetryDelay, () =>
            {
                try
                {
                    int n = 0;
                    var startTime = DateTime.Now;

                    // Use keys
                    for_each_redis_registered(
                        redis =>
                        {
                            if (LockInstance(redis, resource, val, ttl)) n += 1;
                        }
                    );

                    /*
                     * Add 2 milliseconds to the drift to account for Redis expires
                     * precision, which is 1 milliescond, plus 1 millisecond min drift
                     * for small TTLs.
                     */
                    var drift = Convert.ToInt32((ttl.TotalMilliseconds * ClockDriveFactor) + 2);
                    var validity_time = ttl - (DateTime.Now - startTime) - new TimeSpan(0, 0, 0, 0, drift);

                    if (n >= Quorum && validity_time.TotalMilliseconds > 0)
                    {
                        innerLock = new Lock(resource, val, validity_time);
                        return true;
                    }
                    else
                    {
                        for_each_redis_registered(
                            redis =>
                            {
                                UnlockInstance(redis, resource, val);
                            }
                        );
                        return false;
                    }
                }
                catch (Exception)
                { return false; }
            });

            lockObject = innerLock;
            return successfull;
        }
        public void NoErrorWhenNoHandlerIsConfigured()
        {
            RedisKey[] testKeys = new RedisKey[] { "test" };
            RedisValue[] testValues = new RedisValue[] { "test value" };
            object testResult = (RedisValue)"hello world";

            Assert.DoesNotThrow
            (
                () =>
                {
                    Assert.IsFalse(RedisServiceFactory.CommandHandlers.ExecuteBeforeHandlers(RedisCommand.SET, new RedisKey[] { "test" }, new RedisValue[] { "test value" }));
                    Assert.IsFalse(RedisServiceFactory.CommandHandlers.ExecuteAfterHandlers(RedisCommand.HMSET, new RedisKey[] { "test" }, ref testResult));
                }
            );
        }
        public RedisSettings Select(RedisSettings[] settings, RedisKey key)
        {
            if (settings.Length == 0) throw new ArgumentException("settings length is 0");
            if (settings.Length == 1) return settings[0];

            using (var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider())
            {
                var hashBytes = md5.ComputeHash((byte[])key);
                var preSeed = BitConverter.ToInt32(hashBytes, 0);
                if (preSeed == int.MinValue) preSeed++; // int.MinValue can't do Abs

                var seed = System.Math.Abs(preSeed);
                var index = seed % settings.Length;
                return settings[index];
            }
        }
示例#28
0
        public async Task<Tuple<bool, Lock>> LockAsync(RedisKey resource, TimeSpan ttl)
        {
            var val = CreateUniqueLockId();
            Lock lockObject = null;
            var successfull = await Retry(DefaultRetryCount, _defaultRetryDelay, async () =>
            {
                try
                {
                    var n = 0;
                    var startTime = DateTime.Now;

                    // Use keys
                    await for_each_redis_registered(
                        async connection =>
                        {
                            if (await LockInstance(connection, resource, val, ttl)) n += 1;
                        }
                    );

                    /*
                     * Add 2 milliseconds to the drift to account for Redis expires
                     * precision, which is 1 milliescond, plus 1 millisecond min drift 
                     * for small TTLs.        
                     */
                    var drift = Convert.ToInt32((ttl.TotalMilliseconds*ClockDriveFactor) + 2);
                    var validityTime = ttl - (DateTime.Now - startTime) - new TimeSpan(0, 0, 0, 0, drift);

                    if (n >= Quorum && validityTime.TotalMilliseconds > 0)
                    {
                        lockObject = new Lock(resource, val, validityTime);
                        return true;
                    }
                    await for_each_redis_registered(connection => UnlockInstance(connection, resource, val));
                    return false;
                }
                catch (Exception)
                {
                    return false;
                }
            });

            return Tuple.Create(successfull, lockObject);
        }
示例#29
0
 private static void TestConcurrent(IDatabase db, RedisKey key, int SyncLoop, int Threads)
 {
     long value;
     db.KeyDelete(key, CommandFlags.FireAndForget);
     var time = RunConcurrent(delegate
     {
         for (int i = 0; i < SyncLoop; i++)
         {
             db.StringIncrement(key);
         }
     }, Threads, timeout: 45000);
     value = (long)db.StringGet(key);
     Assert.AreEqual(SyncLoop * Threads, value);
     Console.WriteLine("Sync: {0} INCR using {1} threads, {2:###,##0}ms, {3} ops/s; final value: {4}",
         SyncLoop * Threads, Threads,
         (long)time.TotalMilliseconds,
         (long)((SyncLoop * Threads) / time.TotalSeconds),
         value);
 }
        /// <summary>
        ///     初始化数据库环境、实例化子类中,所有Set属性
        /// </summary>
        public void Initializer()
        {
            if (IsInitializer) { return; }
            _client = new RedisClient(_redisConnection);
            IsInitializer = true;

            Connection = new RedisConnection(_client);
            Hash = new RedisHash(_client);
            Key = new RedisKey(_client);
            List = new RedisList(_client);
            PubSub = new RedisPubSub(_client);
            Script = new RedisScript(_client);
            Server = new RedisServer(_client);
            Set = new RedisSet(_client);
            SortedSet = new RedisSortedSet(_client);
            String = new RedisString(_client);
            Transaction = new RedisTransaction(_client);
            Bit = new RedisBit(_client);
            Expire = new RedisExpire(_client);
            Sort = new RedisSort(_client);
            Number = new RedisNumber(_client);
        }
 public TimeSpan?KeyTimeToLive(RedisKey key, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.KeyTimeToLive(ToInner(key), flags));
 }
 public void ListSetByIndex(RedisKey key, long index, RedisValue value, CommandFlags flags = CommandFlags.None)
 {
     Inner.ListSetByIndex(ToInner(key), index, value, flags);
 }
 public long ListInsertBefore(RedisKey key, RedisValue pivot, RedisValue value, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListInsertBefore(ToInner(key), pivot, value, flags));
 }
 public long ListRemove(RedisKey key, RedisValue value, long count = 0, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListRemove(ToInner(key), value, count, flags));
 }
 public RedisValue ListRightPop(RedisKey key, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListRightPop(ToInner(key), flags));
 }
 public bool KeyRename(RedisKey key, RedisKey newKey, When when = When.Always, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.KeyRename(ToInner(key), ToInner(newKey), when, flags));
 }
 public long ListRightPush(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListRightPush(ToInner(key), values, flags));
 }
 public long SetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.SetCombineAndStore(operation, ToInner(destination), ToInner(keys), flags));
 }
 public long SetAdd(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.SetAdd(ToInner(key), values, flags));
 }
 public bool GeoAdd(RedisKey key, GeoEntry value, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.GeoAdd(ToInner(key), value, flags));
 }
 public bool LockTake(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.LockTake(ToInner(key), value, expiry, flags));
 }
 public bool LockRelease(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.LockRelease(ToInner(key), value, flags));
 }
 public RedisType KeyType(RedisKey key, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.KeyType(ToInner(key), flags));
 }
 public long GeoAdd(RedisKey key, GeoEntry[] values, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.GeoAdd(ToInner(key), values, flags));
 }
 public void KeyRestore(RedisKey key, byte[] value, TimeSpan?expiry = null, CommandFlags flags = CommandFlags.None)
 {
     Inner.KeyRestore(ToInner(key), value, expiry, flags);
 }
 public bool GeoAdd(RedisKey key, double longitude, double latitude, RedisValue member, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.GeoAdd(ToInner(key), longitude, latitude, member, flags));
 }
 public RedisValue ListRightPopLeftPush(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListRightPopLeftPush(ToInner(source), ToInner(destination), flags));
 }
 public bool GeoRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.GeoRemove(ToInner(key), member, flags));
 }
 public bool KeyPersist(RedisKey key, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.KeyPersist(ToInner(key), flags));
 }
 public bool SetContains(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.SetContains(ToInner(key), value, flags));
 }
 public bool KeyMove(RedisKey key, int database, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.KeyMove(ToInner(key), database, flags));
 }
 public long SetLength(RedisKey key, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.SetLength(ToInner(key), flags));
 }
 public RedisValue[] ListRange(RedisKey key, long start = 0, long stop = -1, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListRange(ToInner(key), start, stop, flags));
 }
 public RedisValue[] SetMembers(RedisKey key, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.SetMembers(ToInner(key), flags));
 }
 public long SetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.SetCombineAndStore(operation, ToInner(destination), ToInner(first), ToInner(second), flags));
 }
 public long ListRightPush(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListRightPush(ToInner(key), value, when, flags));
 }
 public RedisValue[] SetCombine(SetOperation operation, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.SetCombine(operation, ToInner(first), ToInner(second), flags));
 }
 public RedisValue ListGetByIndex(RedisKey key, long index, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.ListGetByIndex(ToInner(key), index, flags));
 }
 public void ListTrim(RedisKey key, long start, long stop, CommandFlags flags = CommandFlags.None)
 {
     Inner.ListTrim(ToInner(key), start, stop, flags);
 }
 public RedisValue LockQuery(RedisKey key, CommandFlags flags = CommandFlags.None)
 {
     return(Inner.LockQuery(ToInner(key), flags));
 }