Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.fiftyonred.mock_jedis.MockStorage Maven / Gradle / Ivy
package com.fiftyonred.mock_jedis;
import com.fiftyonred.utils.WildcardMatcher;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.SortingParams;
import redis.clients.jedis.exceptions.JedisDataException;
import java.util.*;
import static com.fiftyonred.mock_jedis.DataContainer.CHARSET;
public class MockStorage {
private static final int NUM_DBS = 16;
public static final long MILLISECONDS_IN_SECOND = 1000L;
private final WildcardMatcher wildcardMatcher = new WildcardMatcher();
private final List> allKeys;
private final List> allStorage;
private final List>> allHashStorage;
private final List>> allListStorage;
private final List>> allSetStorage;
private int currentDB;
private Map keys;
private Map storage;
private Map> hashStorage;
private Map> listStorage;
private Map> setStorage;
public MockStorage() {
allKeys = new ArrayList>(NUM_DBS);
allStorage = new ArrayList>(NUM_DBS);
allHashStorage = new ArrayList>>(NUM_DBS);
allListStorage = new ArrayList>>(NUM_DBS);
allSetStorage = new ArrayList>>(NUM_DBS);
for (int i = 0; i < NUM_DBS; ++i) {
allKeys.add(new HashMap());
allStorage.add(new HashMap());
allHashStorage.add(new HashMap>());
allListStorage.add(new HashMap>());
allSetStorage.add(new HashMap>());
}
select(0);
}
public int getCurrentDB() {
return currentDB;
}
private static T getRandomElementFromSet(final Set set) {
return (T) set.toArray()[(int) (Math.random() * set.size())];
}
public int dbSize() {
return keys.size();
}
public synchronized void flushAll() {
for (int dbNum = 0; dbNum < NUM_DBS; ++dbNum) {
allKeys.get(dbNum).clear();
allStorage.get(dbNum).clear();
allHashStorage.get(dbNum).clear();
allListStorage.get(dbNum).clear();
}
}
public synchronized void flushDB() {
keys.clear();
storage.clear();
hashStorage.clear();
listStorage.clear();
}
public synchronized void rename(final DataContainer oldkey, final DataContainer newkey) {
if (oldkey.equals(newkey)) {
throw new JedisDataException("ERR source and destination objects are the same");
}
final KeyInformation info = keys.get(oldkey);
switch (info.getType()) {
case HASH:
hashStorage.put(newkey, hashStorage.get(oldkey));
hashStorage.remove(oldkey);
break;
case LIST:
listStorage.put(newkey, listStorage.get(oldkey));
listStorage.remove(oldkey);
break;
case SET:
setStorage.put(newkey, setStorage.get(oldkey));
setStorage.remove(oldkey);
break;
case STRING:
default:
storage.put(newkey, storage.get(oldkey));
storage.remove(oldkey);
}
keys.put(newkey, info);
keys.remove(oldkey);
}
public synchronized boolean renamenx(final DataContainer oldkey, final DataContainer newkey) {
if (oldkey.equals(newkey)) {
throw new JedisDataException("ERR source and destination objects are the same");
}
final KeyInformation newInfo = keys.get(newkey);
if (newInfo == null) {
rename(oldkey, newkey);
return true;
}
return false;
}
public synchronized void set(final DataContainer key, final DataContainer value) {
createOrUpdateKey(key, KeyType.STRING, true);
storage.put(key, value);
}
public synchronized boolean setnx(final DataContainer key, final DataContainer value) {
final DataContainer result = getContainerFromStorage(key, false);
if (result == null) {
set(key, value);
return true;
}
return false;
}
public DataContainer get(final DataContainer key) {
return getContainerFromStorage(key, false);
}
public synchronized DataContainer getSet(final DataContainer key, final DataContainer value) {
final DataContainer result = get(key);
set(key, value);
return result;
}
public boolean exists(final DataContainer key) {
return keys.containsKey(key);
}
public KeyType type(final DataContainer key) {
final KeyInformation info = keys.get(key);
return info == null ? null : info.getType();
}
public synchronized boolean move(final DataContainer key, final int dbIndex) {
if (dbIndex < 0 || dbIndex >= NUM_DBS) {
throw new JedisDataException("ERR index out of range");
}
final KeyInformation info = keys.get(key);
if (info == null) {
return false;
} else {
final KeyInformation infoNew = allKeys.get(dbIndex).get(key);
if (infoNew == null) {
allKeys.get(dbIndex).put(key, info);
switch (info.getType()) {
case HASH:
allHashStorage.get(dbIndex).put(key, hashStorage.get(key));
hashStorage.remove(key);
break;
case LIST:
allListStorage.get(dbIndex).put(key, listStorage.get(key));
listStorage.remove(key);
break;
case STRING:
default:
allStorage.get(dbIndex).put(key, storage.get(key));
storage.remove(key);
}
keys.remove(key);
return true;
} else {
return false;
}
}
}
public synchronized DataContainer randomKey() {
return keys.isEmpty() ? null : getRandomElementFromSet(keys.keySet());
}
public synchronized void select(final int dbIndex) {
if (dbIndex < 0 || dbIndex >= NUM_DBS) {
throw new JedisDataException("ERR invalid DB index");
}
currentDB = dbIndex;
keys = allKeys.get(dbIndex);
storage = allStorage.get(dbIndex);
hashStorage = allHashStorage.get(dbIndex);
listStorage = allListStorage.get(dbIndex);
setStorage = allSetStorage.get(dbIndex);
}
public synchronized boolean pexpireAt(final DataContainer key, final long millisecondsTimestamp) {
final KeyInformation info = keys.get(key);
if (info == null || info.isTTLSetAndKeyExpired()) {
return false;
}
info.setExpiration(millisecondsTimestamp);
return true;
}
public synchronized void psetex(final DataContainer key, final int milliseconds, final DataContainer value) {
set(key, value);
pexpireAt(key, System.currentTimeMillis() + milliseconds);
}
public long ttl(final DataContainer key) {
Long pttlInResponse = pttl(key);
if (pttlInResponse == -1L) {
return pttlInResponse;
}
if (pttlInResponse > 0L && pttlInResponse < MILLISECONDS_IN_SECOND) {
pttlInResponse = MILLISECONDS_IN_SECOND;
}
return pttlInResponse / MILLISECONDS_IN_SECOND;
}
public synchronized long append(final DataContainer key, final DataContainer value) {
final DataContainer container = getContainerFromStorage(key, true);
final DataContainer newVal = container.append(value);
set(key, newVal);
return newVal.getString().length();
}
public synchronized long pttl(final DataContainer key) {
final KeyInformation info = keys.get(key);
return info == null ? -1L : info.getTTL();
}
public synchronized boolean persist(final DataContainer key) {
final KeyInformation info = keys.get(key);
if (info.getTTL() == -1) {
return false;
}
info.setExpiration(-1L);
return true;
}
public synchronized List mget(final DataContainer... keys) {
if (keys.length <= 0) {
throw new JedisDataException("ERR wrong number of arguments for 'mget' command");
}
final List result = new ArrayList(keys.length);
for (final DataContainer key : keys) {
result.add(getContainerFromStorage(key, false));
}
return result;
}
public synchronized void mset(final DataContainer... keysvalues) {
final int l = keysvalues.length;
if (l <= 0 || l % 2 != 0) {
throw new JedisDataException("ERR wrong number of arguments for 'mset' command");
}
for (int i = 0; i < l; i += 2) {
set(keysvalues[i], keysvalues[i + 1]);
}
}
public synchronized boolean msetnx(final DataContainer... keysvalues) {
final int l = keysvalues.length;
if (l <= 0 || l % 2 != 0) {
throw new JedisDataException("ERR wrong number of arguments for 'msetnx' command");
}
boolean result = true;
for (int i = 0; i < l; i += 2) {
if (!setnx(keysvalues[i], keysvalues[i + 1])) {
result = false;
}
}
return result;
}
public synchronized long incrBy(final DataContainer key, final long integer) {
final DataContainer val = getContainerFromStorage(key, true);
final long oldValue;
try {
oldValue = val == null || val.getString().isEmpty() ? 0L : Long.parseLong(val.getString());
} catch (final NumberFormatException ignored) {
throw new JedisDataException("ERR value is not an integer or out of range");
}
// check for overflow
if (oldValue > 0L ? integer > Long.MAX_VALUE - oldValue : integer < Long.MIN_VALUE - oldValue) {
throw new JedisDataException("ERR value is not an integer or out of range");
}
final long result = oldValue + integer;
storage.put(key, DataContainer.from(Long.toString(result)));
return result;
}
public synchronized DataContainer incrByFloat(final DataContainer key, final double increment) {
DataContainer val = getContainerFromStorage(key, true);
final double result;
try {
result = val == null || val.getString().isEmpty() ? increment : Double.parseDouble(val.getString()) + increment;
} catch (final NumberFormatException ignored) {
throw new JedisDataException("ERR value is not a valid float");
}
val = DataContainer.from(Double.toString(result));
storage.put(key, val);
return val;
}
private static Comparator makeComparator(final Collection params) {
final Comparator comparator;
final int direction = params.contains(Protocol.Keyword.DESC.name().toLowerCase()) ? -1 : 1;
if (params.contains(Protocol.Keyword.ALPHA.name().toLowerCase())) {
comparator = new Comparator() {
@Override
public int compare(final DataContainer o1, final DataContainer o2) {
return o1.compareTo(o2) * direction;
}
};
} else {
comparator = new Comparator() {
@Override
public int compare(final DataContainer o1, final DataContainer o2) {
final Long i1, i2;
try {
i1 = Long.parseLong(o1.getString());
i2 = Long.parseLong(o2.getString());
} catch (final NumberFormatException e) {
throw new JedisDataException("ERR One or more scores can't be converted into double");
}
return i1.compareTo(i2) * direction;
}
};
}
return comparator;
}
public List sort(final DataContainer key, final SortingParams sortingParameters) {
final List result = new ArrayList();
final KeyInformation info = keys.get(key);
if (info != null) {
switch (info.getType()) {
case LIST:
result.addAll(listStorage.get(key));
break;
case SET:
result.addAll(setStorage.get(key));
break;
case SORTED_SET:
throw new RuntimeException("Not implemented");
default:
throw new JedisDataException("WRONGTYPE Operation against a key holding the wrong kind of value");
}
}
final List params = convertToStrings(sortingParameters.getParams());
Collections.sort(result, makeComparator(params));
final List filteredResult = new ArrayList(result.size());
final int limitpos = params.indexOf(Protocol.Keyword.LIMIT.name().toLowerCase());
if (limitpos >= 0) {
final int start = Math.max(Integer.parseInt(params.get(limitpos + 1)), 0);
final int end = Math.min(Integer.parseInt(params.get(limitpos + 2)) + start, result.size());
for (final DataContainer entry : result.subList(start, end)) {
filteredResult.add(entry);
}
} else {
for (final DataContainer entry : result) {
filteredResult.add(entry);
}
}
return filteredResult;
}
protected static List convertToStrings(final Collection collection) {
final List result = new ArrayList(collection.size());
for (final byte[] entry : collection) {
result.add(new String(entry, CHARSET));
}
return result;
}
public synchronized int sort(final DataContainer key, final SortingParams sortingParameters, final DataContainer dstkey) {
final List sorted = sort(key, sortingParameters);
del(dstkey);
keys.put(dstkey, new KeyInformation(KeyType.LIST));
listStorage.put(dstkey, sorted);
return sorted.size();
}
public int strlen(final DataContainer key) {
final DataContainer val = getContainerFromStorage(key, false);
return val == null ? 0 : val.getString().length();
}
public long del(final DataContainer... keys) {
long result = 0L;
for (final DataContainer key : keys) {
if (del(key)) {
++result;
}
}
return result;
}
public synchronized boolean del(final DataContainer key) {
final KeyInformation info = keys.remove(key);
if (info == null) {
return false;
}
switch (info.getType()) {
case HASH:
hashStorage.remove(key);
break;
case LIST:
listStorage.remove(key);
break;
case SET:
setStorage.remove(key);
break;
case STRING:
default:
storage.remove(key);
}
return true;
}
public DataContainer hget(final DataContainer key, final DataContainer field) {
final Map result = getHashFromStorage(key, false);
if (result == null) {
return null;
}
return result.get(field);
}
public Map hgetAll(final DataContainer key) {
return getHashFromStorage(key, false);
}
public Set hkeys(final DataContainer key) {
final Map result = getHashFromStorage(key, false);
return result == null ? null : result.keySet();
}
public Collection hvals(final DataContainer key) {
final Map result = getHashFromStorage(key, false);
return result == null ? null : result.values();
}
public synchronized boolean hset(final DataContainer key, final DataContainer field, final DataContainer value) {
final Map m = getHashFromStorage(key, true);
final DataContainer previousValue = m.put(field, value);
return previousValue == null;
}
public synchronized boolean hsetnx(final DataContainer key, final DataContainer field, final DataContainer value) {
final Map m = getHashFromStorage(key, true);
if (m.containsKey(field)) {
return false;
}
m.put(field, value);
return true;
}
public List hmget(final DataContainer key, final DataContainer... fields) {
final Map hash = getHashFromStorage(key, false);
if (hash == null) {
return null;
}
final List result = new ArrayList();
for (final DataContainer field : fields) {
result.add(hash.get(field));
}
return result;
}
public synchronized void hmset(final DataContainer key, final Map hash) {
final Map m = getHashFromStorage(key, true);
for (final Map.Entry e : hash.entrySet()) {
m.put(e.getKey(), e.getValue());
}
}
public synchronized long hincrBy(final DataContainer key, final DataContainer field, final long value) {
final Map m = getHashFromStorage(key, true);
DataContainer val = m.get(field);
if (val == null) {
val = DataContainer.from(Long.valueOf(0L).toString());
}
final long result;
try {
result = Long.valueOf(val.getString()) + value;
} catch (final NumberFormatException ignored) {
throw new JedisDataException("ERR value is not an integer or out of range");
}
m.put(field, DataContainer.from(Long.toString(result)));
return result;
}
public synchronized DataContainer hincrByFloat(final DataContainer key, final DataContainer field, final double increment) {
final Map m = getHashFromStorage(key, true);
DataContainer val = m.get(field);
if (val == null) {
val = DataContainer.from(Double.toString(0.0D));
}
final double result;
try {
result = Double.parseDouble(val.toString()) + increment;
} catch (final NumberFormatException ignored) {
throw new JedisDataException("ERR value is not a valid float");
}
final DataContainer resultContainer = DataContainer.from(Double.toString(result));
m.put(field, resultContainer);
return resultContainer;
}
public synchronized long hdel(final DataContainer key, final DataContainer... fields) {
final Map m = getHashFromStorage(key, true);
long result = 0L;
for (final DataContainer currentField : fields) {
if (m.remove(currentField) != null) {
++result;
}
}
return result;
}
public boolean hexists(final DataContainer key, final DataContainer field) {
final Map hash = getHashFromStorage(key, false);
return hash != null && hash.containsKey(field);
}
public int hlen(final DataContainer key) {
final Map hash = getHashFromStorage(key, false);
return hash == null ? 0 : hash.size();
}
public synchronized int lpush(final DataContainer key, final DataContainer... string) {
List list = getListFromStorage(key, true);
if (list == null) {
list = new ArrayList();
listStorage.put(key, list);
}
Collections.addAll(list, string);
return list.size();
}
public synchronized DataContainer lpop(final DataContainer key) {
final List list = getListFromStorage(key, true);
return list == null || list.isEmpty() ? null : list.remove(list.size() - 1);
}
public synchronized int llen(final DataContainer key) {
final List list = getListFromStorage(key, false);
return list == null ? 0 : list.size();
}
public synchronized List lrange(final DataContainer key, long start, long end) {
final List full = getListFromStorage(key, false);
final List result = new ArrayList();
if (start < 0L) {
start = Math.max(full.size() + start, 0L);
}
if (end < 0L) {
end = full.size() + end;
}
if (start > full.size() || start > end) {
return Collections.emptyList();
}
end = Math.min(full.size() - 1, end);
for (int i = (int) start; i <= end; i++) {
result.add(full.get(i));
}
return result;
}
public Set keys(final DataContainer pattern) {
final Set result = new HashSet();
for (final DataContainer key : keys.keySet()) {
if (wildcardMatcher.match(key.getString(), pattern.getString())) {
result.add(key);
}
}
return result;
}
protected boolean createOrUpdateKey(final DataContainer key, final KeyType type, final boolean resetTTL) {
KeyInformation info = keys.get(key);
if (info == null) {
info = new KeyInformation(type);
keys.put(key, info);
return true;
} else {
if (info.getType() != type) {
throw new JedisDataException("ERR Operation against a key holding the wrong kind of value");
}
if (resetTTL) {
info.setExpiration(-1L);
}
return false;
}
}
protected DataContainer getContainerFromStorage(final DataContainer key, final boolean createIfNotExist) {
final KeyInformation info = keys.get(key);
if (info == null) {
if (createIfNotExist) {
createOrUpdateKey(key, KeyType.STRING, true);
final DataContainer container = DataContainer.from("");
storage.put(key, container);
return container;
}
return null; // no such key exists
}
if (info.getType() != KeyType.STRING) {
throw new JedisDataException("ERR Operation against a key holding the wrong kind of value");
}
if (info.isTTLSetAndKeyExpired()) {
storage.remove(key);
keys.remove(key);
return null;
}
return storage.get(key);
}
protected Map getHashFromStorage(final DataContainer key, final boolean createIfNotExist) {
final KeyInformation info = keys.get(key);
if (info == null) {
if (createIfNotExist) {
createOrUpdateKey(key, KeyType.HASH, false);
final Map result = new HashMap();
hashStorage.put(key, result);
return result;
}
return null; // no such key exists
}
if (info.getType() != KeyType.HASH) {
throw new JedisDataException("ERR Operation against a key holding the wrong kind of value");
}
if (info.isTTLSetAndKeyExpired()) {
hashStorage.remove(key);
keys.remove(key);
return null;
}
return hashStorage.get(key);
}
protected List getListFromStorage(final DataContainer key, final boolean createIfNotExist) {
final KeyInformation info = keys.get(key);
if (info == null) {
if (createIfNotExist) {
createOrUpdateKey(key, KeyType.LIST, false);
final List result = new ArrayList();
listStorage.put(key, result);
return result;
}
return null; // no such key exists
}
if (info.getType() != KeyType.LIST) {
throw new JedisDataException("ERR Operation against a key holding the wrong kind of value");
}
if (info.isTTLSetAndKeyExpired()) {
listStorage.remove(key);
keys.remove(key);
return null;
}
return listStorage.get(key);
}
protected Set getSetFromStorage(final DataContainer key, final boolean createIfNotExist) {
final KeyInformation info = keys.get(key);
if (info == null) {
if (createIfNotExist) {
createOrUpdateKey(key, KeyType.SET, false);
final Set result = new HashSet();
setStorage.put(key, result);
return result;
}
return null; // no such key exists
}
if (info.getType() != KeyType.SET) {
throw new JedisDataException("ERR Operation against a key holding the wrong kind of value");
}
if (info.isTTLSetAndKeyExpired()) {
setStorage.remove(key);
keys.remove(key);
return null;
}
return setStorage.get(key);
}
public synchronized long sadd(final DataContainer key, final DataContainer... members) {
final Set set = getSetFromStorage(key, true);
long added = 0L;
for (final DataContainer s : members) {
if (set.add(s)) {
added++;
}
}
return added;
}
public synchronized long srem(final DataContainer key, final DataContainer... member) {
final Set set = getSetFromStorage(key, true);
long removed = 0L;
for (final DataContainer s : member) {
if (set.remove(s)) {
++removed;
}
}
return removed;
}
public synchronized int scard(final DataContainer key) {
final Set set = getSetFromStorage(key, true);
return set.size();
}
public synchronized Set sdiff(final DataContainer... keys) {
final int l = keys.length;
if (l <= 0) {
throw new JedisDataException("ERR wrong number of arguments for 'sdiff' command");
}
final Set result = new HashSet(getSetFromStorage(keys[0], true));
for (int i = 1; i < l; ++i) {
final Set set = getSetFromStorage(keys[i], true);
result.removeAll(set);
}
return result;
}
public synchronized int sdiffstore(final DataContainer dstKey, final DataContainer... keys) {
if (keys.length <= 0) {
throw new JedisDataException("ERR wrong number of arguments for 'sdiff' command");
}
final Set diff = sdiff(keys);
final Set dst = getSetFromStorage(dstKey, true);
if (!dst.isEmpty()) {
dst.clear();
}
dst.addAll(diff);
return diff.size();
}
public synchronized Set sinter(final DataContainer... keys) {
final int l = keys.length;
if (l <= 0) {
throw new JedisDataException("ERR wrong number of arguments for 'sinter' command");
}
final Set firstSet = new HashSet(getSetFromStorage(keys[0], true));
for (int i = 1; i < l; ++i) {
final Set set = getSetFromStorage(keys[i], true);
firstSet.retainAll(set);
}
return firstSet;
}
public synchronized int sinterstore(final DataContainer dstKey, final DataContainer... keys) {
if (keys.length <= 0) {
throw new JedisDataException("ERR wrong number of arguments for 'sinterstore' command");
}
final Set inter = sinter(keys);
final Set dst = getSetFromStorage(dstKey, true);
if (!dst.isEmpty()) {
dst.clear();
}
dst.addAll(inter);
return inter.size();
}
public boolean sismember(final DataContainer key, final DataContainer member) {
final Set set = getSetFromStorage(key, false);
return set != null && set.contains(member);
}
public synchronized boolean smove(final DataContainer srckey, final DataContainer dstkey, final DataContainer member) {
final Set src = getSetFromStorage(srckey, false);
final Set dst = getSetFromStorage(dstkey, true);
if (!src.remove(member)) {
return false;
}
dst.add(member);
return true;
}
public synchronized DataContainer spop(final DataContainer key) {
final DataContainer member = srandmember(key);
if (member != null) {
final Set src = getSetFromStorage(key, false);
src.remove(member);
}
return member;
}
public synchronized DataContainer srandmember(final DataContainer key) {
final Set src = getSetFromStorage(key, false);
return src == null ? null : getRandomElementFromSet(src);
}
public synchronized Set smembers(final DataContainer key) {
return getSetFromStorage(key, true);
}
public synchronized Set sunion(final DataContainer... keys) {
final int l = keys.length;
if (l <= 0) {
throw new JedisDataException("ERR wrong number of arguments for 'sunion' command");
}
final Set result = new HashSet(getSetFromStorage(keys[0], true));
for (int i = 1; i < l; ++i) {
final Set set = getSetFromStorage(keys[i], true);
result.addAll(set);
}
return result;
}
public synchronized int sunionstore(final DataContainer dstkey, final DataContainer... keys) {
if (keys.length <= 0) {
throw new JedisDataException("ERR wrong number of arguments for 'sunionstore' command");
}
final Set inter = sunion(keys);
final Set dst = getSetFromStorage(dstkey, true);
if (!dst.isEmpty()) {
dst.clear();
}
dst.addAll(inter);
return inter.size();
}
}