use of org.apache.geode.redis.internal.ByteArrayWrapper in project geode by apache.
the class LSetExecutor method executeCommand.
@Override
public void executeCommand(Command command, ExecutionHandlerContext context) {
List<byte[]> commandElems = command.getProcessedCommand();
if (commandElems.size() < 4) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.LSET));
return;
}
ByteArrayWrapper key = command.getKey();
byte[] indexArray = commandElems.get(2);
byte[] value = commandElems.get(3);
int index;
checkDataType(key, RedisDataType.REDIS_LIST, context);
Region<Integer, ByteArrayWrapper> keyRegion = getRegion(context, key);
if (keyRegion == null) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_INDEX));
return;
}
try {
index = Coder.bytesToInt(indexArray);
} catch (NumberFormatException e) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_NOT_NUMERIC));
return;
}
int listSize = keyRegion.size() - LIST_EMPTY_SIZE;
if (index < 0)
index += listSize;
if (index < 0 || index > listSize) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_INDEX));
return;
}
Integer indexKey;
try {
indexKey = getIndexKey(context, key, index);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (indexKey == null) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_INDEX));
return;
}
if (index == listSize)
indexKey++;
keyRegion.put(indexKey, new ByteArrayWrapper(value));
command.setResponse(Coder.getSimpleStringResponse(context.getByteBufAllocator(), SUCCESS));
}
use of org.apache.geode.redis.internal.ByteArrayWrapper in project geode by apache.
the class ListExecutor method pushElements.
/**
* Helper method to be used by the push commands to push elements onto a list. Because our current
* setup requires non trivial code to push elements in to a Region, I wanted all the push code to
* reside in one place.
*
* @param key Name of the list
* @param commandElems Pieces of the command, this is where the elements that need to be pushed
* live
* @param startIndex The index to start with in the commandElems list, inclusive
* @param endIndex The index to end with in the commandElems list, exclusive
* @param keyRegion Region of list
* @param pushType ListDirection.LEFT || ListDirection.RIGHT
* @param context Context of this push
*/
protected void pushElements(ByteArrayWrapper key, List<byte[]> commandElems, int startIndex, int endIndex, Region keyRegion, ListDirection pushType, ExecutionHandlerContext context) {
String indexKey = pushType == ListDirection.LEFT ? "head" : "tail";
String oppositeKey = pushType == ListDirection.RIGHT ? "head" : "tail";
Integer index = (Integer) keyRegion.get(indexKey);
Integer opp = (Integer) keyRegion.get(oppositeKey);
if (index != opp)
// Subtract index if left push, add if right
index += pushType == ListDirection.LEFT ? -1 : 1;
for (int i = startIndex; i < endIndex; i++) {
byte[] value = commandElems.get(i);
ByteArrayWrapper wrapper = new ByteArrayWrapper(value);
/*
*
* First, use the start index to attempt to insert the value into the Region
*
*/
Object oldValue;
do {
oldValue = keyRegion.putIfAbsent(index, wrapper);
if (oldValue != null) {
// Subtract index if left push, add if
index += pushType == ListDirection.LEFT ? -1 : 1;
// right push
}
} while (oldValue != null);
/*
*
* Next, update the index in the meta data region. Keep trying to replace the existing index
* unless the index is further out than previously inserted, that's ok. Example below:
*
* ********************** LPUSH/LPUSH *************************** Push occurring at the same
* time, further index update first | This push | | | | V V [-4] [-3] [-2] [-1] [0] [1] [2]
*
* In this case, -4 would already exist in the meta data region, therefore we do not try to
* put -3 in the meta data region because a further index is already there.
* ***************************************************************
*
* Another example
*
* ********************** LPUSH/LPOP ***************************** This push | Simultaneous
* LPOP, meta data head index already updated to -2 | | | | V V [-4] [X] [-2] [-1] [0] [1] [2]
*
* In this case, -2 would already exist in the meta data region, but we need to make sure the
* element at -4 is visible to all other threads so we will attempt to change the index to -4
* as long as it is greater than -4
* ***************************************************************
*
*/
boolean indexSet = false;
do {
Integer existingIndex = (Integer) keyRegion.get(indexKey);
if ((pushType == ListDirection.RIGHT && existingIndex < index) || (pushType == ListDirection.LEFT && existingIndex > index))
indexSet = keyRegion.replace(indexKey, existingIndex, index);
else
break;
} while (!indexSet);
}
}
use of org.apache.geode.redis.internal.ByteArrayWrapper in project geode by apache.
the class ZCardExecutor method executeCommand.
@Override
public void executeCommand(Command command, ExecutionHandlerContext context) {
List<byte[]> commandElems = command.getProcessedCommand();
if (commandElems.size() < 2) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ArityDef.ZCARD));
return;
}
ByteArrayWrapper key = command.getKey();
Region<ByteArrayWrapper, DoubleWrapper> keyRegion = getRegion(context, key);
checkDataType(key, RedisDataType.REDIS_SORTEDSET, context);
if (keyRegion == null)
command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), NOT_EXISTS));
else
command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), keyRegion.size()));
}
use of org.apache.geode.redis.internal.ByteArrayWrapper in project geode by apache.
the class ZRangeExecutor method executeCommand.
@Override
public void executeCommand(Command command, ExecutionHandlerContext context) {
List<byte[]> commandElems = command.getProcessedCommand();
if (commandElems.size() < 4) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), getArgsError()));
return;
}
boolean withScores = false;
if (commandElems.size() >= 5) {
byte[] fifthElem = commandElems.get(4);
withScores = Coder.bytesToString(fifthElem).equalsIgnoreCase("WITHSCORES");
}
ByteArrayWrapper key = command.getKey();
checkDataType(key, RedisDataType.REDIS_SORTEDSET, context);
Region<ByteArrayWrapper, DoubleWrapper> keyRegion = getRegion(context, key);
if (keyRegion == null) {
command.setResponse(Coder.getEmptyArrayResponse(context.getByteBufAllocator()));
return;
}
int start;
int stop;
int sSetSize = keyRegion.size();
try {
byte[] startArray = commandElems.get(2);
byte[] stopArray = commandElems.get(3);
start = Coder.bytesToInt(startArray);
stop = Coder.bytesToInt(stopArray);
} catch (NumberFormatException e) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), ERROR_NOT_NUMERIC));
return;
}
start = getBoundedStartIndex(start, sSetSize);
stop = getBoundedEndIndex(stop, sSetSize);
if (start > stop || start == sSetSize) {
command.setResponse(Coder.getEmptyArrayResponse(context.getByteBufAllocator()));
return;
}
if (stop == sSetSize)
stop--;
List<?> list;
try {
list = getRange(context, key, start, stop);
} catch (Exception e) {
throw new RuntimeException(e);
}
command.setResponse(Coder.zRangeResponse(context.getByteBufAllocator(), list, withScores));
}
use of org.apache.geode.redis.internal.ByteArrayWrapper in project geode by apache.
the class ZRankExecutor method executeCommand.
@Override
public void executeCommand(Command command, ExecutionHandlerContext context) {
List<byte[]> commandElems = command.getProcessedCommand();
if (commandElems.size() < 3) {
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), getArgsError()));
return;
}
ByteArrayWrapper key = command.getKey();
checkDataType(key, RedisDataType.REDIS_SORTEDSET, context);
Region<ByteArrayWrapper, DoubleWrapper> keyRegion = getRegion(context, key);
if (keyRegion == null) {
command.setResponse(Coder.getNilResponse(context.getByteBufAllocator()));
return;
}
ByteArrayWrapper member = new ByteArrayWrapper(commandElems.get(2));
DoubleWrapper value = keyRegion.get(member);
if (value == null) {
command.setResponse(Coder.getNilResponse(context.getByteBufAllocator()));
return;
}
int rank;
try {
rank = getRange(context, key, member, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), rank));
}
Aggregations