public void seek(long desired) { if (desired == 0 && bytes.Count == 0) { logEmptySeek(name); return; } int i = 0; foreach (DiskRange curRange in bytes) { if (desired == 0 && curRange.getData().remaining() == 0) { logEmptySeek(name); return; } if (curRange.getOffset() <= desired && (desired - curRange.getOffset()) < curRange.getLength()) { currentOffset = desired; currentRange = i; this.range = curRange.getData().duplicate(); int pos = range.position(); pos += (int)(desired - curRange.getOffset()); // this is why we duplicate this.range.position(pos); return; } ++i; } // if they are seeking to the precise end, go ahead and let them go there int segments = bytes.Count; if (segments != 0 && desired == bytes[segments - 1].getEnd()) { currentOffset = desired; currentRange = segments - 1; DiskRange curRange = bytes[currentRange]; this.range = curRange.getData().duplicate(); int pos = range.position(); pos += (int)(desired - curRange.getOffset()); // this is why we duplicate this.range.position(pos); return; } throw new ArgumentException("Seek in " + name + " to " + desired + " is outside of the data"); }
private void seek(long desired) { if (desired == 0 && bytes.Count == 0) { logEmptySeek(name); return; } int i = 0; foreach (DiskRange range in bytes) { if (range.getOffset() <= desired && desired < range.getEnd()) { currentRange = i; compressed = range.getData().duplicate(); int pos = compressed.position(); pos += (int)(desired - range.getOffset()); compressed.position(pos); currentOffset = desired; return; } ++i; } // if they are seeking to the precise end, go ahead and let them go there int segments = bytes.Count; if (segments != 0 && desired == bytes[segments - 1].getEnd()) { DiskRange range = bytes[segments - 1]; currentRange = segments - 1; compressed = range.getData().duplicate(); compressed.position(compressed.limit()); currentOffset = desired; return; } throw new IOException("Seek outside of data in " + this + " to " + desired); }
/* slices a read only contiguous buffer of chunkLength */ private ByteBuffer slice(int chunkLength) { int len = chunkLength; long oldOffset = currentOffset; ByteBuffer slice; if (compressed.remaining() >= len) { slice = compressed.slice(); // simple case slice.limit(len); currentOffset += len; compressed.position(compressed.position() + len); return(slice); } else if (currentRange >= (bytes.Count - 1)) { // nothing has been modified yet throw new IOException("EOF in " + this + " while trying to read " + chunkLength + " bytes"); } if (LOG.isDebugEnabled()) { LOG.debug(String.Format( "Crossing into next BufferChunk because compressed only has %d bytes (needs %d)", compressed.remaining(), len)); } // we need to consolidate 2 or more buffers into 1 // first copy out compressed buffers ByteBuffer copy = allocateBuffer(chunkLength, compressed.isDirect()); currentOffset += compressed.remaining(); len -= compressed.remaining(); copy.put(compressed); for (int i = currentRange; i < bytes.Count && len > 0; i++) { ++currentRange; if (LOG.isDebugEnabled()) { LOG.debug(String.Format("Read slow-path, >1 cross block reads with {0}", this.ToString())); } DiskRange range = bytes[i]; compressed = range.getData().duplicate(); if (compressed.remaining() >= len) { slice = compressed.slice(); slice.limit(len); copy.put(slice); currentOffset += len; compressed.position(compressed.position() + len); return(copy); } currentOffset += compressed.remaining(); len -= compressed.remaining(); copy.put(compressed); } // restore offsets for exception clarity seek(oldOffset); throw new IOException("EOF in " + this + " while trying to read " + chunkLength + " bytes"); }