IGNITE-5912: Redis EXPIRE/PEXPIRE commands. - Fixes #2383.

Signed-off-by: shroman <rsht...@yahoo.com>


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/988ffe3e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/988ffe3e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/988ffe3e

Branch: refs/heads/ignite-5872
Commit: 988ffe3e131792072e743e103f524ec20394f8e0
Parents: aa81dd1
Author: shroman <rsht...@yahoo.com>
Authored: Thu Aug 10 09:51:05 2017 +0900
Committer: shroman <rsht...@yahoo.com>
Committed: Thu Aug 10 09:51:05 2017 +0900

----------------------------------------------------------------------
 .../tcp/redis/RedisProtocolStringSelfTest.java  |  44 ++++++++
 .../processors/rest/GridRestCommand.java        |   3 +
 .../handlers/cache/GridCacheCommandHandler.java |  75 +++++++++++++-
 .../key/GridRedisExpireCommandHandler.java      | 101 +++++++++++++++++++
 .../protocols/tcp/redis/GridRedisCommand.java   |   4 +
 .../tcp/redis/GridRedisNioListener.java         |   2 +
 6 files changed, 228 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/988ffe3e/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolStringSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolStringSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolStringSelfTest.java
index 68b42c4..21a9882 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolStringSelfTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolStringSelfTest.java
@@ -423,4 +423,48 @@ public class RedisProtocolStringSelfTest extends 
RedisCommonAbstractTest {
             Assert.assertEquals(2, (long)jedis.exists("existsKey1", 
"existsKey2"));
         }
     }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testExpire() throws Exception {
+        testExpire(new Expiration() {
+            @Override public long expire(Jedis jedis, String key) {
+                return jedis.expire("k1", 2);
+            }
+        });
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testExpireMs() throws Exception {
+        testExpire(new Expiration() {
+            @Override public long expire(Jedis jedis, String key) {
+                return jedis.pexpire("k1", 2000);
+            }
+        });
+    }
+
+    private void testExpire(Expiration exp) throws Exception {
+        try (Jedis jedis = pool.getResource()) {
+            jedis.set("k1", "v1");
+
+            Assert.assertTrue(jedis.exists("k1"));
+
+            Assert.assertEquals(1L, exp.expire(jedis, "k1"));
+
+            Assert.assertEquals("v1", jedis.get("k1"));
+
+            Thread.sleep(2100);
+
+            Assert.assertFalse(jedis.exists("k1"));
+
+            Assert.assertEquals(0L, (long)jedis.expire("k1", 2));
+        }
+    }
+
+    private interface Expiration {
+        long expire(Jedis jedis, String key);
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/988ffe3e/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
index 2ed370d..24b4bda 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
@@ -99,6 +99,9 @@ public enum GridRestCommand {
     /** Cache size. */
     CACHE_SIZE("size"),
 
+    /** Set TTL for the key. */
+    CACHE_UPDATE_TLL("updatettl"),
+
     /** Cache metadata. */
     CACHE_METADATA("metadata"),
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/988ffe3e/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
index f2ca071..53342c9 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
@@ -52,7 +52,10 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
+import org.apache.ignite.internal.processors.cache.CacheInvokeEntry;
 import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
+import 
org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
 import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
 import org.apache.ignite.internal.processors.cache.query.GridCacheSqlMetadata;
 import org.apache.ignite.internal.processors.rest.GridRestCommand;
@@ -83,6 +86,7 @@ import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_C
 import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_CLEAR;
 import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_CONTAINS_KEY;
 import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_CONTAINS_KEYS;
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_UPDATE_TLL;
 import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_GET;
 import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_GET_ALL;
 import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_GET_AND_PUT;
@@ -136,6 +140,7 @@ public class GridCacheCommandHandler extends 
GridRestCommandHandlerAdapter {
         CACHE_PREPEND,
         CACHE_METRICS,
         CACHE_SIZE,
+        CACHE_UPDATE_TLL,
         CACHE_METADATA
     );
 
@@ -158,7 +163,8 @@ public class GridCacheCommandHandler extends 
GridRestCommandHandlerAdapter {
         ATOMIC_DECREMENT,
         CACHE_CAS,
         CACHE_APPEND,
-        CACHE_PREPEND
+        CACHE_PREPEND,
+        CACHE_UPDATE_TLL
     );
 
     /**
@@ -634,6 +640,15 @@ public class GridCacheCommandHandler extends 
GridRestCommandHandlerAdapter {
                     break;
                 }
 
+                case CACHE_UPDATE_TLL: {
+                    if (ttl == null)
+                        throw new 
IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("ttl"));
+
+                    fut = executeCommand(req.destinationId(), req.clientId(), 
cacheName, key, new UpdateTllCommand(key, ttl));
+
+                    break;
+                }
+
                 default:
                     throw new IllegalArgumentException("Invalid command for 
cache handler: " + req);
             }
@@ -1621,4 +1636,62 @@ public class GridCacheCommandHandler extends 
GridRestCommandHandlerAdapter {
             return c.sizeAsync(new CachePeekMode[] {CachePeekMode.PRIMARY});
         }
     }
+
+    /** Update TTL on key. */
+    private static class UpdateTllCommand extends CacheCommand {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final Object key;
+
+        /** */
+        private final Long ttl;
+
+        /**
+         * @param key Key.
+         * @param ttl TTL.
+         */
+        UpdateTllCommand(Object key, Long ttl) {
+            this.key = key;
+            this.ttl = ttl;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteInternalFuture<?> applyx(final 
IgniteInternalCache<Object, Object> c,
+            GridKernalContext ctx) {
+            assert c != null;
+
+            return ctx.closure().callLocalSafe(new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    EntryProcessorResult<Boolean> res = c.invoke(key, new 
EntryProcessor<Object, Object, Boolean>() {
+                        @Override
+                        public Boolean process(MutableEntry<Object, Object> 
entry,
+                            Object... objects) throws EntryProcessorException {
+                            GridCacheEntryEx ex = 
((CacheInvokeEntry)entry).entry();
+
+                            if (entry.getValue() == null)
+                                return false;
+
+                            try {
+                                ex.updateTtl(ex.version(), ttl);
+                            }
+                            catch (GridCacheEntryRemovedException e) {
+                                throw new 
EntryProcessorException(e.getCause());
+                            }
+
+                            return true;
+                        }
+                    });
+
+                    try {
+                        return res.get();
+                    }
+                    catch (EntryProcessorException e) {
+                        throw new IgniteCheckedException(e.getCause());
+                    }
+                }
+            }, false);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/988ffe3e/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/key/GridRedisExpireCommandHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/key/GridRedisExpireCommandHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/key/GridRedisExpireCommandHandler.java
new file mode 100644
index 0000000..70ca504
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/key/GridRedisExpireCommandHandler.java
@@ -0,0 +1,101 @@
+/*
+ * 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.ignite.internal.processors.rest.handlers.redis.key;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.List;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.processors.rest.GridRestProtocolHandler;
+import org.apache.ignite.internal.processors.rest.GridRestResponse;
+import 
org.apache.ignite.internal.processors.rest.handlers.redis.GridRedisRestCommandHandler;
+import 
org.apache.ignite.internal.processors.rest.handlers.redis.exception.GridRedisGenericException;
+import 
org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisCommand;
+import 
org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisMessage;
+import 
org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisProtocolParser;
+import org.apache.ignite.internal.processors.rest.request.GridRestCacheRequest;
+import org.apache.ignite.internal.processors.rest.request.GridRestRequest;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_UPDATE_TLL;
+import static 
org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisCommand.EXPIRE;
+import static 
org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisCommand.PEXPIRE;
+
+/**
+ * Redis EXPIRE/PEXPIRE command handler.
+ */
+public class GridRedisExpireCommandHandler extends GridRedisRestCommandHandler 
{
+    /** Supported commands. */
+    private static final Collection<GridRedisCommand> SUPPORTED_COMMANDS = 
U.sealList(
+        EXPIRE,
+        PEXPIRE
+    );
+
+    /** TTL position in Redis message. */
+    private static final int TTL_POS = 2;
+
+    /**
+     * Handler constructor.
+     *
+     * @param log Logger to use.
+     * @param hnd Rest handler.
+     */
+    public GridRedisExpireCommandHandler(final IgniteLogger log, final 
GridRestProtocolHandler hnd) {
+        super(log, hnd);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<GridRedisCommand> supportedCommands() {
+        return SUPPORTED_COMMANDS;
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridRestRequest asRestRequest(GridRedisMessage msg) 
throws IgniteCheckedException {
+        assert msg != null;
+
+        if (msg.messageSize() < 2)
+            throw new GridRedisGenericException("Wrong number of arguments 
(key is missing)");
+        else if (msg.messageSize() < 3)
+            throw new GridRedisGenericException("Wrong number of arguments 
(timeout value is missing)");
+
+        GridRestCacheRequest restReq = new GridRestCacheRequest();
+
+        restReq.clientId(msg.clientId());
+        restReq.key(msg.key());
+        restReq.command(CACHE_UPDATE_TLL);
+        restReq.cacheName(msg.cacheName());
+
+        switch (msg.command()) {
+            case EXPIRE:
+                restReq.ttl(Long.valueOf(msg.aux(TTL_POS)) * 1000);
+                break;
+            default:
+                // PEXPIRE
+                restReq.ttl(Long.valueOf(msg.aux(TTL_POS)));
+        }
+
+        return restReq;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ByteBuffer makeResponse(final GridRestResponse restRes, 
List<String> params) {
+        return ((Boolean)restRes.getResponse() == true ? 
GridRedisProtocolParser.toInteger("1")
+            : GridRedisProtocolParser.toInteger("0"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/988ffe3e/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisCommand.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisCommand.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisCommand.java
index bc3b9a2..bc32fb4 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisCommand.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisCommand.java
@@ -67,6 +67,10 @@ public enum GridRedisCommand {
     DEL("DEL"),
     /** EXISTS. */
     EXISTS("EXISTS"),
+    /** EXPIRE. */
+    EXPIRE("EXPIRE"),
+    /** PEXPIRE. */
+    PEXPIRE("PEXPIRE"),
 
     // Server commands.
     /** DBSIZE. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/988ffe3e/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisNioListener.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisNioListener.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisNioListener.java
index 9436369..bc2daf2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisNioListener.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/GridRedisNioListener.java
@@ -28,6 +28,7 @@ import 
org.apache.ignite.internal.processors.rest.handlers.redis.GridRedisComman
 import 
org.apache.ignite.internal.processors.rest.handlers.redis.GridRedisConnectionCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.redis.key.GridRedisDelCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.redis.key.GridRedisExistsCommandHandler;
+import 
org.apache.ignite.internal.processors.rest.handlers.redis.key.GridRedisExpireCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.redis.server.GridRedisDbSizeCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.redis.server.GridRedisFlushCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.redis.string.GridRedisAppendCommandHandler;
@@ -87,6 +88,7 @@ public class GridRedisNioListener extends 
GridNioServerListenerAdapter<GridRedis
         // key commands.
         addCommandHandler(new GridRedisDelCommandHandler(log, hnd));
         addCommandHandler(new GridRedisExistsCommandHandler(log, hnd));
+        addCommandHandler(new GridRedisExpireCommandHandler(log, hnd));
 
         // server commands.
         addCommandHandler(new GridRedisDbSizeCommandHandler(log, hnd));

Reply via email to