+ add initial draft for ConcurrentMap contract to RedisMap

+ add disabled integration tests (need to find a way to reuse the same connection) w/o transactions
This commit is contained in:
Costin Leau
2010-11-30 14:43:58 +02:00
parent bd3093b3d9
commit d3fd66ef79
6 changed files with 185 additions and 36 deletions

View File

@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.dao.DataAccessException;
import org.springframework.data.keyvalue.redis.connection.RedisConnection;
import org.springframework.data.keyvalue.redis.connection.RedisConnectionFactory;
import org.springframework.data.keyvalue.redis.serializer.RedisSerializer;
@@ -320,7 +321,13 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
@Override
public Object exec() {
throw new UnsupportedOperationException();
return execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
return connection.exec();
}
});
}
@Override
@@ -379,7 +386,13 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
@Override
public void multi() {
throw new UnsupportedOperationException();
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
connection.multi();
return null;
}
}, true);
}
@Override

View File

@@ -83,15 +83,6 @@ public class DefaultRedisMap<K, V> implements RedisMap<K, V> {
return hashOps.increment(key, delta);
}
@Override
public boolean putIfAbsent(K key, V value) {
if (!hashOps.hasKey(key)) {
put(key, value);
return true;
}
return false;
}
@Override
public String getKey() {
return hashOps.getKey();
@@ -203,4 +194,104 @@ public class DefaultRedisMap<K, V> implements RedisMap<K, V> {
sb.append(getKey());
return sb.toString();
}
@Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
// RedisOperations<String, ?> ops = hashOps.getOperations();
//
// for (;;) {
// ops.watch(getKey());
// V v = get(key);
// if (v == null) {
// ops.multi();
// put(key, value);
// if (ops.exec() != null) {
// return null;
// }
// }
// else {
// return v;
// }
// }
}
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
// if (value == null){
// throw new NullPointerException();
// }
//
// RedisOperations<String, ?> ops = hashOps.getOperations();
//
// for (;;) {
// ops.watch(getKey());
// V v = get(key);
// if (value.equals(v)) {
// ops.multi();
// remove(key);
// if (ops.exec() != null) {
// return true;
// }
// }
// else {
// return false;
// }
// }
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException();
// if (newValue == null || oldValue == null) {
// throw new NullPointerException();
// }
//
// RedisOperations<String, ?> ops = hashOps.getOperations();
//
// for (;;) {
// ops.watch(getKey());
// V v = get(key);
// if (oldValue.equals(v)) {
// ops.multi();
// put(key, newValue);
// if (ops.exec() != null) {
// return true;
// }
// }
// else {
// return false;
// }
// }
}
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException();
// if (value == null) {
// throw new NullPointerException();
// }
//
// RedisOperations<String, ?> ops = hashOps.getOperations();
//
// for (;;) {
// ops.watch(getKey());
// if (containsKey(key)) {
// ops.multi();
// V oldValue = put(key, value);
// if (ops.exec() != null) {
// return oldValue;
// }
// }
// else {
// return null;
// }
// }
}
}

View File

@@ -100,7 +100,9 @@ public class RedisAtomicInteger extends Number implements Serializable {
return true;
}
}
return false;
else {
return false;
}
}
}

View File

@@ -101,7 +101,9 @@ public class RedisAtomicLong extends Number implements Serializable {
return true;
}
}
return false;
else {
return false;
}
}
}

View File

@@ -15,16 +15,15 @@
*/
package org.springframework.data.keyvalue.redis.util;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
/**
* Map view of a Redis hash.
*
* @author Costin Leau
*/
public interface RedisMap<K, V> extends RedisStore<String>, Map<K, V> {
boolean putIfAbsent(K key, V value);
public interface RedisMap<K, V> extends RedisStore<String>, ConcurrentMap<K, V> {
Integer increment(K key, int delta);
}

View File

@@ -269,25 +269,6 @@ public abstract class AbstractRedisMapTests<K, V> {
assertEquals(v2, map.get(k2));
}
@Test
public void testPutIfAbsent() {
K k1 = getKey();
K k2 = getKey();
V v1 = getValue();
V v2 = getValue();
assertNull(map.get(k1));
assertTrue(map.putIfAbsent(k1, v1));
assertFalse(map.putIfAbsent(k1, v2));
assertEquals(v1, map.get(k1));
assertTrue(map.putIfAbsent(k2, v2));
assertFalse(map.putIfAbsent(k2, v1));
assertEquals(v2, map.get(k2));
}
@Test
public void testRemove() {
K k1 = getKey();
@@ -375,4 +356,65 @@ public abstract class AbstractRedisMapTests<K, V> {
assertThat(values, hasItem(v1));
assertThat(values, not(hasItem(v2)));
}
@Test(expected = UnsupportedOperationException.class)
public void testConcurrentPutIfAbsent() {
K k1 = getKey();
K k2 = getKey();
V v1 = getValue();
V v2 = getValue();
assertNull(map.get(k1));
assertNull(map.putIfAbsent(k1, v1));
assertEquals(v1, map.putIfAbsent(k1, v2));
assertEquals(v1, map.get(k1));
assertNull(map.putIfAbsent(k2, v2));
assertEquals(v2, map.putIfAbsent(k2, v1));
assertEquals(v2, map.get(k2));
}
@Test(expected = UnsupportedOperationException.class)
public void testConcurrentRemove() {
K k1 = getKey();
V v1 = getValue();
V v2 = getValue();
map.put(k1, v1);
assertFalse(map.remove(k1, v1));
assertEquals(v1, map.get(k1));
assertTrue(map.remove(k1, v1));
assertNull(map.get(k1));
}
@Test(expected = UnsupportedOperationException.class)
public void testConcurrentReplaceTwoArgs() {
K k1 = getKey();
V v1 = getValue();
V v2 = getValue();
map.put(k1, v1);
assertFalse(map.replace(k1, v2, v1));
assertEquals(v1, map.get(k1));
assertTrue(map.replace(k1, v1, v2));
assertEquals(v2, map.get(k1));
}
@Test(expected = UnsupportedOperationException.class)
public void testConcurrentReplaceOneArg() {
K k1 = getKey();
V v1 = getValue();
V v2 = getValue();
assertNull(map.replace(k1, v1));
map.put(k1, v1);
assertNull(map.replace(getKey(), v1));
assertEquals(v1, map.replace(k1, v2));
assertEquals(v2, map.get(k1));
}
}