private static long shiftVirtualFilePointer(long virtualFilePointer, long offset) { long blockAddress = BlockCompressedFilePointerUtil.getBlockAddress(virtualFilePointer); int blockOffset = BlockCompressedFilePointerUtil.getBlockOffset(virtualFilePointer); return (blockAddress + offset) << 16 | (long) blockOffset; } }
/** 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 slice */ void recordMetaData(Slice slice) { final int alignmentStart = slice.alignmentStart; if (alignmentStart == SAMRecord.NO_ALIGNMENT_START) { noCoordinateRecords+=slice.nofRecords; return; } final long start = slice.offset; final long end = slice.offset + 0; if (slice.alignmentSpan < 1) { unAlignedRecords += slice.nofRecords; } else { alignedRecords += slice.nofRecords; } if (BlockCompressedFilePointerUtil.compare(start, firstOffset) < 1 || firstOffset == -1) { this.firstOffset = start; } if (BlockCompressedFilePointerUtil.compare(lastOffset, end) < 1) { this.lastOffset = end; } }
/** * 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; }
/** * @return true if vfp2 points to somewhere in the same BGZF block, or the one immediately following vfp1's BGZF block. */ public static boolean areInSameOrAdjacentBlocks(final long vfp1, final long vfp2) { final long block1 = getBlockAddress(vfp1); final long block2 = getBlockAddress(vfp2); return (block1 == block2 || block1 + 1 == block2); }
/** * 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 basicTest() { List<Long> pointers = new ArrayList<Long>(); pointers.add(makeFilePointer(0, 0)); pointers.add(makeFilePointer(0, BlockCompressedFilePointerUtil.MAX_OFFSET)); final long BIG_BLOCK_ADDRESS = 1L << 46; pointers.add(makeFilePointer(BIG_BLOCK_ADDRESS-1, 0)); pointers.add(makeFilePointer(BIG_BLOCK_ADDRESS-1, BlockCompressedFilePointerUtil.MAX_OFFSET)); pointers.add(makeFilePointer(BIG_BLOCK_ADDRESS, 0)); pointers.add(makeFilePointer(BIG_BLOCK_ADDRESS, BlockCompressedFilePointerUtil.MAX_OFFSET)); pointers.add(makeFilePointer(BlockCompressedFilePointerUtil.MAX_BLOCK_ADDRESS, 0)); pointers.add(makeFilePointer(BlockCompressedFilePointerUtil.MAX_BLOCK_ADDRESS, BlockCompressedFilePointerUtil.MAX_OFFSET)); for (int i = 0; i < pointers.size() - 1; ++i) { for (int j = i+1; j < pointers.size(); ++j) { Assert.assertTrue(BlockCompressedFilePointerUtil.compare(pointers.get(i), pointers.get(j)) < 0, BlockCompressedFilePointerUtil.asString(pointers.get(i)) + " should be < " + BlockCompressedFilePointerUtil.asString(pointers.get(j))); Assert.assertTrue(BlockCompressedFilePointerUtil.compare(pointers.get(j), pointers.get(i)) > 0, BlockCompressedFilePointerUtil.asString(pointers.get(j)) + " should be > " + BlockCompressedFilePointerUtil.asString(pointers.get(i))); } } }
if (BlockCompressedFilePointerUtil.areInSameOrAdjacentBlocks(lastChunk.getChunkEnd(), chunkStart)) {
private long ceiling(final long virtualOffset) { int index = Arrays.binarySearch(virtualOffsets, virtualOffset); if (index < 0) { index = -index - 1; if (index == virtualOffsets.length) { long lastVirtualOffset = virtualOffsets[virtualOffsets.length - 1]; throw new IllegalArgumentException(String.format("No virtual offset found for virtual file pointer %s, last virtual offset %s", BlockCompressedFilePointerUtil.asString(virtualOffset), BlockCompressedFilePointerUtil.asString(lastVirtualOffset))); } } return virtualOffsets[index]; }
/** * @return true if vfp2 points to somewhere in the same BGZF block, or the one immediately following vfp1's BGZF block. */ public static boolean areInSameOrAdjacentBlocks(final long vfp1, final long vfp2) { final long block1 = getBlockAddress(vfp1); final long block2 = getBlockAddress(vfp2); return (block1 == block2 || block1 + 1 == block2); }
/** * 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); }
if (BlockCompressedFilePointerUtil.areInSameOrAdjacentBlocks(lastChunk.getChunkEnd(), chunkStart)) {
private long ceiling(final long virtualOffset) { int index = Arrays.binarySearch(virtualOffsets, virtualOffset); if (index < 0) { index = -index - 1; if (index == virtualOffsets.length) { long lastVirtualOffset = virtualOffsets[virtualOffsets.length - 1]; throw new IllegalArgumentException(String.format("No virtual offset found for virtual file pointer %s, last virtual offset %s", BlockCompressedFilePointerUtil.asString(virtualOffset), BlockCompressedFilePointerUtil.asString(lastVirtualOffset))); } } return virtualOffsets[index]; }
private static long shiftVirtualFilePointer(long virtualFilePointer, long offset) { long blockAddress = BlockCompressedFilePointerUtil.getBlockAddress(virtualFilePointer); int blockOffset = BlockCompressedFilePointerUtil.getBlockOffset(virtualFilePointer); return (blockAddress + offset) << 16 | (long) blockOffset; } }
/** * @return true if vfp2 points to somewhere in the same BGZF block, or the one immediately following vfp1's BGZF block. */ public static boolean areInSameOrAdjacentBlocks(final long vfp1, final long vfp2) { final long block1 = getBlockAddress(vfp1); final long block2 = getBlockAddress(vfp2); return (block1 == block2 || block1 + 1 == block2); }
/** 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 slice */ void recordMetaData(Slice slice) { final int alignmentStart = slice.alignmentStart; if (alignmentStart == SAMRecord.NO_ALIGNMENT_START) { noCoordinateRecords+=slice.nofRecords; return; } final long start = slice.offset; final long end = slice.offset + 0; if (slice.alignmentSpan < 1) { unAlignedRecords += slice.nofRecords; } else { alignedRecords += slice.nofRecords; } if (BlockCompressedFilePointerUtil.compare(start, firstOffset) < 1 || firstOffset == -1) { this.firstOffset = start; } if (BlockCompressedFilePointerUtil.compare(lastOffset, end) < 1) { this.lastOffset = end; } }
if (BlockCompressedFilePointerUtil.areInSameOrAdjacentBlocks(lastChunk.getChunkEnd(), chunkStart)) {
private static long shiftVirtualFilePointer(long virtualFilePointer, long offset) { long blockAddress = BlockCompressedFilePointerUtil.getBlockAddress(virtualFilePointer); int blockOffset = BlockCompressedFilePointerUtil.getBlockOffset(virtualFilePointer); return (blockAddress + offset) << 16 | (long) blockOffset; } }
public static long getFileBlock(final long bgzfOffset) { return BlockCompressedFilePointerUtil.getBlockAddress(bgzfOffset); }