You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2016/12/06 08:40:20 UTC
[23/50] 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/ignite-comm-balance-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));