geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From u..@apache.org
Subject [09/21] geode git commit: GEODE-2449: Moved Redis out of core with minimal Extension work added
Date Fri, 10 Feb 2017 21:34:12 GMT
http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisConstants.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisConstants.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisConstants.java
new file mode 100644
index 0000000..84dd44b
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisConstants.java
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal;
+
+
+public class RedisConstants {
+
+  public static final int NUM_DEFAULT_KEYS = 3;
+
+  /*
+   * Responses
+   */
+  public static final String QUIT_RESPONSE = "OK";
+  public static final String COMMAND_QUEUED = "QUEUED";
+
+
+  /*
+   * Error responses
+   */
+  static final String PARSING_EXCEPTION_MESSAGE =
+      "The command recieved by GeodeRedisServiceImpl was improperly formatted";
+  static final String SERVER_ERROR_MESSAGE = "The server had an internal error please try again";
+  static final String SERVER_ERROR_UNKNOWN_RESPONSE = "Unkown response";
+  static final String SERVER_ERROR_SHUTDOWN = "The server is shutting down";
+  static final String ERROR_UNSUPPORTED_OPERATION_IN_TRANSACTION =
+      "This command is not supported within a transaction";
+  static final String ERROR_TRANSACTION_EXCEPTION =
+      "This transcation cannot be initiated, make sure the command is executed against a replicate region or your data is collocated. If you are using persistent regions, make sure transactions are enabled";
+  public static final String ERROR_NOT_NUMERIC = "Illegal non numeric argument";
+  public static final String ERROR_UNKOWN_COMMAND = "Unable to process uknown command";
+  public static final String ERROR_COMMIT_CONFLICT =
+      "There has been a conflict with another transaction";
+  public static final String ERROR_REGION_CREATION =
+      "This key could not be created. Gemfire does not allow certain characters to used in keys";
+  public static final String ERROR_UNWATCH =
+      "Keys cannot be watched or unwatched because GemFire watches all keys by default for transactions";
+  public static final String ERROR_WATCH =
+      "Keys cannot be watched or unwatched because GemFire watches all keys by default for transactions";
+  public static final String ERROR_ILLEGAL_GLOB = "Incorrect syntax for given glob regex";
+  public static final String ERROR_OUT_OF_RANGE = "The number provided is out of range";
+  public static final String ERROR_NESTED_MULTI = "The MULTI command cannot be nested";
+  public static final String ERROR_NAN_INF_INCR = "increment would produce NaN or Infinity";
+  public static final String ERROR_NO_PASS =
+      "Attempting to authenticate when no password has been set";
+  public static final String ERROR_INVALID_PWD =
+      "Attemping to authenticate with an invalid password";
+  public static final String ERROR_NOT_AUTH = "Must authenticate before sending any requests";
+
+  public static class ArityDef {
+
+    /*
+     * General
+     */
+    public static final int DBSIZE_ARITY = 0;
+    public static final String AUTH =
+        "The wrong number of arguments or syntax was provided, the format for the AUTH command is \"AUTH password\"";
+    public static final String DBSIZE = null;
+    public static final String DEL =
+        "The wrong number of arguments or syntax was provided, the format for the DEL command is \"DEL key [key ...]\"";
+    public static final String ECHO =
+        "The wrong number of arguments or syntax was provided, the format for the ECHO command is \"ECHO message\"";
+    public static final String EXISTS =
+        "The wrong number of arguments or syntax was provided, the format for the EXISTS command is \"EXISTS key\"";
+    public static final String EXPIREAT =
+        "The wrong number of arguments or syntax was provided, the format for the EXPIREAT command is \"EXPIREAT key timestamp\"";
+    public static final String EXPIRE =
+        "The wrong number of arguments or syntax was provided, the format for the EXPIRE command is \"EXPIRE key seconds\"";
+    public static final String FLUSHALL = null;
+    public static final String KEYS =
+        "The wrong number of arguments or syntax was provided, the format for the KEYS command is \"KEYS pattern\"";
+    public static final String PERSIST =
+        "The wrong number of arguments or syntax was provided, the format for the PERSIST command is \"PERSIST key\"";
+    public static final String PEXPIREAT =
+        "The wrong number of arguments or syntax was provided, the format for the PEXPIREAT command is \"PEXPIREAT key milliseconds-timestamp\"";
+    public static final String PEXPIRE =
+        "The wrong number of arguments or syntax was provided, the format for the PEXPIRE command is \"PEXPIRE key milliseconds\"";
+    public static final String PING = null;
+    public static final String PTTL =
+        "The wrong number of arguments or syntax was provided, the format for the PTTL command is \"PTTL key\"";
+    public static final String QUIT = null;
+    public static final String SCAN =
+        "The wrong number of arguments or syntax was provided, the format for the SCAN command is \"SCAN cursor [MATCH pattern] [COUNT count]\"";
+    public static final String SHUTDOWN = null;
+    public static final String TIME = null;
+    public static final String TTL =
+        "The wrong number of arguments or syntax was provided, the format for the TTL command is \"TTL key\"";
+    public static final String TYPE =
+        "The wrong number of arguments or syntax was provided, the format for the TYPE command is \"TYPE key\"";
+    public static final String UNKNOWN = null;
+
+    /*
+     * Hash
+     */
+    public static final String HDEL =
+        "The wrong number of arguments or syntax was provided, the format for the HDEL command is \"HDEL key field [field ...]\"";
+    public static final String HEXISTS =
+        "The wrong number of arguments or syntax was provided, the format for the HEXISTS command is \"HEXISTS key field\"";
+    public static final String HGETALL =
+        "The wrong number of arguments or syntax was provided, the format for the HGETALL command is \"HGETALL key\"";
+    public static final String HGET =
+        "The wrong number of arguments or syntax was provided, the format for the HGET command is \"HGET key field\"";
+    public static final String HINCRBY =
+        "The wrong number of arguments or syntax was provided, the format for the HINCRBY command is \"HINCRBY key field increment\"";
+    public static final String HINCRBYFLOAT =
+        "The wrong number of arguments or syntax was provided, the format for the HINCRBYFLOAT command is \"HINCRBYFLOAT key field increment\"";
+    public static final String HKEYS =
+        "The wrong number of arguments or syntax was provided, the format for the HKEYS command is \"HKEYS key\"";
+    public static final String HLEN =
+        "The wrong number of arguments or syntax was provided, the format for the HLEN command is \"HLEN key\"";
+    public static final String HMGET =
+        "The wrong number of arguments or syntax was provided, the format for the HMGET command is \"HMGET key field [field ...]\"";
+    public static final String HMSET =
+        "The wrong number of arguments or syntax was provided, the format for the HMSET command is \"HMSET key field value [field value ...]\", or not every field is associated with a value";
+    public static final String HSCAN =
+        "The wrong number of arguments or syntax was provided, the format for the SSCAN command is \"SSCAN key cursor [MATCH pattern] [COUNT count]\"";
+    public static final String HSET =
+        "The wrong number of arguments or syntax was provided, the format for the HSET command is \"HSET key field value\"";
+    public static final String HSETNX =
+        "The wrong number of arguments or syntax was provided, the format for the HSETNX command is \"HSETNX key field value\"";
+    public static final String HVALS =
+        "The wrong number of arguments or syntax was provided, the format for the HVALS command is \"HVALS key\"";
+
+    /*
+     * Hll
+     */
+    public static final String PFADD =
+        "The wrong number of arguments or syntax was provided, the format for the PFADD command is \"PFADD key element [element ...]\"";
+    public static final String PFCOUNT =
+        "The wrong number of arguments or syntax was provided, the format for the PFCOUNT command is \"PFCOUNT key [key ...]\"";
+    public static final String PFMERGE =
+        "The wrong number of arguments or syntax was provided, the format for the PFMERGE command is \"PFMERGE destkey sourcekey [sourcekey ...]\"";
+
+    /*
+     * List
+     */
+    public static final String LINDEX =
+        "The wrong number of arguments or syntax was provided, the format for the LINDEX command is \"LINDEX key index";
+    public static final String LINSERT = null;
+    public static final String LLEN =
+        "The wrong number of arguments or syntax was provided, the format for the LLEN command is \"LLEN key";
+    public static final String LPOP =
+        "The wrong number of arguments or syntax was provided, the format for the LPOP command is \"LPOP key";
+    public static final String LPUSH =
+        "The wrong number of arguments or syntax was provided, the format for the LPUSH command is \"LPUSH key value [value ...]";
+    public static final String LPUSHX =
+        "The wrong number of arguments or syntax was provided, the format for the LPUSHX command is \"LPUSHX key value";
+    public static final String LRANGE =
+        "The wrong number of arguments or syntax was provided, the format for the LRANGE command is \"LRANGE key start stop\"";
+    public static final String LREM =
+        "The wrong number of arguments or syntax was provided, the format for the LREM command is \"LREM key count value\"";
+    public static final String LSET =
+        "The wrong number of arguments or syntax was provided, the format for the LSET command is \"LSET key index value\"";
+    public static final String LTRIM =
+        "The wrong number of arguments or syntax was provided, the format for the LTRIM command is \"LTRIM key start stop\"";
+    public static final String RPOP =
+        "The wrong number of arguments or syntax was provided, the format for the RPOP command is \"RPOP key";
+    public static final String RPUSH =
+        "The wrong number of arguments or syntax was provided, the format for the RPUSH command is \"RPUSH key value [value ...]";
+    public static final String RPUSHX =
+        "The wrong number of arguments or syntax was provided, the format for the RPUSHX command is \"RPUSHX key value";
+
+    /*
+     * Set
+     */
+    public static final String SADD =
+        "The wrong number of arguments or syntax was provided, the format for the SADD command is \"SADD key member [member ...]\"";
+    public static final String SCARD =
+        "The wrong number of arguments or syntax was provided, the format for the SCARD command is \"SCARD key\"";
+    public static final String SDIFF =
+        "The wrong number of arguments or syntax was provided, the format for the SDIFF command is \"SDIFF key [key ...]\"";
+    public static final String SDIFFSTORE =
+        "The wrong number of arguments or syntax was provided, the format for the SDIFF command is \"SDIFFSTORE destination key [key ...]\"";
+    public static final String SINTER =
+        "The wrong number of arguments or syntax was provided, the format for the SINTER command is \"SINTER key [key ...]\"";
+    public static final String SINTERSTORE =
+        "The wrong number of arguments or syntax was provided, the format for the SINTERSTORE command is \"SINTERSTORE destination key [key ...]\"";
+    public static final String SISMEMBER =
+        "The wrong number of arguments or syntax was provided, the format for the SISMEMBER command is \"SISMEMBER key member\"";
+    public static final String SMEMBERS =
+        "The wrong number of arguments or syntax was provided, the format for the SMEMBERS command is \"SMEMBERS key\"";
+    public static final String SMOVE =
+        "The wrong number of arguments or syntax was provided, the format for the SMOVE command is \"SMOVE source destination member\"";
+    public static final String SPOP =
+        "The wrong number of arguments or syntax was provided, the format for the SPOP command is \"SPOP key\"";
+    public static final String SRANDMEMBER =
+        "The wrong number of arguments or syntax was provided, the format for the SRANDMEMBER command is \"SRANDMEMBER key [count]\"";
+    public static final String SREM =
+        "The wrong number of arguments or syntax was provided, the format for the SREM command is \"SREM key member [member ...]\"";
+    public static final String SSCAN =
+        "The wrong number of arguments or syntax was provided, the format for the SSCAN command is \"SSCAN key cursor [MATCH pattern] [COUNT count]\"";
+    public static final String SUNION =
+        "The wrong number of arguments or syntax was provided, the format for the SUNION command is \"SUNION key [key ...]\"";
+    public static final String SUNIONSTORE =
+        "The wrong number of arguments or syntax was provided, the format for the SUNIONSTORE command is \"SUNIONSTORE destination key [key ...]\"";
+
+    /*
+     * Sorted set
+     */
+    public static final String ZADD =
+        "The wrong number of arguments or syntax was provided, the format for the ZADD command is \"ZADD key score member [score member ...]\", or not every score matches to a member";
+    public static final String ZCARD =
+        "The wrong number of arguments or syntax was provided, the format for the ZCARD command is \"ZCARD key\"";
+    public static final String ZCOUNT =
+        "The wrong number of arguments or syntax was provided, the format for the ZCOUNT command is \"ZCOUNT key min max\"";
+    public static final String ZINCRBY =
+        "The wrong number of arguments or syntax was provided, the format for the ZINCRBY command is \"ZINCRBY key increment member\"";
+    public static final String ZLEXCOUNT =
+        "The wrong number of arguments or syntax was provided, the format for the ZLEXCOUNT command is \"ZLEXCOUNT key min max\"";
+    public static final String ZRANGEBYLEX =
+        "The wrong number of arguments or syntax was provided, the format for the ZRANGEBYLEX command is \"ZRANGEBYLEX key min max [LIMIT offset count]\"";
+    public static final String ZRANGEBYSCORE =
+        "The wrong number of arguments or syntax was provided, the format for the ZRANGEBYSCORE command is \"ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]\"";
+    public static final String ZRANGE =
+        "The wrong number of arguments or syntax was provided, the format for the ZRANGE command is \"ZRANGE key start stop [WITHSCORES]\"";
+    public static final String ZRANK =
+        "The wrong number of arguments or syntax was provided, the format for the ZRANK command is \"ZRANK key member\"";
+    public static final String ZREM =
+        "The wrong number of arguments or syntax was provided, the format for the ZREM command is \"ZREM key member [member ...]\"";
+    public static final String ZREMRANGEBYLEX =
+        "The wrong number of arguments or syntax was provided, the format for the ZREMRANGEBYLEX command is \"ZREMRANGEBYLEX key min max\"";
+    public static final String ZREMRANGEBYRANK =
+        "The wrong number of arguments or syntax was provided, the format for the ZREMRANGEBYRANK command is \"ZREMRANGEBYRANK key start stop\"";
+    public static final String ZREMRANGEBYSCORE =
+        "The wrong number of arguments or syntax was provided, the format for the ZREMRANGEBYSCORE command is \"ZREMRANGEBYSCORE key min max\"";
+    public static final String ZREVRANGEBYSCORE =
+        "The wrong number of arguments or syntax was provided, the format for the ZREVRANGEBYSCORE command is \"ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]\"";
+    public static final String ZREVRANGE =
+        "The wrong number of arguments or syntax was provided, the format for the ZREVRANGE command is \"ZREVRANGE key start stop [WITHSCORES]\"";
+    public static final String ZREVRANK =
+        "The wrong number of arguments or syntax was provided, the format for the ZREVRANK command is \"ZREVRANK key member\"";
+    public static final String ZSCAN =
+        "The wrong number of arguments or syntax was provided, the format for the SSCAN command is \"SSCAN key cursor [MATCH pattern] [COUNT count]\"";
+    public static final String ZSCORE =
+        "The wrong number of arguments or syntax was provided, the format for the ZSCORE command is \"ZSCORE key member\"";
+
+    /*
+     * String
+     */
+    public static final String APPEND =
+        "The wrong number of arguments or syntax was provided, the format for the APPEND command is \"APPEND key value\"";
+    public static final String BITCOUNT =
+        "The wrong number of arguments or syntax was provided, the format for the BITCOUNT command is \"BITCOUNT key [start end]\"";
+    public static final String BITOP =
+        "The wrong number of arguments or syntax was provided, the format for the BITOP command is \"BITOP operation destkey key [key ...]\"";
+    public static final String BITPOS =
+        "The wrong number of arguments or syntax was provided, the format for the BITOPS command is \"BITPOS key bit [start] [end]\"";
+    public static final String DECRBY =
+        "The wrong number of arguments or syntax was provided, the format for the DECRBY command is \"DECRRBY key decrement\"";
+    public static final String DECR =
+        "The wrong number of arguments or syntax was provided, the format for the DECR command is \"DECR key\"";
+    public static final String GETBIT =
+        "The wrong number of arguments or syntax was provided, the format for the GETBIT command is \"GETBIT key offset\"";
+    public static final String GETEXECUTOR =
+        "The wrong number of arguments or syntax was provided, the format for the GET command is \"GET key\"";
+    public static final String GETRANGE =
+        "The wrong number of arguments or syntax was provided, the format for the GETRANGE command is \"GETRANGE key start end\"";
+    public static final String GETSET =
+        "The wrong number of arguments or syntax was provided, the format for the GETSET command is \"GETSET key value\"";
+    public static final String INCRBY =
+        "The wrong number of arguments or syntax was provided, the format for the INCRBY command is \"INCRBY key increment\"";
+    public static final String INCRBYFLOAT =
+        "The wrong number of arguments or syntax was provided, the format for the INCRBY command is \"INCRBY key increment\"";
+    public static final String INCR =
+        "The wrong number of arguments or syntax was provided, the format for the INCR command is \"INCR key\"";
+    public static final String MGET =
+        "The wrong number of arguments or syntax was provided, the format for the MGET command is \"MGET key [key ...]\"";
+    public static final String MSET =
+        "The wrong number of arguments or syntax was provided, the format for the MSET command is \"MSET key value [key value ...]\", or not every key matches a value";
+    public static final String MSETNX =
+        "The wrong number of arguments or syntax was provided, the format for the MSETNX command is \"MSETNX key value [key value ...]\", or not every key matches a value";
+    public static final String PSETEX =
+        "The wrong number of arguments or syntax was provided, the format for the PSETEX command is \"PSETEX key milliseconds value\"";
+    public static final String SETBIT =
+        "The wrong number of arguments or syntax was provided, the format for the SETBIT command is \"SETBIT key offset value\"";
+    public static final String SET =
+        "The wrong number of arguments or syntax was provided, the format for the SET command is \"SET key value [EX seconds] [PX milliseconds] [NX|XX]\"";
+    public static final String SETEX =
+        "The wrong number of arguments or syntax was provided, the format for the SETEX command is \"SETEX key seconds value\"";
+    public static final String SETNX =
+        "The wrong number of arguments or syntax was provided, the format for the SETNX command is \"SETNX key value\"";
+    public static final String SETRANGE =
+        "The wrong number of arguments or syntax was provided, the format for the SETRANGE command is \"SETRANGE key offset value\"";
+    public static final String STRLEN =
+        "The wrong number of arguments or syntax was provided, the format for the STRELEN command is \"STRLEN key\"";
+
+    /*
+     * Transaction
+     */
+    public static final String DISCARD = null;
+    public static final String EXEC = null;
+    public static final String MULTI = null;
+    public static final String UNWATCH = null;
+    public static final String WATCH = null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataType.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataType.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataType.java
new file mode 100644
index 0000000..9410642
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataType.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.redis.GeodeRedisServiceImpl;
+
+/**
+ * The RedisDataType enum contains the choices to which every {@link Region} on the server must be.
+ * There is only one instance of {@link #REDIS_STRING} and {@link #REDIS_PROTECTED} defined by
+ * {@link GeodeRedisServiceImpl#STRING_REGION} and
+ * {@link GeodeRedisServiceImpl#REDIS_META_DATA_REGION} respectively.
+ * <p>
+ * The data types are:
+ * <li>{@link RedisDataType#REDIS_STRING}</li>
+ * <li>{@link RedisDataType#REDIS_HASH}</li>
+ * <li>{@link RedisDataType#REDIS_LIST}</li>
+ * <li>{@link RedisDataType#REDIS_SET}</li>
+ * <li>{@link RedisDataType#REDIS_SORTEDSET}</li>
+ * <li>{@link RedisDataType#REDIS_PROTECTED}</li>
+ *
+ */
+public enum RedisDataType {
+  /**
+   * Strings Regions
+   */
+  REDIS_STRING {
+    @Override
+    public String toString() {
+      return "string";
+    }
+  },
+
+  /**
+   * Hashes Regions
+   */
+  REDIS_HASH {
+    @Override
+    public String toString() {
+      return "hash";
+    }
+  },
+
+  /**
+   * Lists Regions
+   */
+  REDIS_LIST {
+    @Override
+    public String toString() {
+      return "list";
+    }
+  },
+
+  /**
+   * Sets Regions
+   */
+  REDIS_SET {
+    @Override
+    public String toString() {
+      return "set";
+    }
+  },
+
+  /**
+   * SortedSets Regions
+   */
+  REDIS_SORTEDSET {
+    @Override
+    public String toString() {
+      return "zset";
+    }
+  },
+
+  /**
+   * HyperLogLog Regions
+   */
+  REDIS_HLL {
+    @Override
+    public String toString() {
+      return "hyperloglog";
+    }
+  },
+
+  /**
+   * Regions protected from overwrite or deletion
+   */
+  REDIS_PROTECTED {
+    @Override
+    public String toString() {
+      return "protected";
+    }
+  },
+
+  /**
+   * None
+   */
+  NONE {
+    @Override
+    public String toString() {
+      return "none";
+    }
+  };
+
+};

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataTypeMismatchException.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataTypeMismatchException.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataTypeMismatchException.java
new file mode 100644
index 0000000..727412b
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisDataTypeMismatchException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal;
+
+/**
+ * This exception is for the case that a client attempts to operate on a data structure of one
+ * {@link RedisDataType} with a command that is of another type
+ * 
+ *
+ */
+public class RedisDataTypeMismatchException extends RuntimeException {
+
+  private static final long serialVersionUID = -2451663685348513870L;
+
+  public RedisDataTypeMismatchException() {
+    super();
+  }
+
+  public RedisDataTypeMismatchException(String message) {
+    super(message);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionCreationException.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionCreationException.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionCreationException.java
new file mode 100644
index 0000000..afc009e
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionCreationException.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal;
+
+/**
+ * This exception is used when an error happens while creating a
+ * {@link org.apache.geode.cache.Region} globally
+ * 
+ *
+ */
+public class RegionCreationException extends RuntimeException {
+
+  public RegionCreationException() {}
+
+  public RegionCreationException(String err) {
+    super(err);
+  }
+
+  public RegionCreationException(String err, Throwable cause) {
+    super(err, cause);
+  }
+
+  private static final long serialVersionUID = 8416820139078312997L;
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionProvider.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionProvider.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionProvider.java
new file mode 100644
index 0000000..deacee0
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RegionProvider.java
@@ -0,0 +1,567 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheTransactionManager;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.TransactionId;
+import org.apache.geode.cache.query.IndexExistsException;
+import org.apache.geode.cache.query.IndexInvalidException;
+import org.apache.geode.cache.query.IndexNameConflictException;
+import org.apache.geode.cache.query.Query;
+import org.apache.geode.cache.query.QueryInvalidException;
+import org.apache.geode.cache.query.QueryService;
+import org.apache.geode.cache.query.RegionNotFoundException;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.cli.Result.Status;
+import org.apache.geode.management.internal.cli.commands.CreateAlterDestroyRegionCommands;
+import org.apache.geode.redis.GeodeRedisServiceImpl;
+import org.apache.geode.redis.internal.executor.ExpirationExecutor;
+import org.apache.geode.redis.internal.executor.ListQuery;
+import org.apache.geode.redis.internal.executor.SortedSetQuery;
+import org.apache.geode.redis.internal.hll.HyperLogLogPlus;
+
+import java.io.Closeable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * This class stands between {@link Executor} and {@link Cache#getRegion(String)}. This is needed
+ * because some keys for Redis represented as a {@link Region} in {@link GeodeRedisServiceImpl} come
+ * with additional state. Therefore getting, creating, or destroying a {@link Region} needs to be
+ * synchronized, which is done away with and abstracted by this class.
+ * 
+ *
+ */
+public class RegionProvider implements Closeable {
+
+  private final ConcurrentHashMap<ByteArrayWrapper, Region<?, ?>> regions;
+
+  /**
+   * This is the Redis meta data {@link Region} that holds the {@link RedisDataType} information for
+   * all Regions created. The mapping is a {@link String} key which is the name of the
+   * {@link Region} created to hold the data to the RedisDataType it contains.
+   */
+  private final Region<String, RedisDataType> redisMetaRegion;
+
+  /**
+   * This is the {@link RedisDataType#REDIS_STRING} {@link Region}. This is the Region that stores
+   * all string contents
+   */
+  private final Region<ByteArrayWrapper, ByteArrayWrapper> stringsRegion;
+
+  /**
+   * This is the {@link RedisDataType#REDIS_HLL} {@link Region}. This is the Region that stores all
+   * HyperLogLog contents
+   */
+  private final Region<ByteArrayWrapper, HyperLogLogPlus> hLLRegion;
+
+  private final Cache cache;
+  private final QueryService queryService;
+  private final ConcurrentMap<ByteArrayWrapper, Map<Enum<?>, Query>> preparedQueries =
+      new ConcurrentHashMap<ByteArrayWrapper, Map<Enum<?>, Query>>();
+  private final ConcurrentMap<ByteArrayWrapper, ScheduledFuture<?>> expirationsMap;
+  private final ScheduledExecutorService expirationExecutor;
+  private final RegionShortcut defaultRegionType;
+  private static final CreateAlterDestroyRegionCommands cliCmds =
+      new CreateAlterDestroyRegionCommands();
+  private final ConcurrentHashMap<String, Lock> locks;
+
+  public RegionProvider(Region<ByteArrayWrapper, ByteArrayWrapper> stringsRegion,
+      Region<ByteArrayWrapper, HyperLogLogPlus> hLLRegion,
+      Region<String, RedisDataType> redisMetaRegion,
+      ConcurrentMap<ByteArrayWrapper, ScheduledFuture<?>> expirationsMap,
+      ScheduledExecutorService expirationExecutor, RegionShortcut defaultShortcut) {
+    if (stringsRegion == null || hLLRegion == null || redisMetaRegion == null)
+      throw new NullPointerException();
+    this.regions = new ConcurrentHashMap<ByteArrayWrapper, Region<?, ?>>();
+    this.stringsRegion = stringsRegion;
+    this.hLLRegion = hLLRegion;
+    this.redisMetaRegion = redisMetaRegion;
+    this.cache = GemFireCacheImpl.getInstance();
+    this.queryService = cache.getQueryService();
+    this.expirationsMap = expirationsMap;
+    this.expirationExecutor = expirationExecutor;
+    this.defaultRegionType = defaultShortcut;
+    this.locks = new ConcurrentHashMap<String, Lock>();
+  }
+
+  public boolean existsKey(ByteArrayWrapper key) {
+    return this.redisMetaRegion.containsKey(key.toString());
+  }
+
+  public Set<String> metaKeySet() {
+    return this.redisMetaRegion.keySet();
+  }
+
+  public Set<Entry<String, RedisDataType>> metaEntrySet() {
+    return this.redisMetaRegion.entrySet();
+  }
+
+  public int getMetaSize() {
+    return this.redisMetaRegion.size() - RedisConstants.NUM_DEFAULT_KEYS;
+  }
+
+  private boolean metaRemoveEntry(ByteArrayWrapper key) {
+    return this.redisMetaRegion.remove(key.toString()) != null;
+  }
+
+  public RedisDataType metaPutIfAbsent(ByteArrayWrapper key, RedisDataType value) {
+    return this.redisMetaRegion.putIfAbsent(key.toString(), value);
+  }
+
+  public RedisDataType metaPut(ByteArrayWrapper key, RedisDataType value) {
+    return this.redisMetaRegion.put(key.toString(), value);
+  }
+
+  public RedisDataType metaGet(ByteArrayWrapper key) {
+    return this.redisMetaRegion.get(key.toString());
+  }
+
+  public Region<?, ?> getRegion(ByteArrayWrapper key) {
+    return this.regions.get(key);
+  }
+
+  public void removeRegionReferenceLocally(ByteArrayWrapper key, RedisDataType type) {
+    Lock lock = this.locks.get(key.toString());
+    boolean locked = false;
+    try {
+      locked = lock.tryLock();
+      // If we cannot get the lock we ignore this remote event, this key has local event
+      // that started independently, ignore this event to prevent deadlock
+      if (locked) {
+        cancelKeyExpiration(key);
+        removeRegionState(key, type);
+      }
+    } finally {
+      if (locked) {
+        lock.unlock();
+      }
+    }
+  }
+
+  public boolean removeKey(ByteArrayWrapper key) {
+    RedisDataType type = getRedisDataType(key);
+    return removeKey(key, type);
+  }
+
+  public boolean removeKey(ByteArrayWrapper key, RedisDataType type) {
+    return removeKey(key, type, true);
+  }
+
+  public boolean removeKey(ByteArrayWrapper key, RedisDataType type, boolean cancelExpiration) {
+    if (type == null || type == RedisDataType.REDIS_PROTECTED)
+      return false;
+    Lock lock = this.locks.get(key.toString());
+    try {
+      if (lock != null) {// Strings/hlls will not have locks
+        lock.lock();
+      }
+      metaRemoveEntry(key);
+      try {
+        if (type == RedisDataType.REDIS_STRING) {
+          return this.stringsRegion.remove(key) != null;
+        } else if (type == RedisDataType.REDIS_HLL) {
+          return this.hLLRegion.remove(key) != null;
+        } else {
+          return destroyRegion(key, type);
+        }
+      } catch (Exception exc) {
+        return false;
+      } finally {
+        if (cancelExpiration)
+          cancelKeyExpiration(key);
+        else
+          removeKeyExpiration(key);
+        if (lock != null)
+          this.locks.remove(key.toString());
+      }
+    } finally {
+      if (lock != null) {
+        lock.unlock();
+      }
+    }
+  }
+
+  public Region<?, ?> getOrCreateRegion(ByteArrayWrapper key, RedisDataType type,
+      ExecutionHandlerContext context) {
+    return getOrCreateRegion0(key, type, context, true);
+  }
+
+  public void createRemoteRegionReferenceLocally(ByteArrayWrapper key, RedisDataType type) {
+    if (type == null || type == RedisDataType.REDIS_STRING || type == RedisDataType.REDIS_HLL)
+      return;
+    Region<?, ?> r = this.regions.get(key);
+    if (r != null)
+      return;
+    if (!this.regions.contains(key)) {
+      String stringKey = key.toString();
+      Lock lock = this.locks.get(stringKey);
+      if (lock == null) {
+        this.locks.putIfAbsent(stringKey, new ReentrantLock());
+        lock = this.locks.get(stringKey);
+      }
+      boolean locked = false;
+      try {
+        locked = lock.tryLock();
+        // If we cannot get the lock then this remote event may have been initialized
+        // independently on this machine, so if we wait on the lock it is more than
+        // likely we will deadlock just to do the same task. This event can be ignored
+        if (locked) {
+          r = cache.getRegion(key.toString());
+          // If r is null, this implies that we are after a create/destroy
+          // simply ignore. Calls to getRegion or getOrCreate will work correctly
+          if (r == null)
+            return;
+
+          if (type == RedisDataType.REDIS_LIST) {
+            doInitializeList(key, r);
+          } else if (type == RedisDataType.REDIS_SORTEDSET) {
+            try {
+              doInitializeSortedSet(key, r);
+            } catch (RegionNotFoundException | IndexInvalidException e) {
+              // ignore
+            }
+          }
+          this.regions.put(key, r);
+        }
+      } finally {
+        if (locked) {
+          lock.unlock();
+        }
+      }
+    }
+  }
+
+  private Region<?, ?> getOrCreateRegion0(ByteArrayWrapper key, RedisDataType type,
+      ExecutionHandlerContext context, boolean addToMeta) {
+    checkDataType(key, type);
+    Region<?, ?> r = this.regions.get(key);
+    if (r != null && r.isDestroyed()) {
+      removeKey(key, type);
+      r = null;
+    }
+    if (r == null) {
+      String stringKey = key.toString();
+      Lock lock = this.locks.get(stringKey);
+      if (lock == null) {
+        this.locks.putIfAbsent(stringKey, new ReentrantLock());
+        lock = this.locks.get(stringKey);
+      }
+
+      try {
+        lock.lock();
+        r = regions.get(key);
+        if (r == null) {
+          boolean hasTransaction = context != null && context.hasTransaction(); // Can create
+                                                                                // without context
+          CacheTransactionManager txm = null;
+          TransactionId transactionId = null;
+          try {
+            if (hasTransaction) {
+              txm = cache.getCacheTransactionManager();
+              transactionId = txm.suspend();
+            }
+            Exception concurrentCreateDestroyException = null;
+            do {
+              concurrentCreateDestroyException = null;
+              r = createRegionGlobally(stringKey);
+              try {
+                if (type == RedisDataType.REDIS_LIST) {
+                  doInitializeList(key, r);
+                } else if (type == RedisDataType.REDIS_SORTEDSET) {
+                  try {
+                    doInitializeSortedSet(key, r);
+                  } catch (RegionNotFoundException | IndexInvalidException e) {
+                    concurrentCreateDestroyException = e;
+                  }
+                }
+              } catch (QueryInvalidException e) {
+                if (e.getCause() instanceof RegionNotFoundException) {
+                  concurrentCreateDestroyException = e;
+                }
+              }
+            } while (concurrentCreateDestroyException != null);
+            this.regions.put(key, r);
+            if (addToMeta) {
+              RedisDataType existingType = metaPutIfAbsent(key, type);
+              if (existingType != null && existingType != type)
+                throw new RedisDataTypeMismatchException(
+                    "The key name \"" + key + "\" is already used by a " + existingType.toString());
+            }
+          } finally {
+            if (hasTransaction)
+              txm.resume(transactionId);
+          }
+        }
+      } finally {
+        lock.unlock();
+      }
+    }
+    return r;
+  }
+
+  /**
+   * SYNCHRONIZE EXTERNALLY OF this.locks.get(key.toString())!!!!!
+   * 
+   * @param key Key of region to destroy
+   * @param type Type of region to destroyu
+   * @return Flag if destroyed
+   */
+  private boolean destroyRegion(ByteArrayWrapper key, RedisDataType type) {
+    Region<?, ?> r = this.regions.get(key);
+    if (r != null) {
+      try {
+        r.destroyRegion();
+      } catch (Exception e) {
+        return false;
+      } finally {
+        removeRegionState(key, type);
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Do not call this method if you are not synchronized on the lock associated with this key
+   * 
+   * @param key Key of region to remove
+   * @param type Type of key to remove all state
+   */
+  private void removeRegionState(ByteArrayWrapper key, RedisDataType type) {
+    this.preparedQueries.remove(key);
+    this.regions.remove(key);
+  }
+
+  private void doInitializeSortedSet(ByteArrayWrapper key, Region<?, ?> r)
+      throws RegionNotFoundException, IndexInvalidException {
+    String fullpath = r.getFullPath();
+    try {
+      queryService.createIndex("scoreIndex", "entry.value.score",
+          r.getFullPath() + ".entrySet entry");
+      queryService.createIndex("scoreIndex2", "value.score", r.getFullPath() + ".values value");
+    } catch (IndexNameConflictException | IndexExistsException | UnsupportedOperationException e) {
+      // ignore, these indexes already exist or unsupported but make sure prepared queries are made
+    }
+    HashMap<Enum<?>, Query> queryList = new HashMap<Enum<?>, Query>();
+    for (SortedSetQuery lq : SortedSetQuery.values()) {
+      String queryString = lq.getQueryString(fullpath);
+      Query query = this.queryService.newQuery(queryString);
+      queryList.put(lq, query);
+    }
+    this.preparedQueries.put(key, queryList);
+  }
+
+  private void doInitializeList(ByteArrayWrapper key, Region r) {
+    r.put("head", Integer.valueOf(0));
+    r.put("tail", Integer.valueOf(0));
+    String fullpath = r.getFullPath();
+    HashMap<Enum<?>, Query> queryList = new HashMap<Enum<?>, Query>();
+    for (ListQuery lq : ListQuery.values()) {
+      String queryString = lq.getQueryString(fullpath);
+      Query query = this.queryService.newQuery(queryString);
+      queryList.put(lq, query);
+    }
+    this.preparedQueries.put(key, queryList);
+  }
+
+  /**
+   * This method creates a Region globally with the given name. If there is an error in the
+   * creation, a runtime exception will be thrown.
+   * 
+   * @param key Name of Region to create
+   * @return Region Region created globally
+   */
+  private Region<?, ?> createRegionGlobally(String key) {
+    Region<?, ?> r = null;
+    r = cache.getRegion(key);
+    if (r != null)
+      return r;
+    do {
+      Result result = cliCmds.createRegion(key, defaultRegionType, null, null, true, null, null,
+          null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+          null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+          null, null);
+      r = cache.getRegion(key);
+      if (result.getStatus() == Status.ERROR && r == null) {
+        String err = "";
+        while (result.hasNextLine())
+          err += result.nextLine();
+        throw new RegionCreationException(err);
+      }
+    } while (r == null); // The region can be null in the case that it is concurrently destroyed by
+    // a remote even triggered internally by Geode
+    return r;
+  }
+
+  public Query getQuery(ByteArrayWrapper key, Enum<?> query) {
+    return this.preparedQueries.get(key).get(query);
+    /*
+     * if (query instanceof ListQuery) { return
+     * this.queryService.newQuery(((ListQuery)query).getQueryString(this.regions.get(key).
+     * getFullPath())); } else { return
+     * this.queryService.newQuery(((SortedSetQuery)query).getQueryString(this.regions.get(key).
+     * getFullPath())); }
+     */
+  }
+
+  /**
+   * Checks if the given key is associated with the passed data type. If there is a mismatch, a
+   * {@link RuntimeException} is thrown
+   * 
+   * @param key Key to check
+   * @param type Type to check to
+   */
+  protected void checkDataType(ByteArrayWrapper key, RedisDataType type) {
+    RedisDataType currentType = redisMetaRegion.get(key.toString());
+    if (currentType == null)
+      return;
+    if (currentType == RedisDataType.REDIS_PROTECTED)
+      throw new RedisDataTypeMismatchException("The key name \"" + key + "\" is protected");
+    if (currentType != type)
+      throw new RedisDataTypeMismatchException(
+          "The key name \"" + key + "\" is already used by a " + currentType.toString());
+  }
+
+  public boolean regionExists(ByteArrayWrapper key) {
+    return this.regions.containsKey(key);
+  }
+
+  public Region<ByteArrayWrapper, ByteArrayWrapper> getStringsRegion() {
+    return this.stringsRegion;
+  }
+
+  public Region<ByteArrayWrapper, HyperLogLogPlus> gethLLRegion() {
+    return this.hLLRegion;
+  }
+
+  private RedisDataType getRedisDataType(String key) {
+    return this.redisMetaRegion.get(key);
+  }
+
+  public RedisDataType getRedisDataType(ByteArrayWrapper key) {
+    return getRedisDataType(key.toString());
+  }
+
+  /**
+   * Sets the expiration for a key. The setting and modifying of a key expiration can only be set by
+   * a delay, which means that both expiring after a time and at a time can be done but the delay to
+   * expire at a time must be calculated before these calls. It is also important to note that the
+   * delay is always handled in milliseconds
+   * 
+   * @param key The key to set the expiration for
+   * @param delay The delay in milliseconds of the expiration
+   * @return True is expiration set, false otherwise
+   */
+  public final boolean setExpiration(ByteArrayWrapper key, long delay) {
+    RedisDataType type = getRedisDataType(key);
+    if (type == null)
+      return false;
+    ScheduledFuture<?> future = this.expirationExecutor
+        .schedule(new ExpirationExecutor(key, type, this), delay, TimeUnit.MILLISECONDS);
+    this.expirationsMap.put(key, future);
+    return true;
+  }
+
+  /**
+   * Modifies an expiration on a key
+   * 
+   * @param key String key to modify expiration on
+   * @param delay Delay in milliseconds to reset the expiration to
+   * @return True if reset, false if not
+   */
+  public final boolean modifyExpiration(ByteArrayWrapper key, long delay) {
+    /*
+     * Attempt to cancel future task
+     */
+    boolean canceled = cancelKeyExpiration(key);
+
+    if (!canceled)
+      return false;
+
+    RedisDataType type = getRedisDataType(key);
+    if (type == null)
+      return false;
+
+    ScheduledFuture<?> future = this.expirationExecutor
+        .schedule(new ExpirationExecutor(key, type, this), delay, TimeUnit.MILLISECONDS);
+    this.expirationsMap.put(key, future);
+    return true;
+  }
+
+  /**
+   * Removes an expiration from a key
+   * 
+   * @param key Key
+   * @return True is expiration cancelled on the key, false otherwise
+   */
+  public final boolean cancelKeyExpiration(ByteArrayWrapper key) {
+    ScheduledFuture<?> future = expirationsMap.remove(key);
+    if (future == null)
+      return false;
+    return future.cancel(false);
+  }
+
+  private boolean removeKeyExpiration(ByteArrayWrapper key) {
+    return expirationsMap.remove(key) != null;
+  }
+
+  /**
+   * Check method if key has expiration
+   * 
+   * @param key Key
+   * @return True if key has expiration, false otherwise
+   */
+  public boolean hasExpiration(ByteArrayWrapper key) {
+    return this.expirationsMap.containsKey(key);
+  }
+
+  /**
+   * Get remaining expiration time
+   * 
+   * @param key Key
+   * @return Remaining time in milliseconds or 0 if no delay or key doesn't exist
+   */
+  public final long getExpirationDelayMillis(ByteArrayWrapper key) {
+    ScheduledFuture<?> future = this.expirationsMap.get(key);
+    return future != null ? future.getDelay(TimeUnit.MILLISECONDS) : 0L;
+  }
+
+  @Override
+  public void close() {
+    this.preparedQueries.clear();
+  }
+
+  public String dumpRegionsCache() {
+    StringBuilder builder = new StringBuilder();
+    for (Entry<ByteArrayWrapper, Region<?, ?>> e : this.regions.entrySet()) {
+      builder.append(e.getKey() + " --> {" + e.getValue() + "}\n");
+    }
+    return builder.toString();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractExecutor.java
new file mode 100644
index 0000000..590ab06
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractExecutor.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.query.Query;
+import org.apache.geode.redis.GeodeRedisServiceImpl;
+import org.apache.geode.redis.internal.ByteArrayWrapper;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.Executor;
+import org.apache.geode.redis.internal.RedisDataType;
+import org.apache.geode.redis.internal.RedisDataTypeMismatchException;
+import org.apache.geode.redis.internal.RegionProvider;
+
+/**
+ * The AbstractExecutor is the base of all {@link Executor} types for the
+ * {@link GeodeRedisServiceImpl}.
+ * 
+ *
+ */
+public abstract class AbstractExecutor implements Executor {
+
+  /**
+   * Number of Regions used by GeodeRedisServiceImpl internally
+   */
+  public static final int NUM_DEFAULT_REGIONS = 3;
+
+  /**
+   * Max length of a list
+   */
+  protected static final Integer INFINITY_LIMIT = Integer.MAX_VALUE;
+
+  /**
+   * Constant of number of milliseconds in a second
+   */
+  protected static final int millisInSecond = 1000;
+
+  /**
+   * Getter method for a {@link Region} in the case that a Region should be created if one with the
+   * given name does not exist. Before getting or creating a Region, a check is first done to make
+   * sure the desired key doesn't already exist with a different {@link RedisDataType}. If there is
+   * a data type mismatch this method will throw a {@link RuntimeException}.
+   * 
+   * ********************** IMPORTANT NOTE ********************************************** This
+   * method will not fail in returning a Region unless an internal error occurs, so if a Region is
+   * destroyed right after it is created, it will attempt to retry until a reference to that Region
+   * is obtained
+   * *************************************************************************************
+   * 
+   * @param context Client client
+   * @param key String key of desired key
+   * @param type Type of data type desired
+   * @return Region with name key
+   */
+  protected Region<?, ?> getOrCreateRegion(ExecutionHandlerContext context, ByteArrayWrapper key,
+      RedisDataType type) {
+    return context.getRegionProvider().getOrCreateRegion(key, type, context);
+  }
+
+  /**
+   * Checks if the given key is associated with the passed data type. If there is a mismatch, a
+   * {@link RuntimeException} is thrown
+   * 
+   * @param key Key to check
+   * @param type Type to check to
+   * @param context context
+   */
+  protected void checkDataType(ByteArrayWrapper key, RedisDataType type,
+      ExecutionHandlerContext context) {
+    RedisDataType currentType = context.getRegionProvider().getRedisDataType(key);
+    if (currentType == null)
+      return;
+    if (currentType == RedisDataType.REDIS_PROTECTED)
+      throw new RedisDataTypeMismatchException("The key name \"" + key + "\" is protected");
+    if (currentType != type)
+      throw new RedisDataTypeMismatchException(
+          "The key name \"" + key + "\" is already used by a " + currentType.toString());
+  }
+
+  protected Query getQuery(ByteArrayWrapper key, Enum<?> type, ExecutionHandlerContext context) {
+    return context.getRegionProvider().getQuery(key, type);
+  }
+
+  protected boolean removeEntry(ByteArrayWrapper key, RedisDataType type,
+      ExecutionHandlerContext context) {
+    if (type == null || type == RedisDataType.REDIS_PROTECTED)
+      return false;
+    RegionProvider rC = context.getRegionProvider();
+    return rC.removeKey(key, type);
+  }
+
+  protected int getBoundedStartIndex(int index, int size) {
+    if (size < 0)
+      throw new IllegalArgumentException("Size < 0, really?");
+    if (index >= 0)
+      return Math.min(index, size);
+    else
+      return Math.max(index + size, 0);
+  }
+
+  protected int getBoundedEndIndex(int index, int size) {
+    if (size < 0)
+      throw new IllegalArgumentException("Size < 0, really?");
+    if (index >= 0)
+      return Math.min(index, size);
+    else
+      return Math.max(index + size, -1);
+  }
+
+  protected long getBoundedStartIndex(long index, long size) {
+    if (size < 0L)
+      throw new IllegalArgumentException("Size < 0, really?");
+    if (index >= 0L)
+      return Math.min(index, size);
+    else
+      return Math.max(index + size, 0);
+  }
+
+  protected long getBoundedEndIndex(long index, long size) {
+    if (size < 0L)
+      throw new IllegalArgumentException("Size < 0, really?");
+    if (index >= 0L)
+      return Math.min(index, size);
+    else
+      return Math.max(index + size, -1);
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractScanExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractScanExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractScanExecutor.java
new file mode 100644
index 0000000..02894aa
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AbstractScanExecutor.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.org.apache.hadoop.fs.GlobPattern;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.regex.Pattern;
+
+
+public abstract class AbstractScanExecutor extends AbstractExecutor {
+
+  protected final String ERROR_CURSOR = "Invalid cursor";
+
+  protected final String ERROR_COUNT = "Count must be numeric and positive";
+
+  protected final String ERROR_INVALID_CURSOR =
+      "Cursor is invalid, dataset may have been altered if this is cursor from a previous scan";
+
+  protected final int DEFUALT_COUNT = 10;
+
+  protected abstract List<?> getIteration(Collection<?> list, Pattern matchPatter, int count,
+      int cursor);
+
+  /**
+   * @param pattern A glob pattern.
+   * @return A regex pattern to recognize the given glob pattern.
+   */
+  protected final Pattern convertGlobToRegex(String pattern) {
+    if (pattern == null)
+      return null;
+    return GlobPattern.compile(pattern);
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AuthExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AuthExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AuthExecutor.java
new file mode 100644
index 0000000..2a63fa8
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/AuthExecutor.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.Executor;
+import org.apache.geode.redis.internal.RedisConstants;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class AuthExecutor implements Executor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.AUTH));
+      return;
+    }
+    byte[] pwd = context.getAuthPwd();
+    if (pwd == null) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), RedisConstants.ERROR_NO_PASS));
+      return;
+    }
+    boolean correct = Arrays.equals(commandElems.get(1), pwd);
+
+    if (correct) {
+      context.setAuthenticationVerified();
+      command.setResponse(Coder.getSimpleStringResponse(context.getByteBufAllocator(), "OK"));
+    } else {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), RedisConstants.ERROR_INVALID_PWD));
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DBSizeExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DBSizeExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DBSizeExecutor.java
new file mode 100644
index 0000000..0a121cc
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DBSizeExecutor.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+
+public class DBSizeExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    int size = context.getRegionProvider().getMetaSize();
+    command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), size));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DelExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DelExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DelExecutor.java
new file mode 100644
index 0000000..f827fa8
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/DelExecutor.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.cache.UnsupportedOperationInTransactionException;
+import org.apache.geode.redis.internal.ByteArrayWrapper;
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+import org.apache.geode.redis.internal.RedisDataType;
+
+import java.util.List;
+
+public class DelExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    if (context.hasTransaction())
+      throw new UnsupportedOperationInTransactionException();
+
+    List<byte[]> commandElems = command.getProcessedCommand();
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.DEL));
+      return;
+    }
+
+    int numRemoved = 0;
+
+    for (int i = 1; i < commandElems.size(); i++) {
+      byte[] byteKey = commandElems.get(i);
+      ByteArrayWrapper key = new ByteArrayWrapper(byteKey);
+      RedisDataType type = context.getRegionProvider().getRedisDataType(key);
+      if (removeEntry(key, type, context))
+        numRemoved++;
+    }
+
+    command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), numRemoved));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/EchoExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/EchoExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/EchoExecutor.java
new file mode 100644
index 0000000..acbeb2a
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/EchoExecutor.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+
+import java.util.List;
+
+public class EchoExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.ECHO));
+      return;
+    }
+
+    byte[] echoMessage = commandElems.get(1);
+    command.setResponse(Coder.getBulkStringResponse(context.getByteBufAllocator(), echoMessage));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExistsExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExistsExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExistsExecutor.java
new file mode 100644
index 0000000..ca7991e
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExistsExecutor.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.ByteArrayWrapper;
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+
+import java.util.List;
+
+public class ExistsExecutor extends AbstractExecutor {
+  private final int EXISTS = 1;
+
+  private final int NOT_EXISTS = 0;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.EXISTS));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+    boolean exists = context.getRegionProvider().existsKey(key);
+
+    if (exists)
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), EXISTS));
+    else
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_EXISTS));
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpirationExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpirationExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpirationExecutor.java
new file mode 100644
index 0000000..86503f1
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpirationExecutor.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.ByteArrayWrapper;
+import org.apache.geode.redis.internal.RedisDataType;
+import org.apache.geode.redis.internal.RegionProvider;
+
+
+public class ExpirationExecutor implements Runnable {
+  private final ByteArrayWrapper key;
+  private final RedisDataType type;
+  private final RegionProvider rC;
+
+  public ExpirationExecutor(ByteArrayWrapper k, RedisDataType type, RegionProvider rC) {
+    this.key = k;
+    this.type = type;
+    this.rC = rC;
+  }
+
+  @Override
+  public void run() {
+    rC.removeKey(key, type, false);
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireAtExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireAtExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireAtExecutor.java
new file mode 100644
index 0000000..dabec5e
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireAtExecutor.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.ByteArrayWrapper;
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.Extendable;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+import org.apache.geode.redis.internal.RegionProvider;
+
+import java.util.List;
+
+public class ExpireAtExecutor extends AbstractExecutor implements Extendable {
+
+  private final String ERROR_TIMESTAMP_NOT_USABLE = "The timestamp specified must be numeric";
+
+  private final int TIMESTAMP_INDEX = 2;
+
+  private final int SET = 1;
+
+  private final int NOT_SET = 0;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), getArgsError()));
+      return;
+    }
+    RegionProvider rC = context.getRegionProvider();
+    ByteArrayWrapper wKey = command.getKey();
+
+    byte[] timestampByteArray = commandElems.get(TIMESTAMP_INDEX);
+    long timestamp;
+    try {
+      timestamp = Coder.bytesToLong(timestampByteArray);
+    } catch (NumberFormatException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_TIMESTAMP_NOT_USABLE));
+      return;
+    }
+
+    if (!timeUnitMillis())
+      timestamp = timestamp * millisInSecond;
+
+    long currentTimeMillis = System.currentTimeMillis();
+
+    if (timestamp <= currentTimeMillis) {
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_SET));
+      return;
+    }
+
+    long delayMillis = timestamp - currentTimeMillis;
+
+    boolean expirationSet = false;
+
+    if (rC.hasExpiration(wKey))
+      expirationSet = rC.modifyExpiration(wKey, delayMillis);
+    else
+      expirationSet = rC.setExpiration(wKey, delayMillis);
+
+    if (expirationSet)
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), SET));
+    else
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_SET));
+  }
+
+  protected boolean timeUnitMillis() {
+    return false;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.EXPIREAT;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireExecutor.java
new file mode 100644
index 0000000..80866f9
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpireExecutor.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.internal.ByteArrayWrapper;
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.Extendable;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+import org.apache.geode.redis.internal.RegionProvider;
+
+import java.util.List;
+
+public class ExpireExecutor extends AbstractExecutor implements Extendable {
+
+  private final String ERROR_SECONDS_NOT_USABLE = "The number of seconds specified must be numeric";
+
+  private final int SECONDS_INDEX = 2;
+
+  private final int SET = 1;
+
+  private final int NOT_SET = 0;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), getArgsError()));
+      return;
+    }
+    ByteArrayWrapper wKey = command.getKey();
+    RegionProvider rC = context.getRegionProvider();
+    byte[] delayByteArray = commandElems.get(SECONDS_INDEX);
+    long delay;
+    try {
+      delay = Coder.bytesToLong(delayByteArray);
+    } catch (NumberFormatException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_SECONDS_NOT_USABLE));
+      return;
+    }
+
+    if (delay <= 0) {
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_SET));
+      return;
+    }
+
+    // If time unit given is not in millis convert to millis
+    if (!timeUnitMillis())
+      delay = delay * millisInSecond;
+
+    boolean expirationSet = false;
+
+    if (rC.hasExpiration(wKey))
+      expirationSet = rC.modifyExpiration(wKey, delay);
+    else
+      expirationSet = rC.setExpiration(wKey, delay);
+
+
+    if (expirationSet)
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), SET));
+    else
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_SET));
+  }
+
+  /*
+   * Overridden by PExpire
+   */
+  protected boolean timeUnitMillis() {
+    return false;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.EXPIRE;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/FlushAllExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/FlushAllExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/FlushAllExecutor.java
new file mode 100644
index 0000000..90148ae
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/FlushAllExecutor.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.cache.EntryDestroyedException;
+import org.apache.geode.cache.UnsupportedOperationInTransactionException;
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.RedisDataType;
+
+import java.util.Map.Entry;
+
+public class FlushAllExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    if (context.hasTransaction())
+      throw new UnsupportedOperationInTransactionException();
+
+    for (Entry<String, RedisDataType> e : context.getRegionProvider().metaEntrySet()) {
+      try {
+        String skey = e.getKey();
+        RedisDataType type = e.getValue();
+        removeEntry(Coder.stringToByteWrapper(skey), type, context);
+      } catch (EntryDestroyedException e1) {
+        continue;
+      }
+
+    }
+
+    command.setResponse(Coder.getSimpleStringResponse(context.getByteBufAllocator(), "OK"));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/KeysExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/KeysExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/KeysExecutor.java
new file mode 100644
index 0000000..79ff5e2
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/KeysExecutor.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.executor;
+
+import org.apache.geode.redis.GeodeRedisServiceImpl;
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+import org.apache.geode.redis.internal.RedisConstants;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+import org.apache.geode.redis.internal.org.apache.hadoop.fs.GlobPattern;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class KeysExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.KEYS));
+      return;
+    }
+
+    String glob = Coder.bytesToString(commandElems.get(1));
+    Set<String> allKeys = context.getRegionProvider().metaKeySet();
+    List<String> matchingKeys = new ArrayList<String>();
+
+    Pattern pattern;
+    try {
+      pattern = GlobPattern.compile(glob);
+    } catch (PatternSyntaxException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), RedisConstants.ERROR_ILLEGAL_GLOB));
+      return;
+    }
+
+    for (String key : allKeys) {
+      if (!(key.equals(GeodeRedisServiceImpl.REDIS_META_DATA_REGION)
+          || key.equals(GeodeRedisServiceImpl.STRING_REGION)
+          || key.equals(GeodeRedisServiceImpl.HLL_REGION)) && pattern.matcher(key).matches())
+        matchingKeys.add(key);
+    }
+
+    if (matchingKeys.isEmpty())
+      command.setResponse(Coder.getEmptyArrayResponse(context.getByteBufAllocator()));
+    else
+      command.setResponse(
+          Coder.getBulkStringArrayResponse(context.getByteBufAllocator(), matchingKeys));
+
+
+  }
+}


Mime
View raw message