@Override public final void close() throws IOException { try { if (buffers == null) return; // make local copy, then un-set early final ByteBuffer[] bufs = buffers; unsetBuffers(); if (clones != null) { clones.remove(this); } if (isClone) return; // for extra safety unset also all clones' buffers: if (clones != null) { for (Iterator<ByteBufferIndexInput> it = this.clones.keyIterator(); it.hasNext(); ) { final ByteBufferIndexInput clone = it.next(); assert clone.isClone; clone.unsetBuffers(); } this.clones.clear(); } for (final ByteBuffer b : bufs) { freeBuffer(b); } } finally { unsetBuffers(); } }
@Override public final ByteBufferIndexInput clone() { final ByteBufferIndexInput clone = buildSlice((String) null, 0L, this.length); try { clone.seek(getFilePointer()); } catch (IOException ioe) { throw new AssertionError(ioe); } return clone; }
@Override public void seek(long pos) throws IOException { // necessary in case offset != 0 and pos < 0, but pos >= -offset if (pos < 0L) { throw new IllegalArgumentException("Seeking to negative position: " + this); } super.seek(pos + offset); }
/** Builds the actual sliced IndexInput (may apply extra offset in subclasses). * */ protected ByteBufferIndexInput buildSlice(String sliceDescription, long offset, long length) { if (buffers == null) { throw new AlreadyClosedException("Already closed: " + this); } final ByteBuffer newBuffers[] = buildSlice(buffers, offset, length); final String newResourceDescription = (sliceDescription == null) ? toString() : (toString() + " [slice=" + sliceDescription + "]"); final int ofs = (int) (offset & chunkSizeMask); final ByteBufferIndexInput clone = newCloneInstance(newResourceDescription, newBuffers, ofs, length); clone.isClone = true; // register the new clone in our clone list to clean it up on closing: if (clones != null) { this.clones.put(clone, Boolean.TRUE); } return clone; }