public static long decodeLittleEndianFixedWidthLong(ByteBuffer buffer) { return decodeLittleEndianFixedWidthLong(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining()); }
@Override public void transform(byte[] buf, int valueOff, int relIndex) { long adjustment = offsetAdjustments[relIndex]; if (adjustment != 0) { long offset = EncodingHelper.decodeLittleEndianFixedWidthLong(buf, valueOff, offsetNumBytes); offset += adjustment; EncodingHelper.encodeLittleEndianFixedWidthLong(offset, buf, valueOff, offsetNumBytes); } } }
@Override public void hash(ByteBuffer keyBytes, int keySize, byte[] hashBytes) { long key = EncodingHelper.decodeLittleEndianFixedWidthLong(keyBytes); if (hashIndexBits % 8 != 0) { throw new RuntimeException("hashIndexBits must be a multiple of 8"); } long keyBlock = key / NUM_RECORDS_PER_BLOCK; long keyIndex = key % NUM_RECORDS_PER_BLOCK; byte[] keyHashBytes = new byte[keySize]; // Note: this is valid because hashIndexBits must be a multiple of 8 int hashIndexBytes = hashIndexBits / 8; // Encode bytes for key block EncodingHelper.encodeLittleEndianFixedWidthLong(keyBlock, keyHashBytes, keyHashBytes.length - hashIndexBytes, hashIndexBytes); // Encode bytes for key index in block EncodingHelper.encodeLittleEndianFixedWidthLong(keyIndex, keyHashBytes, 0, keyHashBytes.length - hashIndexBytes); for (int i = 0; i < keyHashBytes.length; ++i) { hashBytes[i] = (byte)(0xff & keyHashBytes[keyHashBytes.length - 1 - i]); } } }
public Footer(FileChannel channel, int hashIndexBits) throws IOException { fileSize = channel.size(); final int hashIndexSize = 1 << hashIndexBits; footerLength = hashIndexSize * 8 + 8; byte[] footer = new byte[getFooterLength()]; int read = channel.read(ByteBuffer.wrap(footer), getFileSize() - getFooterLength()); if (read != getFooterLength()) { throw new IOException("Tried to read " + getFooterLength() + " bytes of footer, but only got " + read + " bytes!"); } hashIndex = new long[hashIndexSize]; for (int i = 0; i < getHashIndex().length; i++) { final long offset = EncodingHelper.decodeLittleEndianFixedWidthLong(footer, i * 8, 8); if (offset < -1) { throw new IOException(String.format("Read an unexpectedly negative block offset (%d) at block position %d!", offset, i)); } if (offset != -1 && i > 0 && hashIndex[i-1] != -1 && hashIndex[i-1] >= offset) { throw new IOException(String.format("Discovered an offset inversion! block %d offset: %d, block %d offset: %d", i-1, hashIndex[i-1], i, offset)); } getHashIndex()[i] = offset; } maxUncompressedBufferSize = (int) EncodingHelper.decodeLittleEndianFixedWidthLong(footer, footer.length - 8, 4); if (maxUncompressedBufferSize < 0) { throw new IOException(String.format("Read an invalid max uncompressed buffer size of %d!", maxUncompressedBufferSize)); } maxCompressedBufferSize = (int) EncodingHelper.decodeLittleEndianFixedWidthLong(footer, footer.length - 4, 4); if (maxCompressedBufferSize < 0) { throw new IOException(String.format("Read an invalid max uncompressed buffer size of %d!", maxCompressedBufferSize)); } }
@Test public void testDecodeLittleEndianFixedWidthLong() throws Exception { byte[] arr = new byte[]{1, 0, 0}; assertEquals(1, EncodingHelper.decodeLittleEndianFixedWidthLong(ByteBuffer.wrap(arr))); arr = new byte[]{-1, -1, -1}; assertEquals(0xffffffL, EncodingHelper.decodeLittleEndianFixedWidthLong(ByteBuffer.wrap(arr))); arr = new byte[]{-1, 1, 0}; assertEquals(0x0001ff, EncodingHelper.decodeLittleEndianFixedWidthLong(ByteBuffer.wrap(arr))); }
if (blockCompressionCodec == null) { long recordFileOffset = EncodingHelper.decodeLittleEndianFixedWidthLong(location); long recordFileBlockOffset = EncodingHelper.decodeLittleEndianFixedWidthLong(location.array(), location.arrayOffset() + location.position(), offsetNumBytes); long offsetInBlock = EncodingHelper.decodeLittleEndianFixedWidthLong(location.array(), location.arrayOffset() + location.position() + offsetNumBytes, offsetInBlockNumBytes);