final int addLength = additionalLength;
BackendOperation.execute(new Callable<Object>() {
@Override
public Object call() throws Exception {
StaticBuffer oldValueCompress = store.get(key, txh);
StaticBuffer oldValue = decompress(oldValueCompress);
int oldLen = oldValue == null ? 0 : oldValue.length();
int newLen = oldLen + addLength;
Preconditions.checkArgument(newLen < MAX_BYTE_LEN, "New allocation [%s] exceeded max value length [%s] ", newLen, MAX_BYTE_LEN);
ByteBuffer out = ByteBuffer.allocate(newLen);
int oldindex = 0;
int addindex = 0;
int delindex = 0;
while (oldindex < oldLen) {
int collen = fromUnsignedShort(oldValue.getShort(oldindex));
oldindex += COLUMN_LEN_BYTES;
int vallen = oldValue.getInt(oldindex);
oldindex += VALUE_LEN_BYTES;
StaticBuffer col = oldValue.subrange(oldindex, collen);
int cmp = -1;
boolean replace = false;
while (addindex < additions.size() && (cmp = col.compareTo(additions.get(addindex).getColumn())) >= 0) {
//insert before
insert(additions.get(addindex), out);
addindex++;
if (cmp == 0) replace = true;
}
if (delindex < deletions.size() && col.compareTo(deletions.get(delindex)) == 0) {
delindex++;
} else if (!replace) {
insert(col, oldValue.subrange(oldindex + collen, vallen), out);
}
//Iterate out missing deletions
while (delindex < deletions.size() && col.compareTo(deletions.get(delindex)) >= 0) {
delindex++;
}
oldindex += collen + vallen;
}
//Write remaining additions
while (addindex < additions.size()) {
insert(additions.get(addindex), out);
addindex++;
}
out.flip();
if (!out.hasRemaining()) {
store.delete(key, txh);
} else {
StaticBuffer newValue = compress(new StaticByteBuffer(out));
store.replace(key, newValue, oldValueCompress, txh);
}
return null;
}
}, maxMutationRetries, mutationRetryWaitTimeMS);