package htsjdk.samtools.cram.paralell; import htsjdk.samtools.SAMFormatException; import htsjdk.samtools.cram.io.InputStreamUtils; import htsjdk.samtools.util.BinaryCodec; import htsjdk.samtools.util.Log; import htsjdk.samtools.util.RuntimeEOFException; import htsjdk.samtools.util.RuntimeIOException; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.function.Supplier; class Bam_OBA_Supplier implements Supplier<OrderedByteArray> { private Log log = Log.getInstance(Bam_OBA_Supplier.class); private BufferedInputStream is; private long order = 0; private BinaryCodec codec; private ByteArrayOutputStream baos; private int refId; private int recordCounter; public Bam_OBA_Supplier(BufferedInputStream is) { this.is = is; codec = new BinaryCodec(); codec.setInputStream(is); baos = new ByteArrayOutputStream(); refId = Integer.MIN_VALUE; recordCounter = 0; } @Override public OrderedByteArray get() { while (true) { try { is.mark(8); int recordLength = 0; try { recordLength = codec.readInt(); } catch (RuntimeEOFException e) { // seems legit: if (recordCounter == 0) return null; return flushStripe(baos); } if (recordLength < 8 * 4) { Thread.dumpStack(); throw new SAMFormatException("Invalid record length: " + recordLength); } final int referenceID = codec.readInt(); is.reset(); if (refId != referenceID && refId != Integer.MIN_VALUE && baos.size() > 0) { return flushStripe(baos); } refId = referenceID; byte[] recordData = InputStreamUtils.readFully(is, recordLength + 4); baos.write(recordData); if (recordCounter++ >= 10000 - 1) { return flushStripe(baos); } } catch (IOException e) { throw new RuntimeIOException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } } } private OrderedByteArray flushStripe(ByteArrayOutputStream baos) throws InterruptedException, IOException { OrderedByteArray stripe = new OrderedByteArray(); stripe.bytes = baos.toByteArray(); log.debug(String.format("adding stripe: order=%d, ref=%d, records=%d, bytes=%d", order, refId, recordCounter, stripe.bytes.length)); stripe.order = order++; baos.reset(); recordCounter = 0; return stripe; } }