RedissonList added

pull/6/head
Nikita 11 years ago
parent fcd1442156
commit 5d38ef36a0

@ -1,5 +1,6 @@
package org.redisson;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
@ -12,6 +13,7 @@ import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
public class Redisson {
// TODO drain after some time
private final ConcurrentMap<String, RedissonList> listsMap = new ConcurrentHashMap<String, RedissonList>();
private final ConcurrentMap<String, RedissonMap> mapsMap = new ConcurrentHashMap<String, RedissonMap>();
private final ConcurrentMap<String, RedissonLock> locksMap = new ConcurrentHashMap<String, RedissonLock>();
@ -19,12 +21,36 @@ public class Redisson {
RedisClient redisClient;
Redisson() {
redisClient = new RedisClient("localhost");
Redisson(String host, int port) {
redisClient = new RedisClient(host, port);
}
public static Redisson create() {
return new Redisson();
return create("localhost");
}
public static Redisson create(String host) {
return create(host, 6379);
}
public static Redisson create(String host, int port) {
return new Redisson(host, port);
}
public <V> List<V> getList(String name) {
RedissonList<V> list = listsMap.get(name);
if (list == null) {
RedisConnection<Object, Object> connection = connect();
list = new RedissonList<V>(connection, name);
RedissonList<V> oldList = listsMap.putIfAbsent(name, list);
if (oldList != null) {
connection.close();
list = oldList;
}
}
return list;
}
public <K, V> ConcurrentMap<K, V> getMap(String name) {
@ -43,10 +69,6 @@ public class Redisson {
return map;
}
RedisConnection<Object, Object> connect() {
return redisClient.connect(codec);
}
public Lock getLock(String name) {
RedissonLock lock = locksMap.get(name);
if (lock == null) {
@ -67,4 +89,8 @@ public class Redisson {
return lock;
}
RedisConnection<Object, Object> connect() {
return redisClient.connect(codec);
}
}

@ -0,0 +1,262 @@
package org.redisson;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import com.lambdaworks.redis.RedisConnection;
public class RedissonList<V> implements List<V> {
private RedisConnection<Object, Object> connection;
private String name;
RedissonList(RedisConnection<Object, Object> connection, String name) {
this.connection = connection;
this.name = name;
}
@Override
public int size() {
return connection.llen(name).intValue();
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}
@Override
public Iterator<V> iterator() {
return listIterator();
}
@Override
public Object[] toArray() {
List<V> list = subList(0, size());
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
List<V> list = subList(0, size());
return list.toArray(a);
}
@Override
public boolean add(V e) {
return connection.rpush(name, e) > 1;
}
@Override
public boolean remove(Object o) {
return connection.lrem(name, 1, o) > 0;
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object object : c) {
// TODO optimize - search bulk values at once in range
if (!contains(object)) {
return false;
}
}
return true;
}
@Override
public boolean addAll(Collection<? extends V> c) {
for (V v : c) {
add(v);
}
return true;
}
@Override
public boolean addAll(int index, Collection<? extends V> c) {
for (V v : c) {
add(index++, v);
}
return true;
}
@Override
public boolean removeAll(Collection<?> c) {
boolean result = false;
for (Object object : c) {
boolean res = connection.lrem(name, 0, object) > 0;
if (!result) {
result = res;
}
}
return result;
}
@Override
public boolean retainAll(Collection<?> c) {
boolean changed = false;
for (Iterator<V> iterator = iterator(); iterator.hasNext();) {
V object = iterator.next();
if (!c.contains(object)) {
iterator.remove();
changed = true;
}
}
return changed;
}
@Override
public void clear() {
connection.del(name);
}
@Override
public V get(int index) {
return (V) connection.lindex(name, index);
}
@Override
public V set(int index, V element) {
V prev = get(index);
connection.lset(name, index, element);
return prev;
}
@Override
public void add(int index, V element) {
V value = get(index);
connection.linsert(name, true, value, element);
}
@Override
public V remove(int index) {
V value = get(index);
connection.lrem(name, 1, value);
return value;
}
@Override
public int indexOf(Object o) {
if (isEmpty()) {
return -1;
}
int to = Math.max(size()/100, 1);
for (int i = 0; i < to; i++) {
List<Object> range = connection.lrange(name, i*100, i*100 + 100);
int index = range.indexOf(o);
if (index != -1) {
return index + i*100;
}
}
return -1;
}
@Override
public int lastIndexOf(Object o) {
if (isEmpty()) {
return -1;
}
int to = Math.max(size()/100, 1);
for (int i = 1; i <= to; i++) {
List<Object> range = connection.lrange(name, -i*100, 100);
int index = range.indexOf(o);
if (index != -1) {
return index + i*100;
}
}
return -1;
}
@Override
public ListIterator<V> listIterator() {
return listIterator(0);
}
@Override
public ListIterator<V> listIterator(final int ind) {
return new ListIterator<V>() {
private int currentIndex = ind - 1;
private boolean removeExecuted;
@Override
public boolean hasNext() {
int size = size();
return currentIndex+1 < size && size > 0;
}
@Override
public V next() {
if (!hasNext()) {
throw new NoSuchElementException("No such element at index " + currentIndex);
}
currentIndex++;
removeExecuted = false;
return RedissonList.this.get(currentIndex);
}
@Override
public void remove() {
if (removeExecuted) {
throw new IllegalStateException("Element been already deleted");
}
RedissonList.this.remove(currentIndex);
removeExecuted = true;
}
@Override
public boolean hasPrevious() {
int size = size();
return currentIndex-1 < size && size > 0;
}
@Override
public V previous() {
if (!hasPrevious()) {
throw new NoSuchElementException("No such element at index " + currentIndex);
}
currentIndex--;
removeExecuted = false;
return RedissonList.this.get(currentIndex);
}
@Override
public int nextIndex() {
return currentIndex + 1;
}
@Override
public int previousIndex() {
return currentIndex - 1;
}
@Override
public void set(V e) {
RedissonList.this.set(currentIndex, e);
}
@Override
public void add(V e) {
RedissonList.this.add(currentIndex, e);
}
};
}
@Override
public List<V> subList(int fromIndex, int toIndex) {
return (List<V>) connection.lrange(name, fromIndex, toIndex);
}
}

@ -0,0 +1,36 @@
package org.redisson;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
public class RedissonListTest {
@Test
public void testSize() {
Redisson redisson = Redisson.create();
List<String> list = redisson.getList("list");
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
Assert.assertThat(list, Matchers.contains("1", "2", "3", "4", "5", "6"));
list.remove("2");
Assert.assertThat(list, Matchers.contains("1", "3", "4", "5", "6"));
clear(list);
}
private void clear(List<?> list) {
list.clear();
Assert.assertEquals(0, list.size());
}
}
Loading…
Cancel
Save