use of com.apple.foundationdb.map.BunchedSerializationException in project fdb-record-layer by FoundationDB.
the class TextIndexBunchedSerializer method deserializeBunch.
@Nonnull
private <T> List<T> deserializeBunch(@Nonnull Tuple key, @Nonnull byte[] data, boolean deserializeValues, @Nonnull BiFunction<Tuple, List<Integer>, T> itemCreator) {
checkPrefix(data);
try {
List<T> list = new ArrayList<>();
ByteBuffer buffer = ByteBuffer.wrap(data);
buffer.position(PREFIX.length);
boolean first = true;
while (buffer.hasRemaining()) {
Tuple entryKey;
if (!first) {
int tupleSize = deserializeVarInt(buffer);
if (tupleSize == 0) {
entryKey = TupleHelpers.EMPTY;
} else {
entryKey = Tuple.fromBytes(data, buffer.position(), tupleSize);
}
buffer.position(buffer.position() + tupleSize);
} else {
entryKey = key;
first = false;
}
List<Integer> entryValue;
if (deserializeValues) {
entryValue = deserializeList(buffer);
} else {
// Don't deserialize the value but advance the pointer as if we had.
entryValue = Collections.emptyList();
int listSize = deserializeVarInt(buffer);
buffer.position(buffer.position() + listSize);
}
list.add(itemCreator.apply(entryKey, entryValue));
}
return Collections.unmodifiableList(list);
} catch (RuntimeException e) {
throw new BunchedSerializationException("unable to deserialize entries", e).setData(data);
}
}
use of com.apple.foundationdb.map.BunchedSerializationException in project fdb-record-layer by FoundationDB.
the class TextIndexBunchedSerializer method serializeEntry.
/**
* Packs a key and value into a byte array. This will write out the tuple and
* position list in a way consistent with the way each entry is serialized by
* {@link #serializeEntries(List)}. Because this serializer supports appending,
* one can take the output of this function and append it to the end of an
* already serialized entry list to produce the serialized form of that list
* with this entry appended to the end.
*
* @param key the key of the map entry
* @param value the value of the map entry
* @return the serialized map entry
* @throws BunchedSerializationException if the value is not monotonically increasing
* non-negative integers or if packing the tuple fails
*/
@Nonnull
@Override
public byte[] serializeEntry(@Nonnull Tuple key, @Nonnull List<Integer> value) {
try {
byte[] serializedKey = key.pack();
int listSize = getListSize(value);
int size = getVarIntSize(serializedKey.length) + serializedKey.length + getVarIntSize(listSize) + listSize;
ByteBuffer buffer = ByteBuffer.allocate(size);
serializeVarInt(buffer, serializedKey.length);
buffer.put(serializedKey);
serializeList(buffer, value, listSize);
return buffer.array();
} catch (RuntimeException e) {
throw new BunchedSerializationException("unable to serialize entry", e).setValue(new AbstractMap.SimpleImmutableEntry<>(key, value));
}
}
use of com.apple.foundationdb.map.BunchedSerializationException in project fdb-record-layer by FoundationDB.
the class TextIndexBunchedSerializer method getListSize.
// Get the size (in bytes) of storing the list. It does *not* include the size
// of the list (which is serialized at its start). It calculates the sizes
// taking into account the fact that they will be delta compressed.
private static int getListSize(@Nonnull List<Integer> list) {
int sum = 0;
int last = 0;
for (int val : list) {
if (val < 0 || val < last) {
throw new BunchedSerializationException("list is not monotonically increasing non-negative integers").setValue(list);
}
sum += getVarIntSize(val - last);
last = val;
}
return sum;
}
use of com.apple.foundationdb.map.BunchedSerializationException in project fdb-record-layer by FoundationDB.
the class TextIndexBunchedSerializer method serializeEntries.
/**
* Packs an entry list into a single byte array. This does so by combining the
* serialized forms of each key and value in the entry list with their
* lengths. Their is a more in-depth explanation of the serialization format
* in the class-level documentation.
*
* @param entries the list of entries to serialize
* @return the serialized entry list
* @throws BunchedSerializationException if the entries are invalid such as if the list is empty
* or contains a list that is not monotonically increasing
*/
@Nonnull
@Override
public byte[] serializeEntries(@Nonnull List<Map.Entry<Tuple, List<Integer>>> entries) {
if (entries.isEmpty()) {
throw new BunchedSerializationException("cannot serialize empty entry list");
}
// Calculate size (to avoid unnecessary allocations)
try {
int size = PREFIX.length;
List<byte[]> serializedKeys = new ArrayList<>(entries.size() - 1);
int[] listSizes = new int[entries.size()];
for (int i = 0; i < entries.size(); i++) {
Map.Entry<Tuple, List<Integer>> entry = entries.get(i);
if (i != 0) {
byte[] serializedKey = entry.getKey().pack();
size += getVarIntSize(serializedKey.length) + serializedKey.length;
serializedKeys.add(serializedKey);
}
int listSize = getListSize(entry.getValue());
listSizes[i] = listSize;
size += getVarIntSize(listSize) + listSize;
}
// Allocate one byte buffer to rule them all and serialize everything to that buffer
ByteBuffer buffer = ByteBuffer.allocate(size);
buffer.put(PREFIX);
for (int i = 0; i < entries.size(); i++) {
if (i != 0) {
byte[] key = serializedKeys.get(i - 1);
serializeVarInt(buffer, key.length);
buffer.put(key);
}
serializeList(buffer, entries.get(i).getValue(), listSizes[i]);
}
return buffer.array();
} catch (RuntimeException e) {
throw new BunchedSerializationException("could not serialize entry list", e).setValue(entries);
}
}
Aggregations