internal static List <DiskRange> getStreamBuffers(DiskRangeList range, long offset, long length) { // This assumes sorted ranges (as do many other parts of ORC code. List <DiskRange> buffers = new List <DiskRange>(); if (length == 0) { return(buffers); } long streamEnd = offset + length; bool inRange = false; while (range != null) { if (!inRange) { if (range.getEnd() <= offset) { range = range.next; continue; // Skip until we are in range. } inRange = true; if (range.getOffset() < offset) { // Partial first buffer, add a slice of it. buffers.Add(range.sliceAndShift(offset, Math.Min(streamEnd, range.getEnd()), -offset)); if (range.getEnd() >= streamEnd) { break; // Partial first buffer is also partial last buffer. } range = range.next; continue; } } else if (range.getOffset() >= streamEnd) { break; } if (range.getEnd() > streamEnd) { // Partial last buffer (may also be the first buffer), add a slice of it. buffers.Add(range.sliceAndShift(range.getOffset(), streamEnd, -offset)); break; } // Buffer that belongs entirely to one stream. // TODO: ideally we would want to reuse the object and remove it from the list, but we cannot // because bufferChunks is also used by clearStreams for zcr. Create a useless dup. buffers.Add(range.sliceAndShift(range.getOffset(), range.getEnd(), -offset)); if (range.getEnd() == streamEnd) { break; } range = range.next; } return(buffers); }
/** * Read the list of ranges from the file. * @param file the file to read * @param base the base of the stripe * @param ranges the disk ranges within the stripe to read * @return the bytes read for each disk range, which is the same length as * ranges * @ */ static DiskRangeList readDiskRanges(Stream file, long @base, DiskRangeList range, bool doForceDirect) { if (range == null) { return(null); } DiskRangeList prev = range.prev; if (prev == null) { prev = new DiskRangeList.MutateHelper(range); } while (range != null) { if (range.hasData()) { range = range.next; continue; } int len = (int)(range.getEnd() - range.getOffset()); long off = range.getOffset(); if (doForceDirect) { file.Seek(@base + off, SeekOrigin.Current); ByteBuffer directBuf = ByteBuffer.allocateDirect(len); readDirect(file, len, directBuf); range = range.replaceSelfWith(new RecordReaderImpl.BufferChunk(directBuf, range.getOffset())); } else { byte[] buffer = new byte[len]; file.readFully((@base + off), buffer, 0, buffer.Length); range = range.replaceSelfWith(new RecordReaderImpl.BufferChunk(ByteBuffer.wrap(buffer), range.getOffset())); } range = range.next; } return(prev.next); }