/** Encode virtual file pointer * Upper 48 bits is the byte offset into the compressed stream of a block. * Lower 16 bits is the byte offset into the uncompressed stream inside the block. */ public long getFilePointer(){ return BlockCompressedFilePointerUtil.makeFilePointer(mBlockAddress, numUncompressedBytes); }
/** Encode virtual file pointer * Upper 48 bits is the byte offset into the compressed stream of a block. * Lower 16 bits is the byte offset into the uncompressed stream inside the block. */ public long getFilePointer(){ return BlockCompressedFilePointerUtil.makeFilePointer(mBlockAddress, numUncompressedBytes); }
/** Encode virtual file pointer * Upper 48 bits is the byte offset into the compressed stream of a block. * Lower 16 bits is the byte offset into the uncompressed stream inside the block. */ public long getFilePointer(){ return BlockCompressedFilePointerUtil.makeFilePointer(mBlockAddress, numUncompressedBytes); }
/** * @param blockAddress File offset of start of BGZF block. * @return Virtual file pointer that points to the start of a BGZF block. */ public static long makeFilePointer(final long blockAddress) { return makeFilePointer(blockAddress, 0); }
/** * @param blockAddress File offset of start of BGZF block. * @return Virtual file pointer that points to the start of a BGZF block. */ public static long makeFilePointer(final long blockAddress) { return makeFilePointer(blockAddress, 0); }
/** * @return virtual file pointer that can be passed to seek() to return to the current position. This is * not an actual byte offset, so arithmetic on file pointers cannot be done to determine the distance between * the two. */ public long getFilePointer() { if (mCurrentOffset == mCurrentBlock.length) { // If current offset is at the end of the current block, file pointer should point // to the beginning of the next block. return BlockCompressedFilePointerUtil.makeFilePointer(mBlockAddress + mLastBlockLength, 0); } return BlockCompressedFilePointerUtil.makeFilePointer(mBlockAddress, mCurrentOffset); }
/** * @return virtual file pointer that can be passed to seek() to return to the current position. This is * not an actual byte offset, so arithmetic on file pointers cannot be done to determine the distance between * the two. */ public long getFilePointer() { if (mCurrentBlock == null) { // Haven't read anything yet = at start of stream return BlockCompressedFilePointerUtil.makeFilePointer(0, 0); } if (mCurrentOffset > 0 && mCurrentOffset == mCurrentBlock.mBlock.length) { // If current offset is at the end of the current block, file // pointer should point // to the beginning of the next block. return BlockCompressedFilePointerUtil.makeFilePointer(mCurrentBlock.mBlockAddress + mCurrentBlock.mBlockCompressedSize, 0); } return BlockCompressedFilePointerUtil.makeFilePointer(mCurrentBlock.mBlockAddress, mCurrentOffset); }
/** * @return virtual file pointer that can be passed to seek() to return to the current position. This is * not an actual byte offset, so arithmetic on file pointers cannot be done to determine the distance between * the two. */ public long getFilePointer() { if (mCurrentBlock == null) { // Haven't read anything yet = at start of stream return BlockCompressedFilePointerUtil.makeFilePointer(0, 0); } if (mCurrentOffset > 0 && mCurrentOffset == mCurrentBlock.mBlock.length) { // If current offset is at the end of the current block, file // pointer should point // to the beginning of the next block. return BlockCompressedFilePointerUtil.makeFilePointer(mCurrentBlock.mBlockAddress + mCurrentBlock.mBlockCompressedSize, 0); } return BlockCompressedFilePointerUtil.makeFilePointer(mCurrentBlock.mBlockAddress, mCurrentOffset); }
/** * @return virtual file pointer that can be passed to seek() to return to the current position. This is * not an actual byte offset, so arithmetic on file pointers cannot be done to determine the distance between * the two. */ public long getFilePointer() { if (mCurrentBlock == null) { // Haven't read anything yet = at start of stream return BlockCompressedFilePointerUtil.makeFilePointer(0, 0); } if (mCurrentOffset > 0 && mCurrentOffset == mCurrentBlock.getUncompressedBlock().length) { // If current offset is at the end of the current block, file // pointer should point // to the beginning of the next block. return BlockCompressedFilePointerUtil.makeFilePointer(mCurrentBlock.getBlockAddress() + mCurrentBlock.getBlockCompressedSize(), 0); } return BlockCompressedFilePointerUtil.makeFilePointer(mCurrentBlock.getBlockAddress(), mCurrentOffset); }
@Test(dataProvider = "badInputs", expectedExceptions = IllegalArgumentException.class) public void negativeTests(long blockAddress, int blockOffset) { BlockCompressedFilePointerUtil.makeFilePointer(blockAddress, blockOffset); Assert.assertFalse(true, "Should not get here."); }
try { if (uncompressedOffset == 0) { return BlockCompressedFilePointerUtil.makeFilePointer(0, 0); return BlockCompressedFilePointerUtil.makeFilePointer( entries.get(pos).getCompressedOffset(), return BlockCompressedFilePointerUtil.makeFilePointer(0, Math.toIntExact(uncompressedOffset)); return BlockCompressedFilePointerUtil.makeFilePointer(indexEntry.getCompressedOffset(), blockOffset); } catch (ArithmeticException e) { throw new IllegalArgumentException("Cannot handle offsets within blocks larger than " + Integer.MAX_VALUE, e);
/** * Return a chunk that corresponds to the given range in the data file. Note that the chunk does not necessarily * completely cover the given range, however this method will map a set of contiguous, non-overlapping file ranges * that cover the whole data file to a set of contiguous, non-overlapping chunks that cover the whole data file. * * @param splitStart the start of the file range (inclusive) * @param splitEnd the start of the file range (exclusive) * @return a chunk whose virtual start is at the first alignment start position that is greater than or equal to the * given split start position, and whose virtual end is at the first alignment start position that is greater than * or equal to the given split end position, or null if the chunk would be empty. * @see #split(long) */ public Chunk getChunk(final long splitStart, final long splitEnd) { if (splitStart >= splitEnd) { throw new IllegalArgumentException(String.format("Split start (%s) must be less than end (%s)", splitStart, splitEnd)); } final long lastVirtualOffset = virtualOffsets[virtualOffsets.length - 1]; final long maxEnd = BlockCompressedFilePointerUtil.getBlockAddress(lastVirtualOffset); final long actualSplitStart = Math.min(splitStart, maxEnd); final long actualSplitEnd = Math.min(splitEnd, maxEnd); final long virtualSplitStart = BlockCompressedFilePointerUtil.makeFilePointer(actualSplitStart); final long virtualSplitEnd = BlockCompressedFilePointerUtil.makeFilePointer(actualSplitEnd); final long virtualSplitStartAlignment = ceiling(virtualSplitStart); final long virtualSplitEndAlignment = ceiling(virtualSplitEnd); if (virtualSplitStartAlignment == virtualSplitEndAlignment) { return null; } return new Chunk(virtualSplitStartAlignment, virtualSplitEndAlignment); }
try { if (uncompressedOffset == 0) { return BlockCompressedFilePointerUtil.makeFilePointer(0, 0); return BlockCompressedFilePointerUtil.makeFilePointer( entries.get(pos).getCompressedOffset(), return BlockCompressedFilePointerUtil.makeFilePointer(0, Math.toIntExact(uncompressedOffset)); return BlockCompressedFilePointerUtil.makeFilePointer(indexEntry.getCompressedOffset(), blockOffset); } catch (ArithmeticException e) { throw new IllegalArgumentException("Cannot handle offsets within blocks larger than " + Integer.MAX_VALUE, e);
/** * Return a chunk that corresponds to the given range in the data file. Note that the chunk does not necessarily * completely cover the given range, however this method will map a set of contiguous, non-overlapping file ranges * that cover the whole data file to a set of contiguous, non-overlapping chunks that cover the whole data file. * * @param splitStart the start of the file range (inclusive) * @param splitEnd the start of the file range (exclusive) * @return a chunk whose virtual start is at the first alignment start position that is greater than or equal to the * given split start position, and whose virtual end is at the first alignment start position that is greater than * or equal to the given split end position, or null if the chunk would be empty. * @see #split(long) */ public Chunk getChunk(final long splitStart, final long splitEnd) { if (splitStart >= splitEnd) { throw new IllegalArgumentException(String.format("Split start (%s) must be less than end (%s)", splitStart, splitEnd)); } final long lastVirtualOffset = virtualOffsets[virtualOffsets.length - 1]; final long maxEnd = BlockCompressedFilePointerUtil.getBlockAddress(lastVirtualOffset); final long actualSplitStart = Math.min(splitStart, maxEnd); final long actualSplitEnd = Math.min(splitEnd, maxEnd); final long virtualSplitStart = BlockCompressedFilePointerUtil.makeFilePointer(actualSplitStart); final long virtualSplitEnd = BlockCompressedFilePointerUtil.makeFilePointer(actualSplitEnd); final long virtualSplitStartAlignment = ceiling(virtualSplitStart); final long virtualSplitEndAlignment = ceiling(virtualSplitEnd); if (virtualSplitStartAlignment == virtualSplitEndAlignment) { return null; } return new Chunk(virtualSplitStartAlignment, virtualSplitEndAlignment); }
@Test public void testEmptyBam() throws Exception { final long bamFileSize = EMPTY_BAM_FILE.length(); final SBIIndex index1 = fromBAMFile(EMPTY_BAM_FILE, SBIIndexWriter.DEFAULT_GRANULARITY); final SBIIndex index2 = fromSAMRecords(EMPTY_BAM_FILE, SBIIndexWriter.DEFAULT_GRANULARITY); Assert.assertEquals(index1, index2); Assert.assertEquals(index1.dataFileLength(), bamFileSize); Assert.assertEquals(index2.dataFileLength(), bamFileSize); // the splitting index for a BAM with no records has a single entry that is just the length of the BAM file Assert.assertEquals(index1.getVirtualOffsets(), new long[] { BlockCompressedFilePointerUtil.makeFilePointer(bamFileSize) }); Assert.assertEquals(index1.getVirtualOffsets(), new long[] { BlockCompressedFilePointerUtil.makeFilePointer(bamFileSize) }); }
/** * Create the virtual file pointer, and also assert that is can be converted back into the input parameters. * @param blockAddress * @param blockOffset * @return block compressed file pointer */ private long makeFilePointer(long blockAddress, int blockOffset) { final long ret = BlockCompressedFilePointerUtil.makeFilePointer(blockAddress, blockOffset); Assert.assertEquals(BlockCompressedFilePointerUtil.getBlockAddress(ret), blockAddress); Assert.assertEquals(BlockCompressedFilePointerUtil.getBlockOffset(ret), blockOffset); Assert.assertEquals(BlockCompressedFilePointerUtil.compare(ret, ret), 0); return ret; }
private SAMRecord getReadAtOffset(final File bamFile, final long virtualOffset) { final Chunk chunk = new Chunk(virtualOffset, BlockCompressedFilePointerUtil.makeFilePointer(bamFile.length())); try (CloseableIterator<SAMRecord> iterator = bamFileReader(bamFile).getIterator(new BAMFileSpan(chunk))) { Assert.assertTrue(iterator.hasNext()); return iterator.next(); } }