Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 3E46D200C3B for ; Fri, 10 Feb 2017 22:34:09 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 3CD51160B5C; Fri, 10 Feb 2017 21:34:09 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 04AED160B4E for ; Fri, 10 Feb 2017 22:34:05 +0100 (CET) Received: (qmail 45560 invoked by uid 500); 10 Feb 2017 21:34:05 -0000 Mailing-List: contact commits-help@geode.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.apache.org Delivered-To: mailing list commits@geode.apache.org Received: (qmail 44744 invoked by uid 99); 10 Feb 2017 21:34:04 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Feb 2017 21:34:04 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5F9BBE080B; Fri, 10 Feb 2017 21:34:04 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: udo@apache.org To: commits@geode.apache.org Date: Fri, 10 Feb 2017 21:34:13 -0000 Message-Id: In-Reply-To: <13fc922022504e0db43236de3997302b@git.apache.org> References: <13fc922022504e0db43236de3997302b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [10/21] geode git commit: GEODE-2449: Moved Redis out of core with minimal Extension work added archived-at: Fri, 10 Feb 2017 21:34:09 -0000 http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/DoubleWrapper.java ---------------------------------------------------------------------- diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/DoubleWrapper.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/DoubleWrapper.java new file mode 100644 index 0000000..460a330 --- /dev/null +++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/DoubleWrapper.java @@ -0,0 +1,76 @@ +/* + * 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.DataSerializable; +import org.apache.geode.DataSerializer; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * This is a wrapper class for doubles, similar to {@link ByteArrayWrapper} + * + * + */ +public class DoubleWrapper implements DataSerializable, Comparable { + + private static final long serialVersionUID = 6946858357297398633L; + + public Double score; + private String toString; + + public DoubleWrapper() {} + + public DoubleWrapper(Double dubs) { + this.score = dubs; + } + + @Override + public void toData(DataOutput out) throws IOException { + DataSerializer.writeDouble(score, out); + } + + @Override + public void fromData(DataInput in) throws IOException, ClassNotFoundException { + this.score = DataSerializer.readDouble(in); + } + + @Override + public int compareTo(Object arg0) { + Double other; + if (arg0 instanceof DoubleWrapper) { + other = ((DoubleWrapper) arg0).score; + } else if (arg0 instanceof Double) { + other = (Double) arg0; + } else + return 0; + Double diff = this.score - other; + if (diff > 0) + return 1; + else if (diff < 0) + return -1; + else + return 0; + } + + public String toString() { + if (this.toString == null) + this.toString = Coder.doubleToString(score); + return this.toString; + } + +} http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/ExecutionHandlerContext.java ---------------------------------------------------------------------- diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/ExecutionHandlerContext.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/ExecutionHandlerContext.java new file mode 100644 index 0000000..8202b10 --- /dev/null +++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/ExecutionHandlerContext.java @@ -0,0 +1,392 @@ +/* + * 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 io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.codec.DecoderException; +import io.netty.util.concurrent.EventExecutor; +import org.apache.geode.LogWriter; +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.CacheClosedException; +import org.apache.geode.cache.CacheTransactionManager; +import org.apache.geode.cache.RegionDestroyedException; +import org.apache.geode.cache.TransactionException; +import org.apache.geode.cache.TransactionId; +import org.apache.geode.cache.UnsupportedOperationInTransactionException; +import org.apache.geode.cache.query.QueryInvocationTargetException; +import org.apache.geode.cache.query.RegionNotFoundException; +import org.apache.geode.redis.GeodeRedisServiceImpl; +import org.apache.geode.redis.internal.executor.transactions.TransactionExecutor; + +import java.io.IOException; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * This class extends {@link ChannelInboundHandlerAdapter} from Netty and it is the last part of the + * channel pipeline. The {@link ByteToCommandDecoder} forwards a {@link Command} to this class which + * executes it and sends the result back to the client. Additionally, all exception handling is done + * by this class. + *

+ * Besides being part of Netty's pipeline, this class also serves as a context to the execution of a + * command. It abstracts transactions, provides access to the {@link RegionProvider} and anything + * else an executing {@link Command} may need. + * + * + */ +public class ExecutionHandlerContext extends ChannelInboundHandlerAdapter { + + private static final int WAIT_REGION_DSTRYD_MILLIS = 100; + private static final int MAXIMUM_NUM_RETRIES = (1000 * 60) / WAIT_REGION_DSTRYD_MILLIS; // 60 + // seconds + // total + + private final Cache cache; + private final GeodeRedisServiceImpl server; + private final LogWriter logger; + private final Channel channel; + private final AtomicBoolean needChannelFlush; + private final Runnable flusher; + private final EventExecutor lastExecutor; + private final ByteBufAllocator byteBufAllocator; + /** + * TransactionId for any transactions started by this client + */ + private TransactionId transactionID; + + /** + * Queue of commands for a given transaction + */ + private Queue transactionQueue; + private final RegionProvider regionProvider; + private final byte[] authPwd; + + private boolean isAuthenticated; + + /** + * Default constructor for execution contexts. + * + * @param ch Channel used by this context, should be one to one + * @param cache The Geode cache instance of this vm + * @param regionProvider The region provider of this context + * @param server Instance of the server it is attached to, only used so that any execution can + * initiate a shutdwon + * @param pwd Authentication password for each context, can be null + */ + public ExecutionHandlerContext(Channel ch, Cache cache, RegionProvider regionProvider, + GeodeRedisServiceImpl server, byte[] pwd) { + if (ch == null || cache == null || regionProvider == null || server == null) + throw new IllegalArgumentException("Only the authentication password may be null"); + this.cache = cache; + this.server = server; + this.logger = cache.getLogger(); + this.channel = ch; + this.needChannelFlush = new AtomicBoolean(false); + this.flusher = new Runnable() { + + @Override + public void run() { + flushChannel(); + } + + }; + this.lastExecutor = channel.pipeline().lastContext().executor(); + this.byteBufAllocator = channel.alloc(); + this.transactionID = null; + this.transactionQueue = null; // Lazy + this.regionProvider = regionProvider; + this.authPwd = pwd; + this.isAuthenticated = pwd != null ? false : true; + } + + private void flushChannel() { + while (needChannelFlush.getAndSet(false)) { + channel.flush(); + } + } + + private void writeToChannel(ByteBuf message) { + channel.write(message, channel.voidPromise()); + if (!needChannelFlush.getAndSet(true)) { + this.lastExecutor.execute(flusher); + } + } + + /** + * This will handle the execution of received commands + */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + Command command = (Command) msg; + executeCommand(ctx, command); + } + + /** + * Exception handler for the entire pipeline + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + if (cause instanceof IOException) { + channelInactive(ctx); + return; + } + ByteBuf response = getExceptionResponse(ctx, cause); + writeToChannel(response); + } + + private ByteBuf getExceptionResponse(ChannelHandlerContext ctx, Throwable cause) { + ByteBuf response; + if (cause instanceof RedisDataTypeMismatchException) + response = Coder.getWrongTypeResponse(this.byteBufAllocator, cause.getMessage()); + else if (cause instanceof DecoderException + && cause.getCause() instanceof RedisCommandParserException) + response = + Coder.getErrorResponse(this.byteBufAllocator, RedisConstants.PARSING_EXCEPTION_MESSAGE); + else if (cause instanceof RegionCreationException) { + this.logger.error(cause); + response = + Coder.getErrorResponse(this.byteBufAllocator, RedisConstants.ERROR_REGION_CREATION); + } else if (cause instanceof InterruptedException || cause instanceof CacheClosedException) + response = + Coder.getErrorResponse(this.byteBufAllocator, RedisConstants.SERVER_ERROR_SHUTDOWN); + else if (cause instanceof IllegalStateException) { + response = Coder.getErrorResponse(this.byteBufAllocator, cause.getMessage()); + } else { + if (this.logger.errorEnabled()) + this.logger.error("GeodeRedisServiceImpl-Unexpected error handler for " + ctx.channel(), + cause); + response = Coder.getErrorResponse(this.byteBufAllocator, RedisConstants.SERVER_ERROR_MESSAGE); + } + return response; + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + if (logger.fineEnabled()) + logger.fine("GeodeRedisServiceImpl-Connection closing with " + ctx.channel().remoteAddress()); + ctx.channel().close(); + ctx.close(); + } + + private void executeCommand(ChannelHandlerContext ctx, Command command) throws Exception { + RedisCommandType type = command.getCommandType(); + Executor exec = type.getExecutor(); + if (isAuthenticated) { + if (type == RedisCommandType.SHUTDOWN) { + this.server.stop(); + return; + } + if (hasTransaction() && !(exec instanceof TransactionExecutor)) + executeWithTransaction(ctx, exec, command); + else + executeWithoutTransaction(exec, command); + + if (hasTransaction() && command.getCommandType() != RedisCommandType.MULTI) { + writeToChannel( + Coder.getSimpleStringResponse(this.byteBufAllocator, RedisConstants.COMMAND_QUEUED)); + } else { + ByteBuf response = command.getResponse(); + writeToChannel(response); + } + } else if (type == RedisCommandType.QUIT) { + exec.executeCommand(command, this); + ByteBuf response = command.getResponse(); + writeToChannel(response); + channelInactive(ctx); + } else if (type == RedisCommandType.AUTH) { + exec.executeCommand(command, this); + ByteBuf response = command.getResponse(); + writeToChannel(response); + } else { + ByteBuf r = Coder.getNoAuthResponse(this.byteBufAllocator, RedisConstants.ERROR_NOT_AUTH); + writeToChannel(r); + } + } + + /** + * Private helper method to execute a command without a transaction, done for special exception + * handling neatness + * + * @param exec Executor to use + * @param command Command to execute + * @throws Exception Throws exception if exception is from within execution and not to be handled + */ + private void executeWithoutTransaction(final Executor exec, Command command) throws Exception { + Exception cause = null; + for (int i = 0; i < MAXIMUM_NUM_RETRIES; i++) { + try { + exec.executeCommand(command, this); + return; + } catch (Exception e) { + cause = e; + if (e instanceof RegionDestroyedException || e instanceof RegionNotFoundException + || e.getCause() instanceof QueryInvocationTargetException) + Thread.sleep(WAIT_REGION_DSTRYD_MILLIS); + } + } + throw cause; + } + + private void executeWithTransaction(ChannelHandlerContext ctx, final Executor exec, + Command command) throws Exception { + CacheTransactionManager txm = cache.getCacheTransactionManager(); + TransactionId transactionId = getTransactionID(); + txm.resume(transactionId); + try { + exec.executeCommand(command, this); + } catch (UnsupportedOperationInTransactionException e) { + command.setResponse(Coder.getErrorResponse(this.byteBufAllocator, + RedisConstants.ERROR_UNSUPPORTED_OPERATION_IN_TRANSACTION)); + } catch (TransactionException e) { + command.setResponse(Coder.getErrorResponse(this.byteBufAllocator, + RedisConstants.ERROR_TRANSACTION_EXCEPTION)); + } catch (Exception e) { + ByteBuf response = getExceptionResponse(ctx, e); + command.setResponse(response); + } + getTransactionQueue().add(command); + transactionId = txm.suspend(); + setTransactionID(transactionId); + } + + /** + * Get the current transacationId + * + * @return The current transactionId, null if one doesn't exist + */ + public TransactionId getTransactionID() { + return this.transactionID; + } + + /** + * Check if client has transaction + * + * @return True if client has transaction, false otherwise + */ + public boolean hasTransaction() { + return transactionID != null; + } + + /** + * Setter method for transaction + * + * @param id TransactionId of current transaction for client + */ + public void setTransactionID(TransactionId id) { + this.transactionID = id; + } + + /** + * Reset the transaction of client + */ + public void clearTransaction() { + this.transactionID = null; + if (this.transactionQueue != null) { + for (Command c : this.transactionQueue) { + ByteBuf r = c.getResponse(); + if (r != null) + r.release(); + } + this.transactionQueue.clear(); + } + } + + /** + * Getter for transaction command queue + * + * @return Command queue + */ + public Queue getTransactionQueue() { + if (this.transactionQueue == null) + this.transactionQueue = new ConcurrentLinkedQueue(); + return this.transactionQueue; + } + + /** + * {@link ByteBuf} allocator for this context. All executors must use this pooled allocator as + * opposed to having unpooled buffers for maximum performance + * + * @return allocator instance + */ + public ByteBufAllocator getByteBufAllocator() { + return this.byteBufAllocator; + } + + /** + * Gets the provider of Regions + * + * @return Provider + */ + public RegionProvider getRegionProvider() { + return this.regionProvider; + } + + /** + * Getter for manager to allow pausing and resuming transactions + * + * @return Instance + */ + public CacheTransactionManager getCacheTransactionManager() { + return this.cache.getCacheTransactionManager(); + } + + /** + * Getter for logger + * + * @return instance + */ + public LogWriter getLogger() { + return this.cache.getLogger(); + } + + /** + * Get the channel for this context + * + * @return instance + * + * public Channel getChannel() { return this.channel; } + */ + + /** + * Get the authentication password, this will be same server wide. It is exposed here as opposed + * to {@link GeodeRedisServiceImpl}. + * + * @return password + */ + public byte[] getAuthPwd() { + return this.authPwd; + } + + /** + * Checker if user has authenticated themselves + * + * @return True if no authentication required or authentication complete, false otherwise + */ + public boolean isAuthenticated() { + return this.isAuthenticated; + } + + /** + * Lets this context know the authentication is complete + */ + public void setAuthenticationVerified() { + this.isAuthenticated = true; + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/Executor.java ---------------------------------------------------------------------- diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/Executor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/Executor.java new file mode 100644 index 0000000..7698535 --- /dev/null +++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/Executor.java @@ -0,0 +1,34 @@ +/* + * 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; + + +/** + * Interface for executors of a {@link Command} + * + * + */ +public interface Executor { + + /** + * This method executes the command and sets the response. Any runtime errors from this execution + * should be handled by caller to ensure the client gets a response + * + * @param command The command to be executed + * @param context The execution context by which this command is to be executed + */ + 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/Extendable.java ---------------------------------------------------------------------- diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/Extendable.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/Extendable.java new file mode 100644 index 0000000..ed36030 --- /dev/null +++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/Extendable.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; + +/** + * This defines a command that can be extended, and there may need some level of abstraction + * + * + */ +public interface Extendable { + + /** + * Getter for error message in case of argument arity mismatch + * + * @return Error string + */ + public String getArgsError(); + +} http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandParserException.java ---------------------------------------------------------------------- diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandParserException.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandParserException.java new file mode 100644 index 0000000..4ec154a --- /dev/null +++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandParserException.java @@ -0,0 +1,42 @@ +/* + * 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; + +/** + * Exception thrown by CommandParser (non-existent class) when a command has illegal syntax + * + * + */ +public class RedisCommandParserException extends Exception { + + private static final long serialVersionUID = 4707944288714910949L; + + public RedisCommandParserException() { + super(); + } + + public RedisCommandParserException(String message) { + super(message); + } + + public RedisCommandParserException(Throwable cause) { + super(cause); + } + + public RedisCommandParserException(String message, Throwable cause) { + super(message, cause); + } + +} http://git-wip-us.apache.org/repos/asf/geode/blob/c6dbc6d4/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java ---------------------------------------------------------------------- diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java new file mode 100644 index 0000000..acacd12 --- /dev/null +++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java @@ -0,0 +1,2896 @@ +/* + * 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.redis.internal.executor.AuthExecutor; +import org.apache.geode.redis.internal.executor.DBSizeExecutor; +import org.apache.geode.redis.internal.executor.DelExecutor; +import org.apache.geode.redis.internal.executor.EchoExecutor; +import org.apache.geode.redis.internal.executor.ExistsExecutor; +import org.apache.geode.redis.internal.executor.ExpireAtExecutor; +import org.apache.geode.redis.internal.executor.ExpireExecutor; +import org.apache.geode.redis.internal.executor.FlushAllExecutor; +import org.apache.geode.redis.internal.executor.KeysExecutor; +import org.apache.geode.redis.internal.executor.PExpireAtExecutor; +import org.apache.geode.redis.internal.executor.PExpireExecutor; +import org.apache.geode.redis.internal.executor.PTTLExecutor; +import org.apache.geode.redis.internal.executor.PersistExecutor; +import org.apache.geode.redis.internal.executor.PingExecutor; +import org.apache.geode.redis.internal.executor.QuitExecutor; +import org.apache.geode.redis.internal.executor.ScanExecutor; +import org.apache.geode.redis.internal.executor.ShutDownExecutor; +import org.apache.geode.redis.internal.executor.TTLExecutor; +import org.apache.geode.redis.internal.executor.TimeExecutor; +import org.apache.geode.redis.internal.executor.TypeExecutor; +import org.apache.geode.redis.internal.executor.UnkownExecutor; +import org.apache.geode.redis.internal.executor.hash.HDelExecutor; +import org.apache.geode.redis.internal.executor.hash.HExistsExecutor; +import org.apache.geode.redis.internal.executor.hash.HGetAllExecutor; +import org.apache.geode.redis.internal.executor.hash.HGetExecutor; +import org.apache.geode.redis.internal.executor.hash.HIncrByExecutor; +import org.apache.geode.redis.internal.executor.hash.HIncrByFloatExecutor; +import org.apache.geode.redis.internal.executor.hash.HKeysExecutor; +import org.apache.geode.redis.internal.executor.hash.HLenExecutor; +import org.apache.geode.redis.internal.executor.hash.HMGetExecutor; +import org.apache.geode.redis.internal.executor.hash.HMSetExecutor; +import org.apache.geode.redis.internal.executor.hash.HScanExecutor; +import org.apache.geode.redis.internal.executor.hash.HSetExecutor; +import org.apache.geode.redis.internal.executor.hash.HSetNXExecutor; +import org.apache.geode.redis.internal.executor.hash.HValsExecutor; +import org.apache.geode.redis.internal.executor.hll.PFAddExecutor; +import org.apache.geode.redis.internal.executor.hll.PFCountExecutor; +import org.apache.geode.redis.internal.executor.hll.PFMergeExecutor; +import org.apache.geode.redis.internal.executor.list.LIndexExecutor; +import org.apache.geode.redis.internal.executor.list.LInsertExecutor; +import org.apache.geode.redis.internal.executor.list.LLenExecutor; +import org.apache.geode.redis.internal.executor.list.LPopExecutor; +import org.apache.geode.redis.internal.executor.list.LPushExecutor; +import org.apache.geode.redis.internal.executor.list.LPushXExecutor; +import org.apache.geode.redis.internal.executor.list.LRangeExecutor; +import org.apache.geode.redis.internal.executor.list.LRemExecutor; +import org.apache.geode.redis.internal.executor.list.LSetExecutor; +import org.apache.geode.redis.internal.executor.list.LTrimExecutor; +import org.apache.geode.redis.internal.executor.list.RPopExecutor; +import org.apache.geode.redis.internal.executor.list.RPushExecutor; +import org.apache.geode.redis.internal.executor.list.RPushXExecutor; +import org.apache.geode.redis.internal.executor.set.SAddExecutor; +import org.apache.geode.redis.internal.executor.set.SCardExecutor; +import org.apache.geode.redis.internal.executor.set.SDiffExecutor; +import org.apache.geode.redis.internal.executor.set.SDiffStoreExecutor; +import org.apache.geode.redis.internal.executor.set.SInterExecutor; +import org.apache.geode.redis.internal.executor.set.SInterStoreExecutor; +import org.apache.geode.redis.internal.executor.set.SIsMemberExecutor; +import org.apache.geode.redis.internal.executor.set.SMembersExecutor; +import org.apache.geode.redis.internal.executor.set.SMoveExecutor; +import org.apache.geode.redis.internal.executor.set.SPopExecutor; +import org.apache.geode.redis.internal.executor.set.SRandMemberExecutor; +import org.apache.geode.redis.internal.executor.set.SRemExecutor; +import org.apache.geode.redis.internal.executor.set.SScanExecutor; +import org.apache.geode.redis.internal.executor.set.SUnionExecutor; +import org.apache.geode.redis.internal.executor.set.SUnionStoreExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZAddExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZCardExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZCountExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZIncrByExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZLexCountExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRangeByLexExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRangeByScoreExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRangeExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRankExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRemExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRemRangeByLexExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRemRangeByRankExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRemRangeByScoreExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRevRangeByScoreExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRevRangeExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZRevRankExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZScanExecutor; +import org.apache.geode.redis.internal.executor.sortedset.ZScoreExecutor; +import org.apache.geode.redis.internal.executor.string.AppendExecutor; +import org.apache.geode.redis.internal.executor.string.BitCountExecutor; +import org.apache.geode.redis.internal.executor.string.BitOpExecutor; +import org.apache.geode.redis.internal.executor.string.BitPosExecutor; +import org.apache.geode.redis.internal.executor.string.DecrByExecutor; +import org.apache.geode.redis.internal.executor.string.DecrExecutor; +import org.apache.geode.redis.internal.executor.string.GetBitExecutor; +import org.apache.geode.redis.internal.executor.string.GetExecutor; +import org.apache.geode.redis.internal.executor.string.GetRangeExecutor; +import org.apache.geode.redis.internal.executor.string.GetSetExecutor; +import org.apache.geode.redis.internal.executor.string.IncrByExecutor; +import org.apache.geode.redis.internal.executor.string.IncrByFloatExecutor; +import org.apache.geode.redis.internal.executor.string.IncrExecutor; +import org.apache.geode.redis.internal.executor.string.MGetExecutor; +import org.apache.geode.redis.internal.executor.string.MSetExecutor; +import org.apache.geode.redis.internal.executor.string.MSetNXExecutor; +import org.apache.geode.redis.internal.executor.string.PSetEXExecutor; +import org.apache.geode.redis.internal.executor.string.SetBitExecutor; +import org.apache.geode.redis.internal.executor.string.SetEXExecutor; +import org.apache.geode.redis.internal.executor.string.SetExecutor; +import org.apache.geode.redis.internal.executor.string.SetNXExecutor; +import org.apache.geode.redis.internal.executor.string.SetRangeExecutor; +import org.apache.geode.redis.internal.executor.string.StrlenExecutor; +import org.apache.geode.redis.internal.executor.transactions.DiscardExecutor; +import org.apache.geode.redis.internal.executor.transactions.ExecExecutor; +import org.apache.geode.redis.internal.executor.transactions.MultiExecutor; +import org.apache.geode.redis.internal.executor.transactions.UnwatchExecutor; +import org.apache.geode.redis.internal.executor.transactions.WatchExecutor; + +/** + * The redis command type used by the server. Each command is directly from the redis protocol and + * calling {@link #getExecutor()} on a type returns the executor class for that command. + * + * + */ +public enum RedisCommandType { + + /*************************************** + *************** Keys ****************** + ***************************************/ + + /** + * AUTH password + *

+ * Authenticate to the server + */ + AUTH { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new AuthExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * DEL key [key ...] + *

+ * Delete a key + */ + DEL { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new DelExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * EXISTS key + *

+ * Determine if a key exists + */ + EXISTS { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ExistsExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * EXPIRE key seconds + *

+ * Set a key's time to live in seconds + */ + EXPIRE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ExpireExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * EXPIREAT key timestamp + *

+ * Set the expiration for a key as a UNIX timestamp + */ + EXPIREAT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ExpireAtExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * FLUSHALL + *

+ * Remove all keys from all databases + */ + FLUSHALL { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new FlushAllExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * FLUSHDB + *

+ * Remove all keys from the current database + *

+ * Same as FLUSHALL for this implementation + */ + FLUSHDB { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new FlushAllExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * KEYS pattern + *

+ * Find all keys matching the given pattern + */ + KEYS { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new KeysExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PERSIST key + *

+ * Remove the expiration from a key + */ + PERSIST { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PersistExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PEXPIRE key milliseconds + *

+ * Set a key's time to live in milliseconds + */ + PEXPIRE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PExpireExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PEXPIREAT key milliseconds-timestamp + *

+ * Set the expiration for a key as a UNIX timestamp specified in milliseconds + */ + PEXPIREAT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PExpireAtExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PTTL key + *

+ * Get the time to live for a key in milliseconds + */ + PTTL { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PTTLExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SCAN cursor [MATCH pattern] [COUNT count] + *

+ * Incrementally iterate the keys space + */ + SCAN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ScanExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * TTL key + *

+ * Get the time to live for a key + */ + TTL { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new TTLExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * TYPE key + *

+ * Determine the type stored at key + */ + TYPE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new TypeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + ************** Strings **************** + ***************************************/ + + /** + * APPEND key value + *

+ * Append a value to a key + */ + APPEND { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new AppendExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * BITCOUNT key start end [start end ...] + *

+ * Count set bits in a string + */ + BITCOUNT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new BitCountExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * BITOP operation destkey key [key ...] + *

+ * Perform bitwise operations between strings + */ + BITOP { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new BitOpExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * BITPOS key bit [start] [end] + *

+ * Find first bit set or clear in a string + */ + BITPOS { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new BitPosExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * DECR key + *

+ * Decrement the integer value of a key by one + */ + DECR { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new DecrExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * DECRBY key decrement + *

+ * Decrement the integer value of a key by the given number + */ + DECRBY { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new DecrByExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * GET key + *

+ * Get the value of a key + */ + GET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new GetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * GETBIT key offset + *

+ * Returns the bit value at offset in the string value stored at key + */ + GETBIT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new GetBitExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * GETRANGE key start end + *

+ * Get a substring of the string stored at a key + */ + GETRANGE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new GetRangeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * GETSET key value + *

+ * Set the string value of a key and return its old value + */ + GETSET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new GetSetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * INCR key + *

+ * Increment the integer value of a key by one + */ + INCR { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new IncrExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * INCRBY key increment + *

+ * Increment the integer value of a key by the given amount + */ + INCRBY { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new IncrByExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * INCRBYFLOAT key increment + *

+ * Increment the float value of a key by the given amount + */ + INCRBYFLOAT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new IncrByFloatExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * MGET key [key ...] + *

+ * Get the values of all the given keys + */ + MGET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new MGetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * MSET key value [key value ...] + *

+ * Set multiple keys to multiple values + */ + MSET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new MSetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * MSETNX key value [key value ...] + *

+ * Set multiple keys to multiple values, only if none of the keys exist + */ + MSETNX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new MSetNXExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PSETEX key milliseconds value + *

+ * Set the value and expiration in milliseconds of a key + */ + PSETEX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PSetEXExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SETEX key seconds value + *

+ * Set the value and expiration of a key + */ + SETEX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SetEXExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SET key value [EX seconds] [PX milliseconds] [NX|XX] + *

+ * Set the string value of a key + */ + SET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SETBIT key offset value + *

+ * Sets or clears the bit at offset in the string value stored at key + */ + SETBIT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SetBitExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SETNX key value + *

+ * Set the value of a key, only if the key does not exist + */ + SETNX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SetNXExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SETRANGE key offset value + *

+ * Overwrite part of a string at key starting at the specified offset + */ + SETRANGE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SetRangeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * STRLEN key + *

+ * Get the length of the value stored in a key + */ + STRLEN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new StrlenExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_STRING; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + **************** Hashes *************** + ***************************************/ + /** + * HDEL key field [field ...] + *

+ * Delete one or more hash fields + */ + HDEL { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HDelExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HEXISTS key field + *

+ * Determine if a hash field exists + */ + HEXISTS { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HExistsExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HGET key field + *

+ * Get the value of a hash field + */ + HGET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HGetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HGETALL key + *

+ * Get all the fields and values in a hash + */ + HGETALL { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HGetAllExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HINCRBY key field increment + *

+ * Increment the integer value of a hash field by the given number + */ + HINCRBY { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HIncrByExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HINCRBYFLOAT key field increment + *

+ * Increment the float value of a hash field by the given amount + */ + HINCRBYFLOAT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HIncrByFloatExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HKEYS key + *

+ * Get all the fields in a hash + */ + HKEYS { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HKeysExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HLEN key + *

+ * Get the number of fields in a hash + */ + HLEN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HLenExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HMGET key field [field ...] + *

+ * Get the values of all the given hash fields + */ + HMGET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HMGetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HMSET key field value [field value ...] + *

+ * Set multiple hash fields to multiple values + */ + HMSET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HMSetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HSCAN key cursor [MATCH pattern] [COUNT count] + *

+ * Incrementally iterate hash fields and associated values + */ + HSCAN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HScanExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HSET key field value + *

+ * Set the string value of a hash field + */ + HSET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HSetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HSETNX key field value + *

+ * Set the value of a hash field, only if the field does not exist + */ + HSETNX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HSetNXExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * HVALS key + *

+ * Get all the values in a hash + */ + HVALS { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new HValsExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HASH; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + *********** HyperLogLogs ************** + ***************************************/ + + /** + * PFADD key element [element ...] + *

+ * Adds the specified elements to the specified HyperLogLog + */ + PFADD { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PFAddExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HLL; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PFCOUNT key [key ...] + *

+ * Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s) + */ + PFCOUNT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PFCountExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HLL; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PFMERGE destkey sourcekey [sourcekey ...] + *

+ * Merge N different HyperLogLogs into a single one + */ + PFMERGE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PFMergeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_HLL; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + *************** Lists ***************** + ***************************************/ + + /** + * LINDEX key index + *

+ * Get an element from a list by its index + */ + LINDEX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LIndexExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LINSERT key BEFORE|AFTER pivot value + *

+ * Insert an element before or after another element in a list + */ + LINSERT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LInsertExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LLEN key + *

+ * Get the length of a list + */ + LLEN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LLenExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LPOP key + *

+ * Remove and get the first element in a list + */ + LPOP { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LPopExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LPUSH key value [value ...] + *

+ * Prepend one or multiple values to a list + */ + LPUSH { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LPushExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LPUSHX key value + *

+ * Prepend a value to a list, only if the list exists + */ + LPUSHX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LPushXExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LRANGE key start stop + *

+ * Get a range of elements from a list + */ + LRANGE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LRangeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LREM key count value + *

+ * Remove elements from a list + */ + LREM { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LRemExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LSET key index value + *

+ * Set the value of an element in a list by its index + */ + LSET { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LSetExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * LTRIM key start stop + *

+ * Trim a list to the specified range + */ + LTRIM { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new LTrimExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * RPOP key + *

+ * Remove and get the last element in a list + */ + RPOP { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new RPopExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * RPUSH key value [value ...] + *

+ * Append one or multiple values to a list + */ + RPUSH { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new RPushExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * RPUSHX key value + *

+ * Append a value to a list, only if the list exists + */ + RPUSHX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new RPushXExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_LIST; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + **************** Sets ***************** + ***************************************/ + + /** + * SADD key member [member ...] + *

+ * Add one or more members to a set + */ + SADD { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SAddExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SCARD key + *

+ * Get the number of members in a set + */ + SCARD { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SCardExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SDIFF key [key ...] + *

+ * Subtract multiple sets + */ + SDIFF { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SDiffExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SDIFFSTORE destination key [key ...] + *

+ * Subtract multiple sets and store the resulting set in a key + */ + SDIFFSTORE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SDiffStoreExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SISMEMBER key member + *

+ * Determine if a given value is a member of a set + */ + SISMEMBER { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SIsMemberExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SINTER key [key ...] + *

+ * Intersect multiple sets + */ + SINTER { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SInterExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SINTERSTORE destination key [key ...] + *

+ * Intersect multiple sets and store the resulting set in a key + */ + SINTERSTORE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SInterStoreExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SMEMBERS key + *

+ * Get all the members in a set + */ + SMEMBERS { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SMembersExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SMOVE source destination member + *

+ * Move a member from one set to another + */ + SMOVE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SMoveExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SPOP key + *

+ * Remove and return a random member from a set + */ + SPOP { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SPopExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SRANDMEMBER key [count] + *

+ * Get one or multiple random members from a set + */ + SRANDMEMBER { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SRandMemberExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SUNION key [key ...] + *

+ * Add multiple sets + */ + SUNION { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SUnionExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SUNIONSTORE destination key [key ...] + *

+ * Add multiple sets and store the resulting set in a key + */ + SUNIONSTORE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SUnionStoreExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SSCAN key cursor [MATCH pattern] [COUNT count] + *

+ * Incrementally iterate Set elements + */ + SSCAN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SScanExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SREM key member [member ...] + *

+ * Remove one or more members from a set + */ + SREM { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new SRemExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + ************* Sorted Sets ************* + ***************************************/ + + /** + * ZADD key score member [score member ...] + *

+ * Add one or more members to a sorted set, or update its score if it already exists + */ + ZADD { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZAddExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZCARD key + *

+ * Get the number of members in a sorted set + */ + ZCARD { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZCardExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZCOUNT key min max + *

+ * Count the members in a sorted set with scores within the given values + */ + ZCOUNT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZCountExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZINCRBY key increment member + *

+ * Increment the score of a member in a sorted set + */ + ZINCRBY { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZIncrByExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZLEXCOUNT key min max + *

+ * Count the number of members in a sorted set between a given lexicographical range + */ + ZLEXCOUNT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZLexCountExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZRANGE key start stop [WITHSCORES] + *

+ * Return a range of members in a sorted set, by index + */ + ZRANGE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRangeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZRANGEBYLEX key min max [LIMIT offset count] + *

+ * Return a range of members in a sorted set, by lexicographical range + */ + ZRANGEBYLEX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRangeByLexExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] + *

+ * Return a range of members in a sorted set, by score + */ + ZRANGEBYSCORE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRangeByScoreExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZREVRANGE key start stop [WITHSCORES] + *

+ * Return a range of members in a sorted set, by index, with scores ordered from high to low + */ + ZREVRANGE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRevRangeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZRANK key member + *

+ * Determine the index of a member in a sorted set + */ + ZRANK { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRankExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZREM key member [member ...] + *

+ * Remove one or more members from a sorted set + */ + ZREM { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRemExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZREMRANGEBYLEX key min max + *

+ * Remove all members in a sorted set between the given lexicographical range + */ + ZREMRANGEBYLEX { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRemRangeByLexExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZREMRANGEBYRANK key start stop + *

+ * Remove all members in a sorted set within the given indexes + */ + ZREMRANGEBYRANK { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRemRangeByRankExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZREMRANGEBYSCORE key min max + *

+ * Remove all members in a sorted set within the given scores + */ + ZREMRANGEBYSCORE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRemRangeByScoreExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] + *

+ * Return a range of members in a sorted set, by score, with scores ordered from high to low + */ + ZREVRANGEBYSCORE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRevRangeByScoreExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZREVRANK key member + *

+ * Determine the index of a member in a sorted set, with scores ordered from high to low + */ + ZREVRANK { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZRevRankExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZSCAN key cursor [MATCH pattern] [COUNT count] + *

+ * Incrementally iterate sorted sets elements and associated scores + */ + ZSCAN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZScanExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ZSCORE key member + *

+ * Get the score associated with the given member in a sorted set + */ + ZSCORE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ZScoreExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.REDIS_SORTEDSET; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + ************ Transactions ************* + ***************************************/ + + /** + * DISCARD + *

+ * Discard all commands issued after MULTI + */ + DISCARD { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new DiscardExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * EXEC + *

+ * Execute all commands issued after MULTI + */ + EXEC { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ExecExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * MULTI + *

+ * Mark the start of a transaction block + */ + MULTI { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new MultiExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * UNWATCH + *

+ * Forget about all watched keys + */ + UNWATCH { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new UnwatchExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * WATCH key [key ...] + *

+ * Watch the given keys to determine execution of the MULTI/EXEC block + */ + WATCH { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new WatchExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /*************************************** + *************** Server **************** + ***************************************/ + + /** + * DBSIZE + *

+ * Return the number of keys in the selected database + */ + DBSIZE { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new DBSizeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * ECHO message + *

+ * Echo the given string + */ + ECHO { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new EchoExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * TIME + *

+ * Return the current server time + */ + TIME { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new TimeExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * PING + *

+ * Ping the server + */ + PING { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new PingExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * QUIT + *

+ * Close the connection + */ + QUIT { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new QuitExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + /** + * SHUTDOWN + *

+ * Shut down the server + */ + SHUTDOWN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new ShutDownExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }, + + // UNKNOWN + UNKNOWN { + private Executor executor; + + @Override + public Executor getExecutor() { + if (executor == null) { + executor = new UnkownExecutor(); + } + return executor; + } + + private final RedisDataType dataType = RedisDataType.NONE; + + @Override + public RedisDataType getDataType() { + return this.dataType; + } + }; + + /** + * Abstract method overridden by each value in enum to get the executor associated with that + * command type + * + * @return {@link Executor} for command type + */ + public abstract Executor getExecutor(); + + public abstract RedisDataType getDataType(); + /* + * private RedisCommandType (RedisDataType dataType) { this.dataType = dataType; } + */ +}