MMapIndexInput(
        String resourceDescription,
        RandomAccessFile raf,
        long offset,
        long length,
        int chunkSizePower)
        throws IOException {
      super(resourceDescription);
      this.length = length;
      this.chunkSizePower = chunkSizePower;
      this.chunkSize = 1L << chunkSizePower;
      this.chunkSizeMask = chunkSize - 1L;

      if (chunkSizePower < 0 || chunkSizePower > 30)
        throw new IllegalArgumentException(
            "Invalid chunkSizePower used for ByteBuffer size: " + chunkSizePower);

      if ((length >>> chunkSizePower) >= Integer.MAX_VALUE)
        throw new IllegalArgumentException(
            "RandomAccessFile too big for chunk size: " + raf.toString());

      // we always allocate one more buffer, the last one may be a 0 byte one
      final int nrBuffers = (int) (length >>> chunkSizePower) + 1;

      // System.out.println("length="+length+", chunkSizePower=" + chunkSizePower + ",
      // chunkSizeMask=" + chunkSizeMask + ", nrBuffers=" + nrBuffers);

      this.buffers = new ByteBuffer[nrBuffers];

      long bufferStart = 0L;
      FileChannel rafc = raf.getChannel();
      for (int bufNr = 0; bufNr < nrBuffers; bufNr++) {
        int bufSize =
            (int) ((length > (bufferStart + chunkSize)) ? chunkSize : (length - bufferStart));
        this.buffers[bufNr] = rafc.map(MapMode.READ_ONLY, offset + bufferStart, bufSize);
        bufferStart += bufSize;
      }
      seek(0L);
    }