package ezdb.util; import java.nio.ByteBuffer; import java.util.Comparator; import ezdb.serde.Serde; public class Util { public static <H, R> byte[] combine(Serde<H> hashKeySerde, Serde<R> rangeKeySerde, H hashKey, R rangeKey) { byte[] rangeBytes = new byte[0]; if (rangeKey != null) { rangeBytes = rangeKeySerde.toBytes(rangeKey); } return combine(hashKeySerde.toBytes(hashKey), rangeBytes); } /** * Utility function to combine a hash key and range key. Hash/range key pairs * are expected to be persisted in the following byte format: * * <pre> * [4 byte hash key length] * [arbitrary hash key bytes] * [4 byte range key length] * [arbitrary range key bytes] * </pre> * * @param hashKeyBytes * Are the hash key's bytes. * @param rangeKeyBytes * Are the range key's bytes. * @return Returns a byte array defined by the format above. */ public static byte[] combine(byte[] hashKeyBytes, byte[] rangeKeyBytes) { byte[] result = new byte[8 + hashKeyBytes.length + rangeKeyBytes.length]; System.arraycopy(ByteBuffer.allocate(4).putInt(hashKeyBytes.length).array(), 0, result, 0, 4); System.arraycopy(hashKeyBytes, 0, result, 4, hashKeyBytes.length); System.arraycopy(ByteBuffer.allocate(4).putInt(rangeKeyBytes.length).array(), 0, result, 4 + hashKeyBytes.length, 4); System.arraycopy(rangeKeyBytes, 0, result, 8 + hashKeyBytes.length, rangeKeyBytes.length); return result; } public static int compareKeys( Comparator<byte[]> hashKeyComparator, Comparator<byte[]> rangeKeyComparator, byte[] k1, byte[] k2) { // First hash key ByteBuffer k1Buffer = ByteBuffer.wrap(k1); int k1HashKeyLength = k1Buffer.getInt(); byte[] k1HashKeyBytes = new byte[k1HashKeyLength]; k1Buffer.get(k1HashKeyBytes); // Second hash key ByteBuffer k2Buffer = ByteBuffer.wrap(k2); int k2HashKeyLength = k2Buffer.getInt(); byte[] k2HashKeyBytes = new byte[k2HashKeyLength]; k2Buffer.get(k2HashKeyBytes); int hashComparison = hashKeyComparator.compare(k1HashKeyBytes, k2HashKeyBytes); if (rangeKeyComparator != null && hashComparison == 0) { // First range key int k1RangeKeyLength = k1Buffer.getInt(); byte[] k1RangeKeyBytes = new byte[k1RangeKeyLength]; k1Buffer.get(k1RangeKeyBytes); // Second range key int k2RangeKeyLength = k2Buffer.getInt(); byte[] k2RangeKeyBytes = new byte[k2RangeKeyLength]; k2Buffer.get(k2RangeKeyBytes); return rangeKeyComparator.compare(k1RangeKeyBytes, k2RangeKeyBytes); } return hashComparison; } }