Skip to content
This repository
Browse code

Add hincrby, getbit, setbit commands

  • Loading branch information...
commit eae3b4a916af80152a44239b4a13c976e4e76045 1 parent f69b865
Alex Bertram authored March 17, 2012
5  core/api/src/main/java/org/jredis/JRedis.java
@@ -1092,4 +1092,9 @@
1092 1092
 	 * @see {@link ObjectInfo}
1093 1093
 	 */
1094 1094
 	public <K extends Object> ObjectInfo debug (K key) throws RedisException;
  1095
+	
  1096
+	public <K extends Object> boolean setbit(K key, int offset, boolean value) throws RedisException;
  1097
+
  1098
+	public <K extends Object> boolean getbit(K key, int offset) throws RedisException;
  1099
+	
1095 1100
 }
22  core/api/src/main/java/org/jredis/JRedisFuture.java
@@ -152,6 +152,10 @@
152 152
 	public <K extends Object, T extends Serializable> 
153 153
 		   Future<Boolean> setnx (K key, T object);
154 154
 
  155
+	public <K extends Object> Future<Boolean> setbit(K key, int offset, boolean value);
  156
+
  157
+
  158
+	
155 159
 	/**
156 160
 	 * @Redis GET
157 161
 	 * @param key
@@ -165,7 +169,10 @@
165 169
 	public <K extends Object, T extends Serializable> 
166 170
 		Future<byte[]> getset (K key, T object);
167 171
 
168  
-	
  172
+
  173
+	public <K extends Object> Future<Boolean> getbit(K key, int offset);
  174
+
  175
+		
169 176
 	/**
170 177
 	 * @Redis MGET
171 178
 	 * @param key
@@ -810,6 +817,17 @@
810 817
 	@Redis(versions="1.3.4")
811 818
 	public <K extends Object> Future<byte[]> hget(K key, K entry);
812 819
 	
  820
+
  821
+	/**
  822
+	 * @Redis HINCRBY
  823
+	 * @param key
  824
+	 * @param entry
  825
+	 * @param increment
  826
+	 * @return
  827
+	 */
  828
+	public <K extends Object> Future<Long> hincrby(K key, K entry, long increment);
  829
+	
  830
+	
813 831
 	/**
814 832
 	 * 
815 833
 	 * @Redis HEXISTS
@@ -998,4 +1016,6 @@
998 1016
 	 * @return
999 1017
 	 */
1000 1018
 	public <K extends Object> Future<ObjectInfo> debug (K key);
  1019
+	
  1020
+
1001 1021
 }
9  core/api/src/main/java/org/jredis/protocol/Command.java
@@ -122,6 +122,10 @@
122 122
 	ZREMRANGEBYRANK	(RequestType.KEY_NUM_NUM,	ResponseType.NUMBER),
123 123
 	ZCOUNT		(RequestType.KEY_NUM_NUM, ResponseType.NUMBER),
124 124
 		
  125
+	// Commands operating on bit sets
  126
+	SETBIT		(RequestType.KEY_IDX_VALUE, ResponseType.NUMBER),
  127
+	GETBIT		(RequestType.KEY_NUM, ResponseType.NUMBER),
  128
+	
125 129
 	// Commands operating on hashes
126 130
 	HSET 		(RequestType.KEY_KEY_VALUE, ResponseType.BOOLEAN),
127 131
 	HGET 		(RequestType.KEY_VALUE, 	ResponseType.BULK),
@@ -131,6 +135,7 @@
131 135
 	HKEYS 		(RequestType.KEY, 			ResponseType.MULTI_BULK),
132 136
 	HVALS 		(RequestType.KEY, 			ResponseType.MULTI_BULK),
133 137
 	HGETALL 	(RequestType.KEY, 			ResponseType.MULTI_BULK),
  138
+	HINCRBY		(RequestType.KEY_KEY_NUM, ResponseType.NUMBER),
134 139
 	
135 140
 	// transactional commands
136 141
 	MULTI		(RequestType.NO_ARG, 		ResponseType.STATUS),
@@ -309,7 +314,9 @@ static final public int bitclear(final int bitsetin, Flag...flags){
309 314
     	/**  */
310 315
     	MULTI_KEY,
311 316
     	/**  */
312  
-    	BULK_SET
  317
+    	BULK_SET,
  318
+    	
  319
+    	KEY_KEY_NUM
313 320
     }
314 321
 
315 322
     /**
62  core/ri/src/main/java/org/jredis/ri/alphazero/JRedisFutureSupport.java
@@ -337,6 +337,32 @@
337 337
 	// -------- set
338 338
 
339 339
 	@Override
  340
+	public <K> Future<Boolean> setbit(K key, int offset, boolean value) {
  341
+		byte[] keybytes = null;
  342
+		if((keybytes = JRedisSupport.getKeyBytes(key)) == null) 
  343
+			throw new IllegalArgumentException ("invalid key => ["+key+"]");
  344
+
  345
+		Future<Response> futureResponse = this.queueRequest(Command.SETBIT, keybytes,  
  346
+				Convert.toBytes(offset), Convert.toBytes(value ? 1 : 0));
  347
+
  348
+		return new FutureBit(futureResponse);
  349
+		
  350
+	}
  351
+
  352
+
  353
+	@Override
  354
+	public <K> Future<Boolean> getbit(K key, int offset)  {
  355
+		byte[] keybytes = null;
  356
+		if((keybytes = JRedisSupport.getKeyBytes(key)) == null) 
  357
+			throw new IllegalArgumentException ("invalid key => ["+key+"]");
  358
+
  359
+		Future<Response> futureResponse = this.queueRequest(Command.GETBIT, keybytes,  
  360
+				Convert.toBytes(offset));
  361
+
  362
+		return new FutureBit(futureResponse);
  363
+	}
  364
+	
  365
+	@Override
340 366
 	public <K extends Object> FutureStatus set(K key, byte[] value) {
341 367
 		byte[] keybytes = null;
342 368
 		if((keybytes = JRedisSupport.getKeyBytes(key)) == null)
@@ -494,6 +520,20 @@
494 520
 	public <K extends Object> Future<Boolean> hset(K key, K field, String stringValue) {
495 521
 		return hset (key, field, DefaultCodec.encode(stringValue));
496 522
 	}
  523
+	
  524
+	public <K extends Object> Future<Long> hincrby(K key, K field, long increment) {
  525
+		byte[] keyBytes = null;
  526
+		if((keyBytes = JRedisSupport.getKeyBytes(key)) == null)
  527
+			throw new IllegalArgumentException ("invalid key => ["+key+"]");
  528
+
  529
+		byte[] entryBytes = null;
  530
+		if((entryBytes = JRedisSupport.getKeyBytes(field)) == null)
  531
+			throw new IllegalArgumentException ("invalid field => ["+field+"]");
  532
+
  533
+		Future<Response> futureResponse = this.queueRequest(Command.HINCRBY, keyBytes, entryBytes, Convert.toBytes(increment));
  534
+		return new FutureLong(futureResponse);
  535
+	}
  536
+	
497 537
 	public <K extends Object> Future<Boolean> hset(K key, K field, Number numberValue) {
498 538
 		return hset (key, field, String.valueOf(numberValue).getBytes());
499 539
 	}
@@ -1486,6 +1526,26 @@ public Boolean get (long timeout, TimeUnit unit)
1486 1526
         	return valResp.getBooleanValue();
1487 1527
         }
1488 1528
 	}
  1529
+	
  1530
+	public static class FutureBit extends FutureResultBase implements Future<Boolean> {
  1531
+
  1532
+        protected FutureBit (Future<Response> pendingRequest) { super(pendingRequest); }
  1533
+
  1534
+        @SuppressWarnings("boxing")
  1535
+		public Boolean get () throws InterruptedException, ExecutionException {
  1536
+        	ValueResponse valResp = (ValueResponse) pendingRequest.get();
  1537
+        	return valResp.getLongValue() == 1;
  1538
+        }
  1539
+
  1540
+        @SuppressWarnings("boxing")
  1541
+		public Boolean get (long timeout, TimeUnit unit)
  1542
+        	throws InterruptedException, ExecutionException, TimeoutException
  1543
+        {
  1544
+        	ValueResponse valResp = (ValueResponse) pendingRequest.get(timeout, unit);
  1545
+        	return valResp.getLongValue() == 1;
  1546
+        }
  1547
+	}
  1548
+	
1489 1549
 	public static class FutureString extends FutureResultBase implements Future<String>{
1490 1550
 
1491 1551
         protected FutureString (Future<Response> pendingRequest) { super(pendingRequest); }
@@ -1779,4 +1839,6 @@ public ObjectInfo get (long timeout, TimeUnit unit)
1779 1839
 		Future<byte[]> echo (T msg) {
1780 1840
 			return echo (DefaultCodec.encode(msg));
1781 1841
 	}
  1842
+	
  1843
+
1782 1844
 }
36  core/ri/src/main/java/org/jredis/ri/alphazero/JRedisSupport.java
@@ -115,7 +115,41 @@
115 115
 	// ------------------------------------------------------------------------
116 116
 
117 117
 
118  
-//	@Override
  118
+	@Override
  119
+	public <K> boolean setbit(K key, int offset, boolean value) throws ProviderException, ClientRuntimeException, RedisException {
  120
+		byte[] keybytes = null;
  121
+		if((keybytes = getKeyBytes(key)) == null) 
  122
+			throw new IllegalArgumentException ("invalid key => ["+key+"]");
  123
+
  124
+		/* ValueRespose */
  125
+		try {
  126
+			ValueResponse valResponse = (ValueResponse) this.serviceRequest(Command.SETBIT, keybytes, Convert.toBytes(offset), Convert.toBytes(value ? 1 : 0));
  127
+			return valResponse.getLongValue() == 1;
  128
+		}
  129
+		catch (ClassCastException e){
  130
+			throw new ProviderException("Expecting a ValueResponse here => " + e.getLocalizedMessage(), e);
  131
+		}
  132
+	}
  133
+
  134
+
  135
+	@Override
  136
+	public <K> boolean getbit(K key, int offset) throws ProviderException, ClientRuntimeException, RedisException {
  137
+		byte[] keybytes = null;
  138
+		if((keybytes = getKeyBytes(key)) == null) 
  139
+			throw new IllegalArgumentException ("invalid key => ["+key+"]");
  140
+
  141
+		/* ValueRespose */
  142
+		try {
  143
+			ValueResponse valResponse = (ValueResponse) this.serviceRequest(Command.GETBIT, keybytes, Convert.toBytes(offset));
  144
+			return valResponse.getLongValue() == 1;
  145
+		}
  146
+		catch (ClassCastException e){
  147
+			throw new ProviderException("Expecting a ValueResponse here => " + e.getLocalizedMessage(), e);
  148
+		}
  149
+	}
  150
+
  151
+
  152
+	//	@Override
119 153
 //	public <K extends Object> JRedis auth(K key) throws RedisException {
120 154
 //		byte[] keydata = null;
121 155
 //		if((keydata = getKeyBytes(key)) == null) 
58  core/ri/src/test/java/org/jredis/ri/alphazero/JRedisFutureProviderTestsBase.java
@@ -39,6 +39,7 @@
39 39
 import org.jredis.protocol.Command;
40 40
 import org.jredis.protocol.ResponseStatus;
41 41
 import org.jredis.ri.JRedisTestSuiteBase;
  42
+import org.jredis.ri.alphazero.support.Convert;
42 43
 import org.jredis.ri.alphazero.support.DefaultCodec;
43 44
 import org.jredis.ri.alphazero.support.Log;
44 45
 import org.testng.annotations.Test;
@@ -1582,6 +1583,34 @@ public void testHsetHget() throws InterruptedException {
1582 1583
 		catch (ClientRuntimeException e) {  fail(cmd + " Runtime ERROR => " + e.getLocalizedMessage(), e);  }
1583 1584
 	}
1584 1585
 
  1586
+
  1587
+	@Test
  1588
+	public void testHIncrBy() throws InterruptedException {
  1589
+		cmd = Command.HSET.code + " | " + Command.HGET + " | " + Command.HINCRBY;
  1590
+		Log.log("TEST: %s command", cmd);
  1591
+		try {
  1592
+			provider.flushdb();
  1593
+			Future<Boolean> hsetResp1 = provider.hset(keys.get(0), keys.get(1), 41);
  1594
+			Future<Long> hincrBy1 = provider.hincrby(keys.get(0), keys.get(1), 1);
  1595
+			Future<byte[]> hget = provider.hget(keys.get(0), keys.get(1));
  1596
+						
  1597
+			Future<Long> hincrBy2 = provider.hincrby(keys.get(0), keys.get(2), 4);
  1598
+			
  1599
+			try {
  1600
+				assertTrue (hsetResp1.get(), "hset using byte[] value");
  1601
+				assertEquals (hincrBy1.get(), (Long)42l, "hexists of field should be true");
  1602
+				assertEquals(hget.get(), Convert.toBytes(42l));
  1603
+				assertEquals(hincrBy2.get(), (Long)4l);
  1604
+
  1605
+			}
  1606
+			catch(ExecutionException e){
  1607
+				Throwable cause = e.getCause();
  1608
+				fail(cmd + " ERROR => " + cause.getLocalizedMessage(), e); 
  1609
+			}
  1610
+		} 
  1611
+		catch (ClientRuntimeException e) {  fail(cmd + " Runtime ERROR => " + e.getLocalizedMessage(), e);  }
  1612
+	}
  1613
+	
1585 1614
 	@Test
1586 1615
 	public void testHkeys() throws InterruptedException {
1587 1616
 		cmd = Command.HSET.code + " | " + Command.HKEYS;
@@ -1629,6 +1658,35 @@ public void testHkeys() throws InterruptedException {
1629 1658
 		} 
1630 1659
 		catch (ClientRuntimeException e) {  fail(cmd + " Runtime ERROR => " + e.getLocalizedMessage(), e);  }
1631 1660
 	}
  1661
+	
  1662
+	@Test
  1663
+	public void testSetBitGetBit() throws InterruptedException {
  1664
+		cmd = Command.SETBIT.code + " | " + Command.GETBIT;
  1665
+		Log.log("TEST: %s command", cmd);
  1666
+		try {
  1667
+			provider.flushdb();
  1668
+			Future<Boolean> setbit1 = provider.setbit(keys.get(0), 1, true);
  1669
+			Future<Boolean> setbit32 = provider.setbit(keys.get(0), 32, true);
  1670
+
  1671
+			Future<Boolean> getbit1 = provider.getbit(keys.get(0), 1);
  1672
+			Future<Boolean> getbit2 = provider.getbit(keys.get(0), 2);
  1673
+			Future<Boolean> getbit32 = provider.getbit(keys.get(0), 32);
  1674
+			
  1675
+			try {
  1676
+				assertFalse (setbit1.get(), "original bit at 1");
  1677
+				assertFalse (setbit32.get(), "original bit at 32");
  1678
+				assertTrue (getbit1.get(), "getbit at 1");
  1679
+				assertFalse (getbit2.get(), "getbit at 2");
  1680
+				assertTrue (getbit32.get(), "getbit at 32");
  1681
+			}
  1682
+			catch(ExecutionException e){
  1683
+				Throwable cause = e.getCause();
  1684
+				fail(cmd + " ERROR => " + cause.getLocalizedMessage(), e); 
  1685
+			}
  1686
+		} 
  1687
+		catch (ClientRuntimeException e) {  fail(cmd + " Runtime ERROR => " + e.getLocalizedMessage(), e);  }
  1688
+	}
  1689
+
1632 1690
 
1633 1691
 	@Test
1634 1692
 	public void testHvals() throws InterruptedException {
22  core/ri/src/test/java/org/jredis/ri/alphazero/JRedisProviderTestsBase.java
@@ -293,6 +293,28 @@ public void testRename() {
293 293
 		} 
294 294
 		catch (RedisException e) { fail(cmd + " ERROR => " + e.getLocalizedMessage(), e); }
295 295
 	}
  296
+	
  297
+	
  298
+	@Test
  299
+	public void testBitCommands() {
  300
+		cmd = Command.SETBIT.code;
  301
+		Log.log("TEST: %s command", cmd);
  302
+		try {
  303
+			provider.flushdb();
  304
+			
  305
+			key = getRandomAsciiString (random.nextInt(24)+2);
  306
+			provider.del(key);
  307
+			provider.setbit(key, 0, true);
  308
+			provider.setbit(key, 32, true);
  309
+			assertEquals(true, provider.getbit(key,0));
  310
+			assertEquals(true, provider.getbit(key,32));
  311
+			assertEquals(false, provider.getbit(key,64));
  312
+			assertEquals(false, provider.getbit(key,1));
  313
+		} 
  314
+		catch (RedisException e) { fail(cmd + " ERROR => " + e.getLocalizedMessage(), e); }
  315
+	}
  316
+	
  317
+	
296 318
 
297 319
 	/**
298 320
 	 * Test method for {@link org.jredis.ri.alphazero.JRedisSupport#renamenx(java.lang.String, java.lang.String)}.

0 notes on commit eae3b4a

Please sign in to comment.
Something went wrong with that request. Please try again.