You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/12/05 12:38:40 UTC

[36/52] ignite git commit: IGNITE-4244: INCR/DECR to operate on AtomicLong.

IGNITE-4244: INCR/DECR to operate on AtomicLong.


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

Branch: refs/heads/master
Commit: d1cc292583b9358ffb7efab5f15ab84bcfb67e9e
Parents: 2ca709f
Author: shtykh_roman <rs...@yahoo.com>
Authored: Mon Nov 28 16:55:47 2016 +0900
Committer: shtykh_roman <rs...@yahoo.com>
Committed: Mon Nov 28 16:55:47 2016 +0900

----------------------------------------------------------------------
 .../tcp/redis/RedisProtocolSelfTest.java        | 101 ++++++++++++++++---
 .../string/GridRedisGetCommandHandler.java      |  27 ++++-
 .../string/GridRedisIncrDecrCommandHandler.java |  63 ++++++++++--
 .../string/GridRedisSetCommandHandler.java      |  24 ++++-
 .../tcp/redis/GridRedisNioListener.java         |   4 +-
 5 files changed, 193 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d1cc2925/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolSelfTest.java
index c059205..a0066aa 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/protocols/tcp/redis/RedisProtocolSelfTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.processors.rest.protocols.tcp.redis;
 
-import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -264,15 +263,20 @@ public class RedisProtocolSelfTest extends GridCommonAbstractTest {
             Assert.assertEquals(1, (long)jedis.incr("newKeyIncr"));
             Assert.assertEquals(-1, (long)jedis.decr("newKeyDecr"));
 
-            jcache().put("incrKey1", 1L);
+            Assert.assertEquals("1", jedis.get("newKeyIncr"));
+            Assert.assertEquals("-1", jedis.get("newKeyDecr"));
 
-            Assert.assertEquals(2L, (long)jedis.incr("incrKey1"));
+            Assert.assertEquals(1, (long)jedis.incr("incrKey1"));
 
-            jcache().put("decrKey1", 1L);
+            jedis.set("incrKey1", "10");
 
-            Assert.assertEquals(0L, (long)jedis.decr("decrKey1"));
+            Assert.assertEquals(11L, (long)jedis.incr("incrKey1"));
 
-            jcache().put("nonInt", "abc");
+            jedis.set("decrKey1", "10");
+
+            Assert.assertEquals(9L, (long)jedis.decr("decrKey1"));
+
+            jedis.set("nonInt", "abc");
 
             try {
                 jedis.incr("nonInt");
@@ -282,6 +286,7 @@ public class RedisProtocolSelfTest extends GridCommonAbstractTest {
             catch (JedisDataException e) {
                 assertTrue(e.getMessage().startsWith("ERR"));
             }
+
             try {
                 jedis.decr("nonInt");
 
@@ -291,9 +296,39 @@ public class RedisProtocolSelfTest extends GridCommonAbstractTest {
                 assertTrue(e.getMessage().startsWith("ERR"));
             }
 
-            jcache().put("outOfRange", new BigInteger("234293482390480948029348230948"));
+            jedis.set("outOfRangeIncr1", "9223372036854775808");
             try {
-                jedis.incr("outOfRange");
+                jedis.incr("outOfRangeIncr1");
+
+                assert false : "Exception has to be thrown!";
+            }
+            catch (JedisDataException e) {
+                assertTrue(e.getMessage().startsWith("ERR"));
+            }
+
+            jedis.set("outOfRangeDecr1", "-9223372036854775809");
+            try {
+                jedis.decr("outOfRangeDecr1");
+
+                assert false : "Exception has to be thrown!";
+            }
+            catch (JedisDataException e) {
+                assertTrue(e.getMessage().startsWith("ERR"));
+            }
+
+            jedis.set("outOfRangeInc2", String.valueOf(Long.MAX_VALUE));
+            try {
+                jedis.incr("outOfRangeInc2");
+
+                assert false : "Exception has to be thrown!";
+            }
+            catch (JedisDataException e) {
+                assertTrue(e.getMessage().startsWith("ERR"));
+            }
+
+            jedis.set("outOfRangeDecr2", String.valueOf(Long.MIN_VALUE));
+            try {
+                jedis.decr("outOfRangeDecr2");
 
                 assert false : "Exception has to be thrown!";
             }
@@ -308,16 +343,54 @@ public class RedisProtocolSelfTest extends GridCommonAbstractTest {
      */
     public void testIncrDecrBy() throws Exception {
         try (Jedis jedis = pool.getResource()) {
-            Assert.assertEquals(2, (long)jedis.incrBy("newKeyIncr1", 2));
-            Assert.assertEquals(-2, (long)jedis.decrBy("newKeyDecr1", 2));
+            Assert.assertEquals(2, (long)jedis.incrBy("newKeyIncrBy", 2));
+            Assert.assertEquals(-2, (long)jedis.decrBy("newKeyDecrBy", 2));
+
+            jedis.set("incrDecrKeyBy", "1");
+
+            Assert.assertEquals(11L, (long)jedis.incrBy("incrDecrKeyBy", 10));
 
-            jcache().put("incrKey2", 1L);
+            Assert.assertEquals(9L, (long)jedis.decrBy("incrDecrKeyBy", 2));
 
-            Assert.assertEquals(3L, (long)jedis.incrBy("incrKey2", 2));
+            jedis.set("outOfRangeIncrBy", "1");
+            try {
+                jedis.incrBy("outOfRangeIncrBy", Long.MAX_VALUE);
+
+                assert false : "Exception has to be thrown!";
+            }
+            catch (JedisDataException e) {
+                assertTrue(e.getMessage().startsWith("ERR"));
+            }
 
-            jcache().put("decrKey2", 2L);
+            jedis.set("outOfRangeDecrBy", "-1");
+            try {
+                jedis.decrBy("outOfRangeDecrBy", Long.MIN_VALUE);
 
-            Assert.assertEquals(0L, (long)jedis.decrBy("decrKey2", 2));
+                assert false : "Exception has to be thrown!";
+            }
+            catch (JedisDataException e) {
+                assertTrue(e.getMessage().startsWith("ERR"));
+            }
+
+            jedis.set("outOfRangeIncBy2", String.valueOf(Long.MAX_VALUE));
+            try {
+                jedis.incrBy("outOfRangeIncBy2", Long.MAX_VALUE);
+
+                assert false : "Exception has to be thrown!";
+            }
+            catch (JedisDataException e) {
+                assertTrue(e.getMessage().startsWith("ERR"));
+            }
+
+            jedis.set("outOfRangeDecrBy2", String.valueOf(Long.MIN_VALUE));
+            try {
+                jedis.decrBy("outOfRangeDecrBy2", Long.MIN_VALUE);
+
+                assert false : "Exception has to be thrown!";
+            }
+            catch (JedisDataException e) {
+                assertTrue(e.getMessage().startsWith("ERR"));
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1cc2925/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisGetCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisGetCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisGetCommandHandler.java
index a275522..aac4170 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisGetCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisGetCommandHandler.java
@@ -20,8 +20,10 @@ package org.apache.ignite.internal.processors.rest.handlers.redis.string;
 import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.List;
+import org.apache.ignite.IgniteAtomicLong;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.GridKernalContext;
 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;
@@ -44,14 +46,21 @@ public class GridRedisGetCommandHandler extends GridRedisRestCommandHandler {
         GET
     );
 
+    /** Grid context. */
+    private final GridKernalContext ctx;
+
     /**
      * Constructor.
      *
      * @param log Logger.
      * @param hnd Handler.
+     * @param ctx Context.
      */
-    public GridRedisGetCommandHandler(IgniteLogger log, GridRestProtocolHandler hnd) {
+    public GridRedisGetCommandHandler(final IgniteLogger log, final GridRestProtocolHandler hnd,
+        GridKernalContext ctx) {
         super(log, hnd);
+
+        this.ctx = ctx;
     }
 
     /** {@inheritDoc} */
@@ -75,8 +84,20 @@ public class GridRedisGetCommandHandler extends GridRedisRestCommandHandler {
 
     /** {@inheritDoc} */
     @Override public ByteBuffer makeResponse(final GridRestResponse restRes, List<String> params) {
-        if (restRes.getResponse() == null)
-            return GridRedisProtocolParser.nil();
+        if (restRes.getResponse() == null) {
+            // check if an atomic long with the key exists (related to incr/decr).
+            IgniteAtomicLong l = ctx.grid().atomicLong(params.get(0), 0, false);
+
+            long val;
+            try {
+                val = l.get();
+            }
+            catch (Exception ignored) {
+                return GridRedisProtocolParser.nil();
+            }
+
+            return GridRedisProtocolParser.toBulkString(val);
+        }
 
         if (restRes.getResponse() instanceof String)
             return GridRedisProtocolParser.toBulkString(restRes.getResponse());

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1cc2925/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisIncrDecrCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisIncrDecrCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisIncrDecrCommandHandler.java
index 4052ad5..2036d76 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisIncrDecrCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisIncrDecrCommandHandler.java
@@ -26,6 +26,7 @@ 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.handlers.redis.exception.GridRedisTypeException;
 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;
@@ -37,6 +38,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import static org.apache.ignite.internal.processors.rest.GridRestCommand.ATOMIC_DECREMENT;
 import static org.apache.ignite.internal.processors.rest.GridRestCommand.ATOMIC_INCREMENT;
 import static org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_GET;
+import static org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_REMOVE;
 import static org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisCommand.DECR;
 import static org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisCommand.DECRBY;
 import static org.apache.ignite.internal.processors.rest.protocols.tcp.redis.GridRedisCommand.INCR;
@@ -89,10 +91,38 @@ public class GridRedisIncrDecrCommandHandler extends GridRedisRestCommandHandler
         if (getResp.getResponse() == null)
             restReq.initial(0L);
         else {
-            if (getResp.getResponse() instanceof Long && (Long)getResp.getResponse() <= Long.MAX_VALUE)
-                restReq.initial((Long)getResp.getResponse());
+            if (getResp.getResponse() instanceof String) {
+                Long init;
+
+                try {
+                    init = Long.parseLong((String)getResp.getResponse());
+
+                    restReq.initial(init);
+                }
+                catch (Exception e) {
+                    U.error(log, "An initial value must be numeric and in range", e);
+
+                    throw new GridRedisGenericException("An initial value must be numeric and in range");
+                }
+
+                if ((init == Long.MAX_VALUE && (msg.command() == INCR || msg.command() == INCRBY))
+                    || (init == Long.MIN_VALUE && (msg.command() == DECR || msg.command() == DECRBY)))
+                    throw new GridRedisGenericException("Increment or decrement would overflow");
+            }
             else
-                throw new GridRedisGenericException("An initial value must be numeric and in range");
+                throw new GridRedisTypeException("Operation against a key holding the wrong kind of value");
+
+            // remove from cache.
+            GridRestCacheRequest rmReq = new GridRestCacheRequest();
+
+            rmReq.clientId(msg.clientId());
+            rmReq.key(msg.key());
+            rmReq.command(CACHE_REMOVE);
+
+            Object rmResp = hnd.handle(rmReq).getResponse();
+
+            if (rmResp == null || !(boolean)rmResp)
+                throw new GridRedisGenericException("Cannot incr/decr on the non-atomiclong key");
         }
 
         restReq.clientId(msg.clientId());
@@ -101,10 +131,16 @@ public class GridRedisIncrDecrCommandHandler extends GridRedisRestCommandHandler
 
         if (msg.messageSize() > 2) {
             try {
-                restReq.delta(Long.valueOf(msg.aux(DELTA_POS)));
+                Long delta = Long.valueOf(msg.aux(DELTA_POS));
+
+                // check if it can be safely added.
+                safeAdd(restReq.initial(), delta);
+
+                restReq.delta(delta);
             }
-            catch (NumberFormatException e) {
-                U.error(log, "Wrong increment delta", e);
+            catch (NumberFormatException | ArithmeticException e) {
+                U.error(log, "An increment value must be numeric and in range", e);
+
                 throw new GridRedisGenericException("An increment value must be numeric and in range");
             }
         }
@@ -139,4 +175,19 @@ public class GridRedisIncrDecrCommandHandler extends GridRedisRestCommandHandler
         else
             return GridRedisProtocolParser.toTypeError("Value is non-numeric or out of range");
     }
+
+    /**
+     * Safely add long values.
+     *
+     * @param left A long value.
+     * @param right A long value.
+     * @return An addition result or an exception is thrown when overflow occurs.
+     */
+    private static long safeAdd(long left, long right) {
+        if (right > 0 ? left > Long.MAX_VALUE - right
+            : left < Long.MIN_VALUE - right) {
+            throw new ArithmeticException("Long overflow");
+        }
+        return left + right;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1cc2925/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisSetCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisSetCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisSetCommandHandler.java
index 956d4cb..2eea0e1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisSetCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/redis/string/GridRedisSetCommandHandler.java
@@ -20,8 +20,11 @@ package org.apache.ignite.internal.processors.rest.handlers.redis.string;
 import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.List;
+import org.apache.ignite.IgniteAtomicLong;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.GridKernalContext;
 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;
@@ -52,14 +55,21 @@ public class GridRedisSetCommandHandler extends GridRedisRestCommandHandler {
     /** Value position in Redis message. */
     private static final int VAL_POS = 2;
 
+    /** Grid context. */
+    private final GridKernalContext ctx;
+
     /**
      * Constructor.
      *
      * @param log Logger.
      * @param hnd Handler.
+     * @param ctx Context.
      */
-    public GridRedisSetCommandHandler(IgniteLogger log, GridRestProtocolHandler hnd) {
+    public GridRedisSetCommandHandler(final IgniteLogger log, final GridRestProtocolHandler hnd,
+        GridKernalContext ctx) {
         super(log, hnd);
+
+        this.ctx = ctx;
     }
 
     /** {@inheritDoc} */
@@ -71,6 +81,18 @@ public class GridRedisSetCommandHandler extends GridRedisRestCommandHandler {
     @Override public GridRestRequest asRestRequest(GridRedisMessage msg) throws IgniteCheckedException {
         assert msg != null;
 
+        // check if an atomic long with the key exists (related to incr/decr).
+        IgniteAtomicLong l = ctx.grid().atomicLong(msg.key(), 0, false);
+
+        if (l != null) {
+            try {
+                l.close();
+            }
+            catch (IgniteException e) {
+                U.warn(log, "Failed to remove atomic long for key [" + msg.key() + "]");
+            }
+        }
+
         GridRestCacheRequest restReq = new GridRestCacheRequest();
 
         restReq.clientId(msg.clientId());

http://git-wip-us.apache.org/repos/asf/ignite/blob/d1cc2925/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 45c8061..1042bdb 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
@@ -67,8 +67,8 @@ public class GridRedisNioListener extends GridNioServerListenerAdapter<GridRedis
         addCommandHandler(new GridRedisConnectionCommandHandler());
 
         // string commands.
-        addCommandHandler(new GridRedisGetCommandHandler(log, hnd));
-        addCommandHandler(new GridRedisSetCommandHandler(log, hnd));
+        addCommandHandler(new GridRedisGetCommandHandler(log, hnd, ctx));
+        addCommandHandler(new GridRedisSetCommandHandler(log, hnd, ctx));
         addCommandHandler(new GridRedisMSetCommandHandler(log, hnd));
         addCommandHandler(new GridRedisMGetCommandHandler(log, hnd));
         addCommandHandler(new GridRedisIncrDecrCommandHandler(log, hnd));