Skip to content

Commit

Permalink
RMultimap.get should return RSet or RList interface instead of Set an…
Browse files Browse the repository at this point in the history
…d List. #464
  • Loading branch information
Nikita committed Sep 9, 2016
1 parent 008cd07 commit 951c8dd
Show file tree
Hide file tree
Showing 9 changed files with 627 additions and 562 deletions.
314 changes: 161 additions & 153 deletions redisson/src/main/java/org/redisson/RedissonListMultimap.java

Large diffs are not rendered by default.

222 changes: 97 additions & 125 deletions redisson/src/main/java/org/redisson/RedissonListMultimapCache.java
Expand Up @@ -15,13 +15,12 @@
*/
package org.redisson;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.redisson.api.RFuture;
import org.redisson.api.RList;
import org.redisson.api.RListMultimapCache;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.RedisCommands;
Expand Down Expand Up @@ -50,31 +49,26 @@ public class RedissonListMultimapCache<K, V> extends RedissonListMultimap<K, V>
}

public RFuture<Boolean> containsKeyAsync(Object key) {
try {
byte[] keyState = codec.getMapKeyEncoder().encode(key);
String keyHash = hash(keyState);

String valuesName = getValuesName(keyHash);

return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"local value = redis.call('hget', KEYS[1], ARGV[2]); " +
"if value ~= false then " +
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate <= tonumber(ARGV[1]) then "
+ "return 0;"
+ "end; "
+ "return redis.call('llen', ARGV[3]) > 0 and 1 or 0;" +
"end;" +
"return 0; ",
Arrays.<Object>asList(getName(), getTimeoutSetName()), System.currentTimeMillis(), keyState, valuesName);

} catch (IOException e) {
throw new IllegalArgumentException(e);
}
byte[] keyState = encodeMapKey(key);
String keyHash = hash(keyState);

String valuesName = getValuesName(keyHash);

return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"local value = redis.call('hget', KEYS[1], ARGV[2]); " +
"if value ~= false then " +
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate <= tonumber(ARGV[1]) then "
+ "return 0;"
+ "end; "
+ "return redis.call('llen', ARGV[3]) > 0 and 1 or 0;" +
"end;" +
"return 0; ",
Arrays.<Object>asList(getName(), getTimeoutSetName()), System.currentTimeMillis(), keyState, valuesName);
}

String getTimeoutSetName() {
Expand All @@ -83,119 +77,97 @@ String getTimeoutSetName() {


public RFuture<Boolean> containsValueAsync(Object value) {
try {
byte[] valueState = codec.getMapValueEncoder().encode(value);

return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"local keys = redis.call('hgetall', KEYS[1]); " +
"for i, v in ipairs(keys) do " +
"if i % 2 == 0 then " +
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], keys[i-1]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate > tonumber(ARGV[2]) then " +
"local name = '{' .. KEYS[1] .. '}:' .. v; " +

"local items = redis.call('lrange', name, 0, -1) " +
"for i=1,#items do " +
"if items[i] == ARGV[1] then " +
"return 1; " +
"end; " +
byte[] valueState = encodeMapValue(value);

return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"local keys = redis.call('hgetall', KEYS[1]); " +
"for i, v in ipairs(keys) do " +
"if i % 2 == 0 then " +
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], keys[i-1]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate > tonumber(ARGV[2]) then " +
"local name = '{' .. KEYS[1] .. '}:' .. v; " +

"local items = redis.call('lrange', name, 0, -1) " +
"for i=1,#items do " +
"if items[i] == ARGV[1] then " +
"return 1; " +
"end; " +

"end; " +
"end;" +
"end; " +
"return 0; ",
Arrays.<Object>asList(getName(), getTimeoutSetName()), valueState, System.currentTimeMillis());
} catch (IOException e) {
throw new IllegalArgumentException(e);
}

"end; " +
"end;" +
"end; " +
"return 0; ",
Arrays.<Object>asList(getName(), getTimeoutSetName()), valueState, System.currentTimeMillis());
}

public RFuture<Boolean> containsEntryAsync(Object key, Object value) {
try {
byte[] keyState = codec.getMapKeyEncoder().encode(key);
String keyHash = hash(keyState);
byte[] valueState = codec.getMapValueEncoder().encode(value);

String valuesName = getValuesName(keyHash);
return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate > tonumber(ARGV[1]) then " +
"local items = redis.call('lrange', KEYS[1], 0, -1); " +
"for i = 1, #items do " +
"if items[i] == ARGV[3] then " +
"return 1; " +
"end; " +
byte[] keyState = encodeMapKey(key);
String keyHash = hash(keyState);
byte[] valueState = encodeMapValue(value);

String valuesName = getValuesName(keyHash);
return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate > tonumber(ARGV[1]) then " +
"local items = redis.call('lrange', KEYS[1], 0, -1); " +
"for i = 1, #items do " +
"if items[i] == ARGV[3] then " +
"return 1; " +
"end; " +
"end; " +
"return 0; ",
Arrays.<Object>asList(valuesName, getTimeoutSetName()), System.currentTimeMillis(), keyState, valueState);

} catch (IOException e) {
throw new IllegalArgumentException(e);
}
"end; " +
"end; " +
"return 0; ",
Arrays.<Object>asList(valuesName, getTimeoutSetName()), System.currentTimeMillis(), keyState, valueState);
}

@Override
public List<V> get(K key) {
try {
byte[] keyState = codec.getMapKeyEncoder().encode(key);
String keyHash = hash(keyState);
String valuesName = getValuesName(keyHash);

return new RedissonListMultimapValues<V>(codec, commandExecutor, valuesName, getTimeoutSetName(), key);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
public RList<V> get(K key) {
byte[] keyState = encodeMapKey(key);
String keyHash = hash(keyState);
String valuesName = getValuesName(keyHash);

return new RedissonListMultimapValues<V>(codec, commandExecutor, valuesName, getTimeoutSetName(), key);
}

public RFuture<Collection<V>> getAllAsync(K key) {
try {
byte[] keyState = codec.getMapKeyEncoder().encode(key);
String keyHash = hash(keyState);
String valuesName = getValuesName(keyHash);

return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_LIST,
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate > tonumber(ARGV[1]) then " +
"return redis.call('lrange', KEYS[1], 0, -1); " +
"end; " +
"return {}; ",
Arrays.<Object>asList(valuesName, getTimeoutSetName()), System.currentTimeMillis(), keyState);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}

byte[] keyState = encodeMapKey(key);
String keyHash = hash(keyState);
String valuesName = getValuesName(keyHash);

return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_LIST,
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate > tonumber(ARGV[1]) then " +
"return redis.call('lrange', KEYS[1], 0, -1); " +
"end; " +
"return {}; ",
Arrays.<Object>asList(valuesName, getTimeoutSetName()), System.currentTimeMillis(), keyState);
}

public RFuture<Collection<V>> removeAllAsync(Object key) {
try {
byte[] keyState = codec.getMapKeyEncoder().encode(key);
String keyHash = hash(keyState);

String valuesName = getValuesName(keyHash);
return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_SET,
"redis.call('hdel', KEYS[1], ARGV[1]); " +
"local members = redis.call('lrange', KEYS[2], 0, -1); " +
"redis.call('del', KEYS[2]); " +
"redis.call('zrem', KEYS[3], ARGV[1]); " +
"return members; ",
Arrays.<Object>asList(getName(), valuesName, getTimeoutSetName()), keyState);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
byte[] keyState = encodeMapKey(key);
String keyHash = hash(keyState);

String valuesName = getValuesName(keyHash);
return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_SET,
"redis.call('hdel', KEYS[1], ARGV[1]); " +
"local members = redis.call('lrange', KEYS[2], 0, -1); " +
"redis.call('del', KEYS[2]); " +
"redis.call('zrem', KEYS[3], ARGV[1]); " +
"return members; ",
Arrays.<Object>asList(getName(), valuesName, getTimeoutSetName()), keyState);
}

@Override
Expand Down
Expand Up @@ -30,6 +30,7 @@
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.redisson.api.RFuture;
import org.redisson.api.RList;
Expand Down Expand Up @@ -71,6 +72,54 @@ public RedissonListMultimapValues(Codec codec, CommandAsyncExecutor commandExecu
this.timeoutSetName = timeoutSetName;
this.key = key;
}

@Override
public RFuture<Boolean> clearExpireAsync() {
throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set");
}

@Override
public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) {
throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set");
}

@Override
public RFuture<Boolean> expireAtAsync(long timestamp) {
throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set");
}

@Override
public RFuture<Long> remainTimeToLiveAsync() {
throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set");
}

@Override
public RFuture<Void> renameAsync(String newName) {
throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set");
}

@Override
public RFuture<Boolean> renamenxAsync(String newName) {
throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set");
}

public RFuture<Boolean> deleteAsync() {
return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[1], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if expireDate <= tonumber(ARGV[1]) then "
+ "return 0;"
+ "end; " +
"local res = redis.call('zrem', KEYS[1], ARGV[2]); " +
"if res > 0 then " +
"redis.call('del', KEYS[2]); " +
"end; " +
"return res; ",
Arrays.<Object>asList(timeoutSetName, getName()), System.currentTimeMillis(), key);
}

@Override
public int size() {
Expand Down
45 changes: 23 additions & 22 deletions redisson/src/main/java/org/redisson/RedissonMultimap.java
Expand Up @@ -15,7 +15,6 @@
*/
package org.redisson;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.AbstractCollection;
import java.util.AbstractSet;
Expand All @@ -35,6 +34,7 @@
import org.redisson.client.codec.LongCodec;
import org.redisson.client.codec.ScanCodec;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.client.protocol.decoder.MapScanResult;
import org.redisson.client.protocol.decoder.ScanObjectEntry;
Expand Down Expand Up @@ -156,28 +156,28 @@ public RFuture<Long> fastRemoveAsync(K ... keys) {
return newSucceededFuture(0L);
}

try {
List<Object> mapKeys = new ArrayList<Object>(keys.length);
List<Object> listKeys = new ArrayList<Object>(keys.length + 1);
listKeys.add(getName());
for (K key : keys) {
byte[] keyState = codec.getMapKeyEncoder().encode(key);
mapKeys.add(keyState);
String keyHash = hash(keyState);
String name = getValuesName(keyHash);
listKeys.add(name);
}

return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_LONG,
"local res = redis.call('hdel', KEYS[1], unpack(ARGV)); " +
"if res > 0 then " +
"redis.call('del', unpack(KEYS, 2, #KEYS)); " +
"end; " +
"return res; ",
listKeys, mapKeys.toArray());
} catch (IOException e) {
throw new RuntimeException(e);
List<Object> mapKeys = new ArrayList<Object>(keys.length);
List<Object> listKeys = new ArrayList<Object>(keys.length + 1);
listKeys.add(getName());
for (K key : keys) {
byte[] keyState = encodeMapKey(key);
mapKeys.add(keyState);
String keyHash = hash(keyState);
String name = getValuesName(keyHash);
listKeys.add(name);
}

return fastRemoveAsync(mapKeys, listKeys, RedisCommands.EVAL_LONG);
}

protected <T> RFuture<T> fastRemoveAsync(List<Object> mapKeys, List<Object> listKeys, RedisCommand<T> evalCommandType) {
return commandExecutor.evalWriteAsync(getName(), codec, evalCommandType,
"local res = redis.call('hdel', KEYS[1], unpack(ARGV)); " +
"if res > 0 then " +
"redis.call('del', unpack(KEYS, 2, #KEYS)); " +
"end; " +
"return res; ",
listKeys, mapKeys.toArray());
}

@Override
Expand Down Expand Up @@ -242,6 +242,7 @@ public RFuture<Boolean> clearExpireAsync() {
Arrays.<Object>asList(getName()));
}

@Override
public RFuture<Integer> keySizeAsync() {
return commandExecutor.readAsync(getName(), LongCodec.INSTANCE, RedisCommands.HLEN, getName());
}
Expand Down

0 comments on commit 951c8dd

Please sign in to comment.