geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From u..@apache.org
Subject [08/21] geode git commit: GEODE-2449: Moved Redis out of core with minimal Extension work added
Date Fri, 10 Feb 2017 21:34:11 GMT
http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ListQuery.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ListQuery.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ListQuery.java
new file mode 100644
index 0000000..dcd062a
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ListQuery.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+public enum ListQuery {
+
+  LINDEX {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE key != 'head' AND key != 'tail' ORDER BY key asc LIMIT $1";
+    }
+  },
+  LRANGE {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE key != 'head' AND key != 'tail' ORDER BY key asc LIMIT $1";
+    }
+  },
+  LREMG {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE value = $1 AND key != 'head' AND key != 'tail' ORDER BY key asc LIMIT $2";
+    }
+  },
+  LREML {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE value = $1 AND key != 'head' AND key != 'tail' ORDER BY key desc LIMIT $2";
+    }
+  },
+  LREME {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE value = $1 ORDER BY key asc";
+    }
+  },
+  LSET {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key != 'head' AND key != 'tail' ORDER BY key asc LIMIT $1";
+    }
+  },
+  LTRIM {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key != 'head' AND key != 'tail' ORDER BY key asc LIMIT $1";
+    }
+  };
+
+  public abstract String getQueryString(String fullpath);
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireAtExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireAtExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireAtExecutor.java
new file mode 100644
index 0000000..fa68d13
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireAtExecutor.java
@@ -0,0 +1,30 @@
+/*
+ * 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.RedisConstants.ArityDef;
+
+public class PExpireAtExecutor extends ExpireAtExecutor {
+
+  @Override
+  protected boolean timeUnitMillis() {
+    return true;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.PEXPIREAT;
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireExecutor.java
new file mode 100644
index 0000000..3581d5d
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PExpireExecutor.java
@@ -0,0 +1,30 @@
+/*
+ * 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.RedisConstants.ArityDef;
+
+public class PExpireExecutor extends ExpireExecutor {
+
+  @Override
+  protected boolean timeUnitMillis() {
+    return true;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.PEXPIRE;
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PTTLExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PTTLExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PTTLExecutor.java
new file mode 100644
index 0000000..9e15d56
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PTTLExecutor.java
@@ -0,0 +1,31 @@
+/*
+ * 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.RedisConstants.ArityDef;
+
+public class PTTLExecutor extends TTLExecutor {
+
+
+  @Override
+  protected boolean timeUnitMillis() {
+    return true;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.PTTL;
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PersistExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PersistExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PersistExecutor.java
new file mode 100644
index 0000000..16bbc0f
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PersistExecutor.java
@@ -0,0 +1,51 @@
+/*
+ * 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 PersistExecutor extends AbstractExecutor {
+
+  private final int TIMEOUT_REMOVED = 1;
+
+  private final int KEY_NOT_EXIST_OR_NO_TIMEOUT = 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.PERSIST));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    boolean canceled = context.getRegionProvider().cancelKeyExpiration(key);
+
+    if (canceled)
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), TIMEOUT_REMOVED));
+    else
+      command.setResponse(
+          Coder.getIntegerResponse(context.getByteBufAllocator(), KEY_NOT_EXIST_OR_NO_TIMEOUT));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PingExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PingExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PingExecutor.java
new file mode 100644
index 0000000..4561b5c
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/PingExecutor.java
@@ -0,0 +1,30 @@
+/*
+ * 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 PingExecutor extends AbstractExecutor {
+
+  private final String PING_RESPONSE = "PONG";
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    command
+        .setResponse(Coder.getSimpleStringResponse(context.getByteBufAllocator(), PING_RESPONSE));
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/QuitExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/QuitExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/QuitExecutor.java
new file mode 100644
index 0000000..84ad241
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/QuitExecutor.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+public class QuitExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    command.setResponse(
+        Coder.getSimpleStringResponse(context.getByteBufAllocator(), RedisConstants.QUIT_RESPONSE));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ScanExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ScanExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ScanExecutor.java
new file mode 100644
index 0000000..3f8ea4d
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ScanExecutor.java
@@ -0,0 +1,146 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class ScanExecutor extends AbstractScanExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.SCAN));
+      return;
+    }
+
+    String cursorString = command.getStringKey();
+    int cursor = 0;
+    Pattern matchPattern = null;
+    String globMatchString = null;
+    int count = DEFUALT_COUNT;
+    try {
+      cursor = Integer.parseInt(cursorString);
+    } catch (NumberFormatException e) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_CURSOR));
+      return;
+    }
+    if (cursor < 0) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_CURSOR));
+      return;
+    }
+
+    if (commandElems.size() > 3) {
+      try {
+        byte[] bytes = commandElems.get(2);
+        String tmp = Coder.bytesToString(bytes);
+        if (tmp.equalsIgnoreCase("MATCH")) {
+          bytes = commandElems.get(3);
+          globMatchString = Coder.bytesToString(bytes);
+        } else if (tmp.equalsIgnoreCase("COUNT")) {
+          bytes = commandElems.get(3);
+          count = Coder.bytesToInt(bytes);
+        }
+      } catch (NumberFormatException e) {
+        command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_COUNT));
+        return;
+      }
+    }
+
+    if (commandElems.size() > 5) {
+      try {
+        byte[] bytes = commandElems.get(4);
+        String tmp = Coder.bytesToString(bytes);
+        if (tmp.equalsIgnoreCase("COUNT")) {
+          bytes = commandElems.get(5);
+          count = Coder.bytesToInt(bytes);
+        }
+      } catch (NumberFormatException e) {
+        command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_COUNT));
+        return;
+      }
+    }
+
+    if (count < 0) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_COUNT));
+      return;
+    }
+
+    try {
+      matchPattern = convertGlobToRegex(globMatchString);
+    } catch (PatternSyntaxException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), RedisConstants.ERROR_ILLEGAL_GLOB));
+      return;
+    }
+
+    @SuppressWarnings("unchecked")
+    List<String> returnList = (List<String>) getIteration(context.getRegionProvider().metaKeySet(),
+        matchPattern, count, cursor);
+
+    command.setResponse(Coder.getScanResponse(context.getByteBufAllocator(), returnList));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  protected List<?> getIteration(Collection<?> list, Pattern matchPattern, int count, int cursor) {
+    List<String> returnList = new ArrayList<String>();
+    int size = list.size();
+    int beforeCursor = 0;
+    int numElements = 0;
+    int i = -1;
+    for (String key : (Collection<String>) list) {
+      if (key.equals(GeodeRedisServiceImpl.REDIS_META_DATA_REGION)
+          || key.equals(GeodeRedisServiceImpl.STRING_REGION)
+          || key.equals(GeodeRedisServiceImpl.HLL_REGION))
+        continue;
+      i++;
+      if (beforeCursor < cursor) {
+        beforeCursor++;
+        continue;
+      } else if (numElements < count) {
+        if (matchPattern != null) {
+          if (matchPattern.matcher(key).matches()) {
+            returnList.add(key);
+            numElements++;
+          }
+        } else {
+          returnList.add(key);
+          numElements++;
+        }
+      } else
+        break;
+    }
+
+    if (i == size - (NUM_DEFAULT_REGIONS + 1))
+      returnList.add(0, String.valueOf(0));
+    else
+      returnList.add(0, String.valueOf(i));
+    return returnList;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ShutDownExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ShutDownExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ShutDownExecutor.java
new file mode 100644
index 0000000..0392095
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ShutDownExecutor.java
@@ -0,0 +1,25 @@
+/*
+ * 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.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+
+public class ShutDownExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {}
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SortedSetQuery.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SortedSetQuery.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SortedSetQuery.java
new file mode 100644
index 0000000..a0a8f63
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SortedSetQuery.java
@@ -0,0 +1,283 @@
+/*
+ * 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;
+
+public enum SortedSetQuery {
+
+  ZCOUNTNINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".values value WHERE value.score <= $1";
+    }
+  },
+  ZCOUNTNINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".values value WHERE value.score < $1";
+    }
+  },
+  ZCOUNTPINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".values value WHERE value.score >= $1";
+    }
+  },
+  ZCOUNTPINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".values value WHERE value.score > $1";
+    }
+  },
+  ZCOUNTSTI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".values value WHERE value.score >= $1 AND value.score < $2";
+    }
+  },
+  ZCOUNTSTISI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".values value WHERE value.score >= $1 AND value.score <= $2";
+    }
+  },
+  ZCOUNTSI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".values value WHERE value.score > $1 AND value.score <= $2";
+    }
+  },
+  ZCOUNT {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".values value WHERE value.score > $1 AND value.score < $2";
+    }
+  },
+  ZLEXCOUNTNINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".keySet key WHERE key.compareTo($1) <= 0";
+    }
+  },
+  ZLEXCOUNTNINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".keySet key WHERE key.compareTo($1) < 0";
+    }
+  },
+  ZLEXCOUNTPINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".keySet key WHERE key.compareTo($1) >= 0";
+    }
+  },
+  ZLEXCOUNTPINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath + ".keySet key WHERE key.compareTo($1) > 0";
+    }
+  },
+  ZLEXCOUNTSTI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) >= 0 AND key.compareTo($2) < 0";
+    }
+  },
+  ZLEXCOUNTSTISI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) >= 0 AND key.compareTo($2) <= 0";
+    }
+  },
+  ZLEXCOUNTSI {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) > 0 AND key.compareTo($2) <= 0";
+    }
+  },
+  ZLEXCOUNT {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) > 0 AND key.compareTo($2) < 0";
+    }
+  },
+  ZRANGEBYLEXNINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) <= 0 ORDER BY key asc LIMIT $2";
+    }
+  },
+  ZRANGEBYLEXNINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) < 0 ORDER BY key asc LIMIT $2";
+    }
+  },
+  ZRANGEBYLEXPINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) >= 0 ORDER BY key asc LIMIT $2";
+    }
+  },
+  ZRANGEBYLEXPINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) > 0 ORDER BY key asc LIMIT $2";
+    }
+  },
+  ZRANGEBYLEXSTI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) >= 0 AND key.compareTo($2) < 0 ORDER BY key asc LIMIT $3";
+    }
+  },
+  ZRANGEBYLEXSTISI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) >= 0 AND key.compareTo($2) <= 0 ORDER BY key asc LIMIT $3";
+    }
+  },
+  ZRANGEBYLEXSI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) > 0 AND key.compareTo($2) <= 0 ORDER BY key asc LIMIT $3";
+    }
+  },
+  ZRANGEBYLEX {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT * FROM " + fullpath
+          + ".keySet key WHERE key.compareTo($1) > 0 AND key.compareTo($2) < 0 ORDER BY key asc LIMIT $3";
+    }
+  },
+  ZREMRANGEBYRANK {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry ORDER BY entry.value asc LIMIT $1";
+    }
+  },
+  ZRBSNINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE value.score <= $1 ORDER BY entry.value asc LIMIT $2";
+    }
+  },
+  ZRBSNINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score < $1 ORDER BY entry.value asc LIMIT $2";
+    }
+  },
+  ZRBSPINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score >= $1 ORDER BY entry.value asc LIMIT $2";
+    }
+  },
+  ZRBSPINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score > $1 ORDER BY entry.value asc LIMIT $2";
+    }
+  },
+  ZRBSSTISI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score >= $1 AND entry.value.score <= $2 ORDER BY entry.value asc LIMIT $3";
+    }
+  },
+  ZRBSSTI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score >= $1 AND entry.value.score < $2 ORDER BY entry.value asc LIMIT $3";
+    }
+  },
+  ZRBSSI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score > $1 AND entry.value.score <= $2 ORDER BY entry.value asc LIMIT $3";
+    }
+  },
+  ZRBS {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score > $1 AND entry.value.score < $2 ORDER BY entry.value asc LIMIT $3";
+    }
+  },
+  ZREVRBSNINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE value <= $1 ORDER BY entry.value desc, entry.key desc LIMIT $2";
+    }
+  },
+  ZREVRBSNINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score < $1 ORDER BY entry.value desc, entry.key desc LIMIT $2";
+    }
+  },
+  ZREVRBSPINFI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score >= $1 ORDER BY entry.value desc, entry.key desc LIMIT $2";
+    }
+  },
+  ZREVRBSPINF {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score > $1 ORDER BY entry.value desc, entry.key desc LIMIT $2";
+    }
+  },
+  ZREVRBSSTISI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score >= $1 AND entry.value.score <= $2 ORDER BY entry.value desc, entry.key desc LIMIT $3";
+    }
+  },
+  ZREVRBSSTI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score >= $1 AND entry.value.score < $2 ORDER BY entry.value desc, entry.key desc LIMIT $3";
+    }
+  },
+  ZREVRBSSI {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score > $1 AND entry.value.score <= $2 ORDER BY entry.value desc, entry.key desc LIMIT $3";
+    }
+  },
+  ZREVRBS {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry WHERE entry.value.score > $1 AND entry.value.score < $2 ORDER BY entry.value desc, entry.key desc LIMIT $3";
+    }
+  },
+  ZREVRANGE {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry ORDER BY entry.value asc, entry.key asc LIMIT $1";
+    }
+  },
+  ZRANGE {
+    public String getQueryString(String fullpath) {
+      return "SELECT DISTINCT entry.key, entry.value FROM " + fullpath
+          + ".entrySet entry ORDER BY entry.value desc, entry.key desc LIMIT $1";
+    }
+  },
+  ZRANK {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".entrySet entry WHERE entry.value < $1 OR (entry.value = $2 AND entry.key.compareTo($3) < 0)";
+    }
+  },
+  ZREVRANK {
+    public String getQueryString(String fullpath) {
+      return "SELECT COUNT(*) FROM " + fullpath
+          + ".entrySet entry WHERE entry.value > $1 OR (entry.value = $2 AND entry.key.compareTo($3) > 0)";
+    }
+  };
+
+  public abstract String getQueryString(String fullpath);
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TTLExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TTLExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TTLExecutor.java
new file mode 100644
index 0000000..f237342
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TTLExecutor.java
@@ -0,0 +1,75 @@
+/*
+ * 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.RedisDataType;
+import org.apache.geode.redis.internal.RegionProvider;
+
+import java.util.List;
+
+public class TTLExecutor extends AbstractExecutor implements Extendable {
+
+  private final int NOT_EXISTS = -2;
+
+  private final int NO_TIMEOUT = -1;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), getArgsError()));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+    RegionProvider rC = context.getRegionProvider();
+    boolean exists = false;
+    RedisDataType val = rC.getRedisDataType(key);
+    if (val != null)
+      exists = true;
+
+    if (!exists) {
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_EXISTS));
+      return;
+    }
+    long ttl = rC.getExpirationDelayMillis(key);
+
+    if (ttl == 0L) {
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NO_TIMEOUT));
+      return;
+    }
+
+    if (!timeUnitMillis())
+      ttl = ttl / millisInSecond;
+
+    command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), ttl));
+  }
+
+  protected boolean timeUnitMillis() {
+    return false;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.TTL;
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TimeExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TimeExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TimeExecutor.java
new file mode 100644
index 0000000..4094200
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TimeExecutor.java
@@ -0,0 +1,48 @@
+/*
+ * 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 io.netty.buffer.ByteBuf;
+import org.apache.geode.redis.internal.Coder;
+import org.apache.geode.redis.internal.Command;
+import org.apache.geode.redis.internal.ExecutionHandlerContext;
+
+public class TimeExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    long timeStamp = System.currentTimeMillis();
+    long seconds = timeStamp / 1000;
+    long microSeconds = (timeStamp - (seconds * 1000)) * 1000;
+    byte[] secAr = Coder.longToBytes(seconds);
+    byte[] micAr = Coder.longToBytes(microSeconds);
+
+    ByteBuf response = context.getByteBufAllocator().buffer(50);
+    response.writeByte(Coder.ARRAY_ID);
+    response.writeByte(50); // #2
+    response.writeBytes(Coder.CRLFar);
+    response.writeByte(Coder.BULK_STRING_ID);
+    response.writeBytes(Coder.intToBytes(secAr.length));
+    response.writeBytes(Coder.CRLFar);
+    response.writeBytes(secAr);
+    response.writeBytes(Coder.CRLFar);
+    response.writeByte(Coder.BULK_STRING_ID);
+    response.writeBytes(Coder.intToBytes(micAr.length));
+    response.writeBytes(Coder.CRLFar);
+    response.writeBytes(micAr);
+    response.writeBytes(Coder.CRLFar);
+    command.setResponse(response);
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TypeExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TypeExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TypeExecutor.java
new file mode 100644
index 0000000..f6a0313
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/TypeExecutor.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 org.apache.geode.redis.internal.RedisDataType;
+
+import java.util.List;
+
+public class TypeExecutor 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.TYPE));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    RedisDataType type = context.getRegionProvider().getRedisDataType(key);
+
+    if (type == null)
+      command.setResponse(Coder.getBulkStringResponse(context.getByteBufAllocator(), "none"));
+    else
+      command
+          .setResponse(Coder.getBulkStringResponse(context.getByteBufAllocator(), type.toString()));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/UnkownExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/UnkownExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/UnkownExecutor.java
new file mode 100644
index 0000000..d5c2bba
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/UnkownExecutor.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+public class UnkownExecutor extends AbstractExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    command.setResponse(
+        Coder.getErrorResponse(context.getByteBufAllocator(), RedisConstants.ERROR_UNKOWN_COMMAND));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HDelExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HDelExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HDelExecutor.java
new file mode 100644
index 0000000..c034334
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HDelExecutor.java
@@ -0,0 +1,65 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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 HDelExecutor extends HashExecutor {
+
+  private final int START_FIELDS_INDEX = 2;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HDEL));
+      return;
+    }
+
+    int numDeleted = 0;
+
+    ByteArrayWrapper key = command.getKey();
+
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion = getRegion(context, key);
+
+    if (keyRegion == null) {
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), numDeleted));
+      return;
+    }
+
+
+    for (int i = START_FIELDS_INDEX; i < commandElems.size(); i++) {
+      ByteArrayWrapper field = new ByteArrayWrapper(commandElems.get(i));
+      Object oldValue = keyRegion.remove(field);
+      if (oldValue != null)
+        numDeleted++;
+    }
+    if (keyRegion.isEmpty()) {
+      context.getRegionProvider().removeKey(key, RedisDataType.REDIS_HASH);
+    }
+    command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), numDeleted));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HExistsExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HExistsExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HExistsExecutor.java
new file mode 100644
index 0000000..e1eb0e7
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HExistsExecutor.java
@@ -0,0 +1,64 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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 HExistsExecutor extends HashExecutor {
+
+  private final int NOT_EXISTS = 0;
+
+  private final int EXISTS = 1;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HEXISTS));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion = getRegion(context, key);
+
+    if (keyRegion == null) {
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_EXISTS));
+      return;
+    }
+
+    byte[] byteField = commandElems.get(FIELD_INDEX);
+    ByteArrayWrapper field = new ByteArrayWrapper(byteField);
+
+    boolean hasField = keyRegion.containsKey(field);
+
+    if (hasField)
+      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/hash/HGetAllExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HGetAllExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HGetAllExecutor.java
new file mode 100644
index 0000000..99138de
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HGetAllExecutor.java
@@ -0,0 +1,62 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public class HGetAllExecutor extends HashExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HGETALL));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion = getRegion(context, key);
+
+    if (keyRegion == null) {
+      command.setResponse(Coder.getEmptyArrayResponse(context.getByteBufAllocator()));
+      return;
+    }
+
+    Collection<Map.Entry<ByteArrayWrapper, ByteArrayWrapper>> entries =
+        new ArrayList(keyRegion.entrySet()); // This creates a CopyOnRead behavior
+
+    if (entries.isEmpty()) {
+      command.setResponse(Coder.getEmptyArrayResponse(context.getByteBufAllocator()));
+      return;
+    }
+
+    command.setResponse(Coder.getKeyValArrayResponse(context.getByteBufAllocator(), entries));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HGetExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HGetExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HGetExecutor.java
new file mode 100644
index 0000000..858fe80
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HGetExecutor.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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 HGetExecutor extends HashExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HGET));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion = getRegion(context, key);
+
+    if (keyRegion == null) {
+      command.setResponse(Coder.getNilResponse(context.getByteBufAllocator()));
+      return;
+    }
+
+    byte[] byteField = commandElems.get(FIELD_INDEX);
+    ByteArrayWrapper field = new ByteArrayWrapper(byteField);
+
+    ByteArrayWrapper valueWrapper = keyRegion.get(field);
+
+    if (valueWrapper != null) {
+      command.setResponse(
+          Coder.getBulkStringResponse(context.getByteBufAllocator(), valueWrapper.toBytes()));
+    } else
+      command.setResponse(Coder.getNilResponse(context.getByteBufAllocator()));
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByExecutor.java
new file mode 100644
index 0000000..faf9945
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByExecutor.java
@@ -0,0 +1,111 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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 HIncrByExecutor extends HashExecutor {
+
+  private final String ERROR_FIELD_NOT_USABLE = "The value at this field is not an integer";
+
+  private final String ERROR_INCREMENT_NOT_USABLE = "The increment on this key must be numeric";
+
+  private final String ERROR_OVERFLOW = "This incrementation cannot be performed due to overflow";
+
+  private final int FIELD_INDEX = 2;
+
+  private final int INCREMENT_INDEX = 3;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 4) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HINCRBY));
+      return;
+    }
+
+    byte[] incrArray = commandElems.get(INCREMENT_INDEX);
+    long increment;
+
+    try {
+      increment = Coder.bytesToLong(incrArray);
+    } catch (NumberFormatException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_INCREMENT_NOT_USABLE));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion =
+        getOrCreateRegion(context, key, RedisDataType.REDIS_HASH);
+
+    byte[] byteField = commandElems.get(FIELD_INDEX);
+    ByteArrayWrapper field = new ByteArrayWrapper(byteField);
+
+    /*
+     * Put incrememnt as value if field doesn't exist
+     */
+
+    ByteArrayWrapper oldValue = keyRegion.get(field);
+
+    if (oldValue == null) {
+      keyRegion.put(field, new ByteArrayWrapper(incrArray));
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), increment));
+      return;
+    }
+
+    /*
+     * If the field did exist then increment the field
+     */
+
+    long value;
+
+    try {
+      value = Long.parseLong(oldValue.toString());
+    } catch (NumberFormatException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_FIELD_NOT_USABLE));
+      return;
+    }
+
+    /*
+     * Check for overflow
+     */
+    if ((value >= 0 && increment > (Long.MAX_VALUE - value))
+        || (value <= 0 && increment < (Long.MIN_VALUE - value))) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_OVERFLOW));
+      return;
+    }
+
+    value += increment;
+    // String newValue = String.valueOf(value);
+
+    keyRegion.put(field, new ByteArrayWrapper(Coder.longToBytes(value)));
+
+    command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), value));
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByFloatExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByFloatExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByFloatExecutor.java
new file mode 100644
index 0000000..3be182e
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HIncrByFloatExecutor.java
@@ -0,0 +1,104 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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 HIncrByFloatExecutor extends HashExecutor {
+
+  private final String ERROR_FIELD_NOT_USABLE =
+      "The value at this field cannot be incremented numerically because it is not a float";
+
+  private final String ERROR_INCREMENT_NOT_USABLE =
+      "The increment on this key must be floating point numeric";
+
+  private final int FIELD_INDEX = 2;
+
+  private final int INCREMENT_INDEX = 3;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 4) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HINCRBYFLOAT));
+      return;
+    }
+
+    byte[] incrArray = commandElems.get(INCREMENT_INDEX);
+    Double increment;
+
+    try {
+      increment = Coder.bytesToDouble(incrArray);
+    } catch (NumberFormatException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_INCREMENT_NOT_USABLE));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion =
+        getOrCreateRegion(context, key, RedisDataType.REDIS_HASH);
+
+    byte[] byteField = commandElems.get(FIELD_INDEX);
+    ByteArrayWrapper field = new ByteArrayWrapper(byteField);
+
+    /*
+     * Put incrememnt as value if field doesn't exist
+     */
+
+    ByteArrayWrapper oldValue = keyRegion.get(field);
+
+    if (oldValue == null) {
+      keyRegion.put(field, new ByteArrayWrapper(incrArray));
+      command.setResponse(Coder.getBulkStringResponse(context.getByteBufAllocator(), increment));
+      return;
+    }
+
+    /*
+     * If the field did exist then increment the field
+     */
+    String valueS = oldValue.toString();
+    if (valueS.contains(" ")) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_FIELD_NOT_USABLE));
+      return;
+    }
+    Double value;
+
+    try {
+      value = Coder.stringToDouble(valueS);
+    } catch (NumberFormatException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_FIELD_NOT_USABLE));
+      return;
+    }
+
+    value += increment;
+    keyRegion.put(field, new ByteArrayWrapper(Coder.doubleToBytes(value)));
+    command.setResponse(Coder.getBulkStringResponse(context.getByteBufAllocator(), value));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HKeysExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HKeysExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HKeysExecutor.java
new file mode 100644
index 0000000..01ac817
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HKeysExecutor.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class HKeysExecutor extends HashExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 2) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HKEYS));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion = getRegion(context, key);
+
+    if (keyRegion == null) {
+      command.setResponse(Coder.getEmptyArrayResponse(context.getByteBufAllocator()));
+      return;
+    }
+
+    Set<ByteArrayWrapper> keys = new HashSet(keyRegion.keySet());
+
+    if (keys.isEmpty()) {
+      command.setResponse(Coder.getEmptyArrayResponse(context.getByteBufAllocator()));
+      return;
+    }
+
+    // String response = getBulkStringArrayResponse(keys);
+
+    command.setResponse(Coder.getBulkStringArrayResponse(context.getByteBufAllocator(), keys));
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HLenExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HLenExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HLenExecutor.java
new file mode 100644
index 0000000..945a715
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HLenExecutor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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 HLenExecutor extends HashExecutor {
+
+  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.HLEN));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion = getRegion(context, key);
+
+    if (keyRegion == null) {
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_EXISTS));
+      return;
+    }
+
+    final int regionSize = keyRegion.size();
+
+    command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), regionSize));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMGetExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMGetExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMGetExecutor.java
new file mode 100644
index 0000000..132e7d5
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMGetExecutor.java
@@ -0,0 +1,71 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class HMGetExecutor extends HashExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HMGET));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion = getRegion(context, key);
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+
+    if (keyRegion == null) {
+      command.setResponse(
+          Coder.getArrayOfNils(context.getByteBufAllocator(), commandElems.size() - 2));
+      return;
+    }
+
+    ArrayList<ByteArrayWrapper> fields = new ArrayList<ByteArrayWrapper>();
+    for (int i = 2; i < commandElems.size(); i++) {
+      byte[] fieldArray = commandElems.get(i);
+      ByteArrayWrapper field = new ByteArrayWrapper(fieldArray);
+      fields.add(field);
+    }
+
+    Map<ByteArrayWrapper, ByteArrayWrapper> results = keyRegion.getAll(fields);
+
+    ArrayList<ByteArrayWrapper> values = new ArrayList<ByteArrayWrapper>();
+
+    /*
+     * This is done to preserve order in the output
+     */
+    for (ByteArrayWrapper field : fields)
+      values.add(results.get(field));
+
+    command.setResponse(Coder.getBulkStringArrayResponse(context.getByteBufAllocator(), values));
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMSetExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMSetExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMSetExecutor.java
new file mode 100644
index 0000000..7cbe1ba
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HMSetExecutor.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class HMSetExecutor extends HashExecutor {
+
+  private final String SUCCESS = "OK";
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3 || commandElems.size() % 2 == 1) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HMSET));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion =
+        getOrCreateRegion(context, key, RedisDataType.REDIS_HASH);
+
+    Map<ByteArrayWrapper, ByteArrayWrapper> map = new HashMap<ByteArrayWrapper, ByteArrayWrapper>();
+    for (int i = 2; i < commandElems.size(); i += 2) {
+      byte[] fieldArray = commandElems.get(i);
+      ByteArrayWrapper field = new ByteArrayWrapper(fieldArray);
+      byte[] value = commandElems.get(i + 1);
+      map.put(field, new ByteArrayWrapper(value));
+    }
+
+    keyRegion.putAll(map);
+
+    command.setResponse(Coder.getSimpleStringResponse(context.getByteBufAllocator(), SUCCESS));
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HScanExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HScanExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HScanExecutor.java
new file mode 100644
index 0000000..1a8dddc
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HScanExecutor.java
@@ -0,0 +1,166 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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;
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+import org.apache.geode.redis.internal.RedisDataType;
+import org.apache.geode.redis.internal.executor.AbstractScanExecutor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class HScanExecutor extends AbstractScanExecutor {
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 3) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.HSCAN));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+    @SuppressWarnings("unchecked")
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion =
+        (Region<ByteArrayWrapper, ByteArrayWrapper>) context.getRegionProvider().getRegion(key);
+    checkDataType(key, RedisDataType.REDIS_HASH, context);
+    if (keyRegion == null) {
+      command.setResponse(
+          Coder.getScanResponse(context.getByteBufAllocator(), new ArrayList<String>()));
+      return;
+    }
+    byte[] cAr = commandElems.get(2);
+    String cursorString = Coder.bytesToString(cAr);
+
+    int cursor = 0;
+    Pattern matchPattern = null;
+    String globMatchPattern = null;
+    int count = DEFUALT_COUNT;
+    try {
+      cursor = Integer.parseInt(cursorString);
+    } catch (NumberFormatException e) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_CURSOR));
+      return;
+    }
+    if (cursor < 0) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_CURSOR));
+      return;
+    }
+
+    if (commandElems.size() > 4) {
+      try {
+        byte[] bytes = commandElems.get(3);
+        String tmp = Coder.bytesToString(bytes);
+        if (tmp.equalsIgnoreCase("MATCH")) {
+          bytes = commandElems.get(4);
+          globMatchPattern = Coder.bytesToString(bytes);
+        } else if (tmp.equalsIgnoreCase("COUNT")) {
+          bytes = commandElems.get(4);
+          count = Coder.bytesToInt(bytes);
+        }
+      } catch (NumberFormatException e) {
+        command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_COUNT));
+        return;
+      }
+    }
+
+    if (commandElems.size() > 6) {
+      try {
+        byte[] bytes = commandElems.get(5);
+        String tmp = Coder.bytesToString(bytes);
+        if (tmp.equalsIgnoreCase("MATCH")) {
+          bytes = commandElems.get(6);
+          globMatchPattern = Coder.bytesToString(bytes);
+        } else if (tmp.equalsIgnoreCase("COUNT")) {
+          bytes = commandElems.get(6);
+          count = Coder.bytesToInt(bytes);
+        }
+      } catch (NumberFormatException e) {
+        command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_COUNT));
+        return;
+      }
+    }
+
+    if (count < 0) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_COUNT));
+      return;
+    }
+
+    try {
+      matchPattern = convertGlobToRegex(globMatchPattern);
+    } catch (PatternSyntaxException e) {
+      command.setResponse(
+          Coder.getErrorResponse(context.getByteBufAllocator(), RedisConstants.ERROR_ILLEGAL_GLOB));
+      return;
+    }
+
+    List<Object> returnList =
+        getIteration(new HashSet(keyRegion.entrySet()), matchPattern, count, cursor);
+
+    command.setResponse(Coder.getScanResponse(context.getByteBufAllocator(), returnList));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  protected List<Object> getIteration(Collection<?> list, Pattern matchPattern, int count,
+      int cursor) {
+    List<Object> returnList = new ArrayList<Object>();
+    int size = list.size();
+    int beforeCursor = 0;
+    int numElements = 0;
+    int i = -1;
+    for (Entry<ByteArrayWrapper, ByteArrayWrapper> entry : (Collection<Entry<ByteArrayWrapper, ByteArrayWrapper>>) list) {
+      ByteArrayWrapper key = entry.getKey();
+      ByteArrayWrapper value = entry.getValue();
+      i++;
+      if (beforeCursor < cursor) {
+        beforeCursor++;
+        continue;
+      } else if (numElements < count) {
+        if (matchPattern != null) {
+          if (matchPattern.matcher(key.toString()).matches()) {
+            returnList.add(key);
+            returnList.add(value);
+            numElements++;
+          }
+        } else {
+          returnList.add(key);
+          returnList.add(value);
+          numElements++;
+        }
+      } else
+        break;
+    }
+
+    if (i == size - 1)
+      returnList.add(0, String.valueOf(0));
+    else
+      returnList.add(0, String.valueOf(i));
+    return returnList;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetExecutor.java
new file mode 100644
index 0000000..64952db
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetExecutor.java
@@ -0,0 +1,77 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.cache.Region;
+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.RedisDataType;
+
+import java.util.List;
+
+public class HSetExecutor extends HashExecutor implements Extendable {
+
+  private final int EXISTING_FIELD = 0;
+
+  private final int NEW_FIELD = 1;
+
+  private final int VALUE_INDEX = 3;
+
+  @Override
+  public void executeCommand(Command command, ExecutionHandlerContext context) {
+    List<byte[]> commandElems = command.getProcessedCommand();
+
+    if (commandElems.size() < 4) {
+      command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), getArgsError()));
+      return;
+    }
+
+    ByteArrayWrapper key = command.getKey();
+
+    Region<ByteArrayWrapper, ByteArrayWrapper> keyRegion =
+        getOrCreateRegion(context, key, RedisDataType.REDIS_HASH);
+
+    byte[] byteField = commandElems.get(FIELD_INDEX);
+    ByteArrayWrapper field = new ByteArrayWrapper(byteField);
+
+    byte[] value = commandElems.get(VALUE_INDEX);
+
+    Object oldValue;
+
+    if (onlySetOnAbsent())
+      oldValue = keyRegion.putIfAbsent(field, new ByteArrayWrapper(value));
+    else
+      oldValue = keyRegion.put(field, new ByteArrayWrapper(value));
+
+    if (oldValue == null)
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NEW_FIELD));
+    else
+      command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), EXISTING_FIELD));
+
+  }
+
+  protected boolean onlySetOnAbsent() {
+    return false;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.HSET;
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetNXExecutor.java
----------------------------------------------------------------------
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetNXExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetNXExecutor.java
new file mode 100644
index 0000000..5312527
--- /dev/null
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/HSetNXExecutor.java
@@ -0,0 +1,31 @@
+/*
+ * 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.hash;
+
+import org.apache.geode.redis.internal.RedisConstants.ArityDef;
+
+
+public class HSetNXExecutor extends HSetExecutor {
+
+  @Override
+  protected boolean onlySetOnAbsent() {
+    return true;
+  }
+
+  @Override
+  public String getArgsError() {
+    return ArityDef.HSETNX;
+  }
+}


Mime
View raw message