Index: lucene/core/src/java/org/apache/lucene/codecs/MultiLevelSkipListReader.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/MultiLevelSkipListReader.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/codecs/MultiLevelSkipListReader.java	(working copy)
@@ -312,5 +312,9 @@
       this.pos =  (int) (pos - pointer);
     }
     
+    @Override
+    public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+      throw new UnsupportedOperationException();
+    }
   }
 }
Index: lucene/core/src/java/org/apache/lucene/store/BufferedChecksumIndexInput.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/BufferedChecksumIndexInput.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/BufferedChecksumIndexInput.java	(working copy)
@@ -74,4 +74,9 @@
   public IndexInput clone() {
     throw new UnsupportedOperationException();
   }
+
+  @Override
+  public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+    throw new UnsupportedOperationException();
+  }
 }
Index: lucene/core/src/java/org/apache/lucene/store/BufferedIndexInput.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/BufferedIndexInput.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/BufferedIndexInput.java	(working copy)
@@ -315,6 +315,11 @@
 
     return clone;
   }
+  
+  @Override
+  public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+    return wrap("SlicedIndexInput(" + sliceDescription + " in " + this + ")", this, offset, length);
+  }
 
   /**
    * Flushes the in-memory buffer to the given output, copying at most
@@ -349,4 +354,62 @@
     }
   }
   
+  /** 
+   * Wraps a portion of a file with buffering. 
+   */
+  public static BufferedIndexInput wrap(String description, IndexInput other, long offset, long length) {
+    return new SlicedIndexInput(description, other, offset, length);
+  }
+  
+  /** 
+   * Implementation of an IndexInput that reads from a portion of a file.
+   */
+  private static final class SlicedIndexInput extends BufferedIndexInput {
+    IndexInput base;
+    long fileOffset;
+    long length;
+    
+    SlicedIndexInput(String sliceDescription, IndexInput base, long offset, long length) {
+      super("SlicedIndexInput(" + sliceDescription + " in " + base + " slice=" + offset + ":" + (offset+length) + ")", BufferedIndexInput.BUFFER_SIZE);
+      if (offset < 0 || length < 0) {
+        throw new IllegalArgumentException();
+      }
+      assert offset + length <= base.length();
+      this.base = base.clone();
+      this.fileOffset = offset;
+      this.length = length;
+    }
+    
+    @Override
+    public SlicedIndexInput clone() {
+      SlicedIndexInput clone = (SlicedIndexInput)super.clone();
+      clone.base = base.clone();
+      clone.fileOffset = fileOffset;
+      clone.length = length;
+      return clone;
+    }
+    
+    @Override
+    protected void readInternal(byte[] b, int offset, int len) throws IOException {
+      long start = getFilePointer();
+      if (start + len > length) {
+        throw new EOFException("read past EOF: " + this);
+      }
+      base.seek(fileOffset + start);
+      base.readBytes(b, offset, len, false);
+    }
+    
+    @Override
+    protected void seekInternal(long pos) {}
+    
+    @Override
+    public void close() throws IOException {
+      base.close();
+    }
+    
+    @Override
+    public long length() {
+      return length;
+    }
+  }
 }
Index: lucene/core/src/java/org/apache/lucene/store/ByteBufferIndexInput.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/ByteBufferIndexInput.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/ByteBufferIndexInput.java	(working copy)
@@ -198,9 +198,6 @@
    * Creates a slice of this index input, with the given description, offset, and length. The slice is seeked to the beginning.
    */
   public final ByteBufferIndexInput slice(String sliceDescription, long offset, long length) {
-    if (isClone) { // well we could, but this is stupid
-      throw new IllegalStateException("cannot slice() " + sliceDescription + " from a cloned IndexInput: " + this);
-    }
     final ByteBufferIndexInput clone = buildSlice(offset, length);
     clone.sliceDescription = sliceDescription;
     try {
Index: lucene/core/src/java/org/apache/lucene/store/CompoundFileDirectory.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/CompoundFileDirectory.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/CompoundFileDirectory.java	(working copy)
@@ -87,7 +87,7 @@
   private final boolean openForWrite;
   private static final Map<String,FileEntry> SENTINEL = Collections.emptyMap();
   private final CompoundFileWriter writer;
-  private final IndexInputSlicer handle;
+  private final IndexInput handle;
   private int version;
   
   /**
@@ -101,7 +101,7 @@
     this.openForWrite = openForWrite;
     if (!openForWrite) {
       boolean success = false;
-      handle = directory.createSlicer(fileName, context);
+      handle = directory.openInput(fileName, context);
       try {
         this.entries = readEntries(directory, fileName);
         success = true;
@@ -192,7 +192,7 @@
     if (entry == null) {
       throw new FileNotFoundException("No sub-file with id " + id + " found (fileName=" + name + " files: " + entries.keySet() + ")");
     }
-    return handle.openSlice(name, entry.offset, entry.length);
+    return handle.slice(name, entry.offset, entry.length);
   }
   
   /** Returns an array of strings, one for each file in the directory. */
@@ -259,28 +259,6 @@
   }
 
   @Override
-  public IndexInputSlicer createSlicer(final String name, IOContext context)
-      throws IOException {
-    ensureOpen();
-    assert !openForWrite;
-    final String id = IndexFileNames.stripSegmentName(name);
-    final FileEntry entry = entries.get(id);
-    if (entry == null) {
-      throw new FileNotFoundException("No sub-file with id " + id + " found (fileName=" + name + " files: " + entries.keySet() + ")");
-    }
-    return new IndexInputSlicer() {
-      @Override
-      public void close() {
-      }
-      
-      @Override
-      public IndexInput openSlice(String sliceDescription, long offset, long length) throws IOException {
-        return handle.openSlice(sliceDescription, entry.offset + offset, length);
-      }
-    };
-  }
-
-  @Override
   public String toString() {
     return "CompoundFileDirectory(file=\"" + fileName + "\" in dir=" + directory + ")";
   }
Index: lucene/core/src/java/org/apache/lucene/store/Directory.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/Directory.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/Directory.java	(working copy)
@@ -17,7 +17,6 @@
  * limitations under the License.
  */
 
-import java.io.EOFException;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.Closeable;
@@ -201,112 +200,7 @@
   }
 
   /**
-   * Creates an {@link IndexInputSlicer} for the given file name.
-   * IndexInputSlicer allows other {@link Directory} implementations to
-   * efficiently open one or more sliced {@link IndexInput} instances from a
-   * single file handle. The underlying file handle is kept open until the
-   * {@link IndexInputSlicer} is closed.
-   * <p>Throws {@link FileNotFoundException} or {@link NoSuchFileException}
-   * if the file does not exist.
-   *
-   * @throws IOException
-   *           if an {@link IOException} occurs
-   * @lucene.internal
-   * @lucene.experimental
-   */
-  public IndexInputSlicer createSlicer(final String name, final IOContext context) throws IOException {
-    ensureOpen();
-    return new IndexInputSlicer() {
-      private final IndexInput base = Directory.this.openInput(name, context);
-      @Override
-      public IndexInput openSlice(String sliceDescription, long offset, long length) {
-        return new SlicedIndexInput("SlicedIndexInput(" + sliceDescription + " in " + base + ")", base, offset, length);
-      }
-      @Override
-      public void close() throws IOException {
-        base.close();
-      }
-    };
-  }
-
-  /**
    * @throws AlreadyClosedException if this Directory is closed
    */
   protected void ensureOpen() throws AlreadyClosedException {}
-  
-  /**
-   * Allows to create one or more sliced {@link IndexInput} instances from a single 
-   * file handle. Some {@link Directory} implementations may be able to efficiently map slices of a file
-   * into memory when only certain parts of a file are required.   
-   * @lucene.internal
-   * @lucene.experimental
-   */
-  public abstract class IndexInputSlicer implements Closeable {
-    /**
-     * Returns an {@link IndexInput} slice starting at the given offset with the given length.
-     */
-    public abstract IndexInput openSlice(String sliceDescription, long offset, long length) throws IOException;
-  }
-  
-  /** Implementation of an IndexInput that reads from a portion of
-   *  a file.
-   */
-  private static final class SlicedIndexInput extends BufferedIndexInput {
-    IndexInput base;
-    long fileOffset;
-    long length;
-    
-    SlicedIndexInput(final String sliceDescription, final IndexInput base, final long fileOffset, final long length) {
-      this(sliceDescription, base, fileOffset, length, BufferedIndexInput.BUFFER_SIZE);
-    }
-    
-    SlicedIndexInput(final String sliceDescription, final IndexInput base, final long fileOffset, final long length, int readBufferSize) {
-      super("SlicedIndexInput(" + sliceDescription + " in " + base + " slice=" + fileOffset + ":" + (fileOffset+length) + ")", readBufferSize);
-      this.base = base.clone();
-      this.fileOffset = fileOffset;
-      this.length = length;
-    }
-    
-    @Override
-    public SlicedIndexInput clone() {
-      SlicedIndexInput clone = (SlicedIndexInput)super.clone();
-      clone.base = base.clone();
-      clone.fileOffset = fileOffset;
-      clone.length = length;
-      return clone;
-    }
-    
-    /** Expert: implements buffer refill.  Reads bytes from the current
-     *  position in the input.
-     * @param b the array to read bytes into
-     * @param offset the offset in the array to start storing bytes
-     * @param len the number of bytes to read
-     */
-    @Override
-    protected void readInternal(byte[] b, int offset, int len) throws IOException {
-      long start = getFilePointer();
-      if(start + len > length)
-        throw new EOFException("read past EOF: " + this);
-      base.seek(fileOffset + start);
-      base.readBytes(b, offset, len, false);
-    }
-    
-    /** Expert: implements seek.  Sets current position in this file, where
-     *  the next {@link #readInternal(byte[],int,int)} will occur.
-     * @see #readInternal(byte[],int,int)
-     */
-    @Override
-    protected void seekInternal(long pos) {}
-    
-    /** Closes the stream to further operations. */
-    @Override
-    public void close() throws IOException {
-      base.close();
-    }
-    
-    @Override
-    public long length() {
-      return length;
-    }
-  }
 }
Index: lucene/core/src/java/org/apache/lucene/store/FileSwitchDirectory.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/FileSwitchDirectory.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/FileSwitchDirectory.java	(working copy)
@@ -166,10 +166,4 @@
   public IndexInput openInput(String name, IOContext context) throws IOException {
     return getDirectory(name).openInput(name, context);
   }
-
-  @Override
-  public IndexInputSlicer createSlicer(String name, IOContext context)
-      throws IOException {
-    return getDirectory(name).createSlicer(name, context);
-  }
 }
Index: lucene/core/src/java/org/apache/lucene/store/IndexInput.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/IndexInput.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/IndexInput.java	(working copy)
@@ -82,4 +82,10 @@
   public IndexInput clone() {
     return (IndexInput) super.clone();
   }
+  
+  /**
+   * Creates a slice of this index input, with the given description, offset, and length. 
+   * The slice is seeked to the beginning.
+   */
+  public abstract IndexInput slice(String sliceDescription, long offset, long length) throws IOException;
 }
Index: lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java	(working copy)
@@ -196,23 +196,6 @@
       return new MMapIndexInput("MMapIndexInput(path=\"" + file.toString() + "\")", c);
     }
   }
-  
-  @Override
-  public IndexInputSlicer createSlicer(String name, IOContext context) throws IOException {
-    final MMapIndexInput full = (MMapIndexInput) openInput(name, context);
-    return new IndexInputSlicer() {
-      @Override
-      public IndexInput openSlice(String sliceDescription, long offset, long length) throws IOException {
-        ensureOpen();
-        return full.slice(sliceDescription, offset, length);
-      }
-      
-      @Override
-      public void close() throws IOException {
-        full.close();
-      }
-    };
-  }
 
   private final class MMapIndexInput extends ByteBufferIndexInput {
     private final boolean useUnmapHack;
Index: lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java	(working copy)
@@ -20,7 +20,6 @@
 import java.io.File;
 import java.io.EOFException;
 import java.io.IOException;
-import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedChannelException; // javadoc @link
 import java.nio.channels.FileChannel;
@@ -83,31 +82,10 @@
     return new NIOFSIndexInput("NIOFSIndexInput(path=\"" + path + "\")", fc, context);
   }
   
-  @Override
-  public IndexInputSlicer createSlicer(final String name,
-      final IOContext context) throws IOException {
-    ensureOpen();
-    final File path = new File(getDirectory(), name);
-    final FileChannel descriptor = FileChannel.open(path.toPath(), StandardOpenOption.READ);
-    return new Directory.IndexInputSlicer() {
-
-      @Override
-      public void close() throws IOException {
-        descriptor.close();
-      }
-
-      @Override
-      public IndexInput openSlice(String sliceDescription, long offset, long length) {
-        return new NIOFSIndexInput("NIOFSIndexInput(" + sliceDescription + " in path=\"" + path + "\" slice=" + offset + ":" + (offset+length) + ")", descriptor, offset,
-            length, BufferedIndexInput.bufferSize(context));
-      }
-    };
-  }
-
   /**
    * Reads bytes with {@link FileChannel#read(ByteBuffer, long)}
    */
-  protected static class NIOFSIndexInput extends BufferedIndexInput {
+  static final class NIOFSIndexInput extends BufferedIndexInput {
     /**
      * The maximum chunk size for reads of 16384 bytes.
      */
@@ -154,6 +132,11 @@
     }
     
     @Override
+    public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+      return new NIOFSIndexInput(sliceDescription, channel, off + offset, length, getBufferSize());
+    }
+
+    @Override
     public final long length() {
       return end - off;
     }
Index: lucene/core/src/java/org/apache/lucene/store/NRTCachingDirectory.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/NRTCachingDirectory.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/NRTCachingDirectory.java	(working copy)
@@ -227,22 +227,6 @@
       return delegate.openInput(name, context);
     }
   }
-
-  @Override
-  public synchronized IndexInputSlicer createSlicer(final String name, final IOContext context) throws IOException {
-    ensureOpen();
-    if (VERBOSE) {
-      System.out.println("nrtdir.openInput name=" + name);
-    }
-    if (cache.fileNameExists(name)) {
-      if (VERBOSE) {
-        System.out.println("  from cache");
-      }
-      return cache.createSlicer(name, context);
-    } else {
-      return delegate.createSlicer(name, context);
-    }
-  }
   
   /** Close this directory, which flushes any cached files
    *  to the delegate and then closes the delegate. */
Index: lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java	(working copy)
@@ -118,4 +118,10 @@
     }
     bufferPosition = (int) (pos % BUFFER_SIZE);
   }
+
+  // TODO: improve this, kinda stupid
+  @Override
+  public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+    return BufferedIndexInput.wrap(sliceDescription, this, offset, length);
+  }
 }
Index: lucene/core/src/java/org/apache/lucene/store/RateLimitedDirectoryWrapper.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/RateLimitedDirectoryWrapper.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/RateLimitedDirectoryWrapper.java	(working copy)
@@ -51,13 +51,6 @@
   }
 
   @Override
-  public IndexInputSlicer createSlicer(String name, IOContext context)
-      throws IOException {
-    ensureOpen();
-    return in.createSlicer(name, context);
-  }
-
-  @Override
   public void copy(Directory to, String src, String dest, IOContext context) throws IOException {
     ensureOpen();
     in.copy(to, src, dest, context);
Index: lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java	(working copy)
@@ -59,32 +59,11 @@
     return new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + path.getPath() + "\")", raf, context);
   }
 
-  @Override
-  public IndexInputSlicer createSlicer(final String name,
-      final IOContext context) throws IOException {
-    ensureOpen();
-    final File file = new File(getDirectory(), name);
-    final RandomAccessFile descriptor = new RandomAccessFile(file, "r");
-    return new IndexInputSlicer() {
-
-      @Override
-      public void close() throws IOException {
-        descriptor.close();
-      }
-
-      @Override
-      public IndexInput openSlice(String sliceDescription, long offset, long length) {
-        return new SimpleFSIndexInput("SimpleFSIndexInput(" + sliceDescription + " in path=\"" + file.getPath() + "\" slice=" + offset + ":" + (offset+length) + ")", descriptor, offset,
-            length, BufferedIndexInput.bufferSize(context));
-      }
-    };
-  }
-
   /**
    * Reads bytes with {@link RandomAccessFile#seek(long)} followed by
    * {@link RandomAccessFile#read(byte[], int, int)}.  
    */
-  protected static class SimpleFSIndexInput extends BufferedIndexInput {
+  static final class SimpleFSIndexInput extends BufferedIndexInput {
     /**
      * The maximum chunk size is 8192 bytes, because {@link RandomAccessFile} mallocs
      * a native buffer outside of stack if the read buffer size is larger.
@@ -130,6 +109,11 @@
     }
     
     @Override
+    public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+      return new SimpleFSIndexInput(sliceDescription, file, off + offset, length, getBufferSize());
+    }
+
+    @Override
     public final long length() {
       return end - off;
     }
Index: lucene/core/src/java/org/apache/lucene/store/TrackingDirectoryWrapper.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/store/TrackingDirectoryWrapper.java	(revision 1595418)
+++ lucene/core/src/java/org/apache/lucene/store/TrackingDirectoryWrapper.java	(working copy)
@@ -50,11 +50,6 @@
     in.copy(to, src, dest, context);
   }
 
-  @Override
-  public Directory.IndexInputSlicer createSlicer(final String name, final IOContext context) throws IOException {
-    return in.createSlicer(name, context);
-  }
-
   // maybe clone before returning.... all callers are
   // cloning anyway....
   public Set<String> getCreatedFiles() {
Index: lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java	(revision 1595418)
+++ lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java	(working copy)
@@ -183,6 +183,12 @@
       }
       return i;
     }
+    
+    @Override
+    public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+      IndexInput slice = delegate.slice(sliceDescription, offset, length);
+      return new FaultyIndexInput(slice);
+    }
   }
 
   // LUCENE-1262
Index: lucene/core/src/test/org/apache/lucene/index/TestIndexInput.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestIndexInput.java	(revision 1595418)
+++ lucene/core/src/test/org/apache/lucene/index/TestIndexInput.java	(working copy)
@@ -20,9 +20,11 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 import org.apache.lucene.util.TestUtil;
+import org.apache.lucene.store.BufferedIndexInput;
 import org.apache.lucene.store.ByteArrayDataInput;
 import org.apache.lucene.store.ByteArrayDataOutput;
 import org.apache.lucene.store.DataInput;
+import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
 import org.apache.lucene.store.RAMDirectory;
@@ -169,34 +171,26 @@
     }
   }
 
-  // this test only checks BufferedIndexInput because MockIndexInput extends BufferedIndexInput
-  public void testBufferedIndexInputRead() throws IOException {
-    IndexInput is = new MockIndexInput(READ_TEST_BYTES);
-    checkReads(is, IOException.class);
-    is.close();
-    is = new MockIndexInput(RANDOM_TEST_BYTES);
-    checkRandomReads(is);
-    is.close();
-  }
-
-  // this test checks the raw IndexInput methods as it uses RAMIndexInput which extends IndexInput directly
+  // this test checks the IndexInput methods of any impl
   public void testRawIndexInputRead() throws IOException {
-    Random random = random();
-    final RAMDirectory dir = new RAMDirectory();
-    IndexOutput os = dir.createOutput("foo", newIOContext(random));
-    os.writeBytes(READ_TEST_BYTES, READ_TEST_BYTES.length);
-    os.close();
-    IndexInput is = dir.openInput("foo", newIOContext(random));
-    checkReads(is, IOException.class);
-    is.close();
+    for (int i = 0; i < 10; i++) {
+      Random random = random();
+      final Directory dir = newDirectory();
+      IndexOutput os = dir.createOutput("foo", newIOContext(random));
+      os.writeBytes(READ_TEST_BYTES, READ_TEST_BYTES.length);
+      os.close();
+      IndexInput is = dir.openInput("foo", newIOContext(random));
+      checkReads(is, IOException.class);
+      is.close();
     
-    os = dir.createOutput("bar", newIOContext(random));
-    os.writeBytes(RANDOM_TEST_BYTES, RANDOM_TEST_BYTES.length);
-    os.close();
-    is = dir.openInput("bar", newIOContext(random));
-    checkRandomReads(is);
-    is.close();
-    dir.close();
+      os = dir.createOutput("bar", newIOContext(random));
+      os.writeBytes(RANDOM_TEST_BYTES, RANDOM_TEST_BYTES.length);
+      os.close();
+      is = dir.openInput("bar", newIOContext(random));
+      checkRandomReads(is);
+      is.close();
+      dir.close();
+    }
   }
 
   public void testByteArrayDataInput() throws IOException {
Index: lucene/core/src/test/org/apache/lucene/index/TestLazyProxSkipping.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestLazyProxSkipping.java	(revision 1595418)
+++ lucene/core/src/test/org/apache/lucene/index/TestLazyProxSkipping.java	(working copy)
@@ -227,6 +227,10 @@
           public SeeksCountingStream clone() {
               return new SeeksCountingStream(this.input.clone());
           }
-      
+
+          @Override
+          public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+            return new SeeksCountingStream(this.input.clone());
+          }
     }
 }
Index: lucene/core/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java	(revision 1595418)
+++ lucene/core/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java	(working copy)
@@ -189,5 +189,9 @@
       return new CountingStream(this.input.clone());
     }
 
+    @Override
+    public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+      return new CountingStream(this.input.slice(sliceDescription, offset, length));
+    }
   }
 }
Index: lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java	(revision 1595418)
+++ lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java	(working copy)
@@ -219,6 +219,11 @@
       public long length() {
         return len;
       }
+      
+      @Override
+      public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+        throw new UnsupportedOperationException();
+      }
     }
 
     public void testSetBufferSize() throws IOException {
Index: lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java	(revision 1595418)
+++ lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java	(working copy)
@@ -32,7 +32,6 @@
     // except those under the 'exclude' list
     Set<Method> exclude = new HashSet<>();
     exclude.add(Directory.class.getMethod("copy", Directory.class, String.class, String.class, IOContext.class));
-    exclude.add(Directory.class.getMethod("createSlicer", String.class, IOContext.class));
     exclude.add(Directory.class.getMethod("openChecksumInput", String.class, IOContext.class));
     for (Method m : FilterDirectory.class.getMethods()) {
       if (m.getDeclaringClass() == Directory.class) {
Index: lucene/core/src/test/org/apache/lucene/store/TestMultiMMap.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/store/TestMultiMMap.java	(revision 1595418)
+++ lucene/core/src/test/org/apache/lucene/store/TestMultiMMap.java	(working copy)
@@ -26,7 +26,6 @@
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.store.Directory.IndexInputSlicer;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.TestUtil;
 
@@ -113,9 +112,9 @@
     io.writeInt(1);
     io.writeInt(2);
     io.close();
-    IndexInputSlicer slicer = mmapDir.createSlicer("bytes", newIOContext(random()));
-    IndexInput one = slicer.openSlice("first int", 0, 4);
-    IndexInput two = slicer.openSlice("second int", 4, 4);
+    IndexInput slicer = mmapDir.openInput("bytes", newIOContext(random()));
+    IndexInput one = slicer.slice("first int", 0, 4);
+    IndexInput two = slicer.slice("second int", 4, 4);
     IndexInput three = one.clone(); // clone of clone
     IndexInput four = two.clone(); // clone of clone
     slicer.close();
@@ -158,9 +157,9 @@
     io.writeInt(1);
     io.writeInt(2);
     io.close();
-    IndexInputSlicer slicer = mmapDir.createSlicer("bytes", newIOContext(random()));
-    IndexInput one = slicer.openSlice("first int", 0, 4);
-    IndexInput two = slicer.openSlice("second int", 4, 4);
+    IndexInput slicer = mmapDir.openInput("bytes", newIOContext(random()));
+    IndexInput one = slicer.slice("first int", 0, 4);
+    IndexInput two = slicer.slice("second int", 4, 4);
     one.close();
     try {
       one.readInt();
@@ -170,7 +169,7 @@
     }
     assertEquals(2, two.readInt());
     // reopen a new slice "one":
-    one = slicer.openSlice("first int", 0, 4);
+    one = slicer.slice("first int", 0, 4);
     assertEquals(1, one.readInt());
     one.close();
     two.close();
@@ -195,8 +194,8 @@
       MMapDirectory mmapDir = new MMapDirectory(createTempDir("testSeekSliceZero"), null, 1<<i);
       IndexOutput io = mmapDir.createOutput("zeroBytes", newIOContext(random()));
       io.close();
-      IndexInputSlicer slicer = mmapDir.createSlicer("zeroBytes", newIOContext(random()));
-      IndexInput ii = slicer.openSlice("zero-length slice", 0, 0);
+      IndexInput slicer = mmapDir.openInput("zeroBytes", newIOContext(random()));
+      IndexInput ii = slicer.slice("zero-length slice", 0, 0);
       ii.seek(0L);
       ii.close();
       slicer.close();
@@ -230,8 +229,8 @@
       random().nextBytes(bytes);
       io.writeBytes(bytes, bytes.length);
       io.close();
-      IndexInputSlicer slicer = mmapDir.createSlicer("bytes", newIOContext(random()));
-      IndexInput ii = slicer.openSlice("full slice", 0, bytes.length);
+      IndexInput slicer = mmapDir.openInput("bytes", newIOContext(random()));
+      IndexInput ii = slicer.slice("full slice", 0, bytes.length);
       byte actual[] = new byte[1<<i];
       ii.readBytes(actual, 0, actual.length);
       assertEquals(new BytesRef(bytes), new BytesRef(actual));
@@ -282,11 +281,11 @@
       ii.readBytes(actual, 0, actual.length);
       ii.close();
       assertEquals(new BytesRef(bytes), new BytesRef(actual));
-      IndexInputSlicer slicer = mmapDir.createSlicer("bytes", newIOContext(random()));
+      IndexInput slicer = mmapDir.openInput("bytes", newIOContext(random()));
       for (int sliceStart = 0; sliceStart < bytes.length; sliceStart++) {
         for (int sliceLength = 0; sliceLength < bytes.length - sliceStart; sliceLength++) {
           byte slice[] = new byte[sliceLength];
-          IndexInput input = slicer.openSlice("bytesSlice", sliceStart, slice.length);
+          IndexInput input = slicer.slice("bytesSlice", sliceStart, slice.length);
           input.readBytes(slice, 0, slice.length);
           input.close();
           assertEquals(new BytesRef(bytes, sliceStart, sliceLength), new BytesRef(slice));
Index: lucene/facet/src/test/org/apache/lucene/facet/SlowRAMDirectory.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/SlowRAMDirectory.java	(revision 1595418)
+++ lucene/facet/src/test/org/apache/lucene/facet/SlowRAMDirectory.java	(working copy)
@@ -118,7 +118,11 @@
       ii.readBytes(b, offset, len);
     }
     
+    // TODO: is it intentional that clone doesnt wrap?
     @Override public IndexInput clone() { return ii.clone(); }
+    @Override public IndexInput slice(String sliceDescription, long offset, long length) throws IOException { 
+      return ii.slice(sliceDescription, offset, length);
+    }
     @Override public void close() throws IOException { ii.close(); }
     @Override public boolean equals(Object o) { return ii.equals(o); }
     @Override public long getFilePointer() { return ii.getFilePointer(); }
Index: lucene/misc/src/java/org/apache/lucene/store/NativeUnixDirectory.java
===================================================================
--- lucene/misc/src/java/org/apache/lucene/store/NativeUnixDirectory.java	(revision 1595418)
+++ lucene/misc/src/java/org/apache/lucene/store/NativeUnixDirectory.java	(working copy)
@@ -406,5 +406,11 @@
         throw new RuntimeException("IOException during clone: " + this, ioe);
       }
     }
+
+    @Override
+    public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+      // TODO: is this the right thing to do?
+      return BufferedIndexInput.wrap(sliceDescription, this, offset, length);
+    }
   }
 }
Index: lucene/test-framework/src/java/org/apache/lucene/index/MockIndexInput.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/index/MockIndexInput.java	(revision 1595418)
+++ lucene/test-framework/src/java/org/apache/lucene/index/MockIndexInput.java	(working copy)
@@ -1,70 +0,0 @@
-package org.apache.lucene.index;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.apache.lucene.store.BufferedIndexInput;
-
-// TODO: what is this used for? just testing BufferedIndexInput?
-// if so it should be pkg-private. otherwise its a dup of ByteArrayIndexInput?
-/**
- * IndexInput backed by a byte[] for testing.
- */
-public class MockIndexInput extends BufferedIndexInput {
-    private byte[] buffer;
-    private int pointer = 0;
-    private long length;
-
-    public MockIndexInput(byte[] bytes) {
-        super("MockIndexInput", BufferedIndexInput.BUFFER_SIZE);
-        buffer = bytes;
-        length = bytes.length;
-    }
-
-    @Override
-    protected void readInternal(byte[] dest, int destOffset, int len) {
-        int remainder = len;
-        int start = pointer;
-        while (remainder != 0) {
-//          int bufferNumber = start / buffer.length;
-          int bufferOffset = start % buffer.length;
-          int bytesInBuffer = buffer.length - bufferOffset;
-          int bytesToCopy = bytesInBuffer >= remainder ? remainder : bytesInBuffer;
-          System.arraycopy(buffer, bufferOffset, dest, destOffset, bytesToCopy);
-          destOffset += bytesToCopy;
-          start += bytesToCopy;
-          remainder -= bytesToCopy;
-        }
-        pointer += len;
-    }
-
-    @Override
-    public void close() {
-        // ignore
-    }
-
-    @Override
-    protected void seekInternal(long pos) {
-        pointer = (int) pos;
-    }
-
-    @Override
-    public long length() {
-      return length;
-    }
-
-}
Index: lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java	(revision 1595418)
+++ lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java	(working copy)
@@ -75,9 +75,4 @@
   public void copy(Directory to, String src, String dest, IOContext context) throws IOException {
     in.copy(to, src, dest, context);
   }
-
-  @Override
-  public IndexInputSlicer createSlicer(String name, IOContext context) throws IOException {
-    return in.createSlicer(name, context);
-  }  
 }
Index: lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java	(revision 1595418)
+++ lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java	(working copy)
@@ -946,45 +946,6 @@
     // randomize the IOContext here?
     in.copy(to, src, dest, context);
   }
-
-  @Override
-  public IndexInputSlicer createSlicer(final String name, IOContext context)
-      throws IOException {
-    maybeYield();
-    if (!LuceneTestCase.slowFileExists(in, name)) {
-      throw randomState.nextBoolean() ? new FileNotFoundException(name) : new NoSuchFileException(name);
-    }
-    // cannot open a file for input if it's still open for
-    // output, except for segments.gen and segments_N
-    if (openFilesForWrite.contains(name) && !name.startsWith("segments")) {
-      throw (IOException) fillOpenTrace(new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open for writing"), name, false);
-    }
-    
-    final IndexInputSlicer delegateHandle = in.createSlicer(name, context);
-    final IndexInputSlicer handle = new IndexInputSlicer() {
-      
-      private boolean isClosed;
-      @Override
-      public void close() throws IOException {
-        if (!isClosed) {
-          delegateHandle.close();
-          MockDirectoryWrapper.this.removeOpenFile(this, name);
-          isClosed = true;
-        }
-      }
-
-      @Override
-      public IndexInput openSlice(String sliceDescription, long offset, long length) throws IOException {
-        maybeYield();
-        IndexInput ii = new MockIndexInputWrapper(MockDirectoryWrapper.this, name, delegateHandle.openSlice(sliceDescription, offset, length));
-        addFileHandle(ii, name, Handle.Input);
-        return ii;
-      }
-      
-    };
-    addFileHandle(handle, name, Handle.Slice);
-    return handle;
-  }
   
   final class BufferedIndexOutputWrapper extends BufferedIndexOutput {
     private final IndexOutput io;
Index: lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java	(revision 1595418)
+++ lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java	(working copy)
@@ -89,6 +89,16 @@
   }
 
   @Override
+  public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+    ensureOpen();
+    dir.inputCloneCount.incrementAndGet();
+    IndexInput slice = delegate.slice(sliceDescription, offset, length);
+    MockIndexInputWrapper clone = new MockIndexInputWrapper(dir, sliceDescription, slice);
+    clone.isClone = true;
+    return clone;
+  }
+
+  @Override
   public long getFilePointer() {
     ensureOpen();
     return delegate.getFilePointer();
Index: solr/core/src/java/org/apache/solr/store/blockcache/CustomBufferedIndexInput.java
===================================================================
--- solr/core/src/java/org/apache/solr/store/blockcache/CustomBufferedIndexInput.java	(revision 1595418)
+++ solr/core/src/java/org/apache/solr/store/blockcache/CustomBufferedIndexInput.java	(working copy)
@@ -20,6 +20,7 @@
 import java.io.EOFException;
 import java.io.IOException;
 
+import org.apache.lucene.store.BufferedIndexInput;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
 
@@ -255,6 +256,11 @@
     return clone;
   }
   
+  @Override
+  public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
+    return BufferedIndexInput.wrap(sliceDescription, this, offset, length);
+  }
+
   /**
    * Flushes the in-memory bufer to the given output, copying at most
    * <code>numBytes</code>.
