/**
  * Truncate the file.
  *
  * @param newLength the new length
  */
 void truncate(long newLength) {
   changeLength(newLength);
   long end = MathUtils.roundUpLong(newLength, BLOCK_SIZE);
   if (end != newLength) {
     int lastPage = (int) (newLength >>> BLOCK_SIZE_SHIFT);
     expand(data, lastPage);
     ByteBuffer d = data[lastPage];
     for (int i = (int) (newLength & BLOCK_SIZE_MASK); i < BLOCK_SIZE; i++) {
       d.put(i, (byte) 0);
     }
     if (compress) {
       compressLater(data, lastPage);
     }
   }
 }
 /**
  * Read or write.
  *
  * @param pos the position
  * @param b the byte array
  * @param off the offset within the byte array
  * @param len the number of bytes
  * @param write true for writing
  * @return the new position
  */
 long readWrite(long pos, ByteBuffer b, int off, int len, boolean write) {
   long end = pos + len;
   if (end > length) {
     if (write) {
       changeLength(end);
     } else {
       len = (int) (length - pos);
     }
   }
   while (len > 0) {
     int l = (int) Math.min(len, BLOCK_SIZE - (pos & BLOCK_SIZE_MASK));
     int page = (int) (pos >>> BLOCK_SIZE_SHIFT);
     expand(data, page);
     ByteBuffer block = data[page];
     int blockOffset = (int) (pos & BLOCK_SIZE_MASK);
     if (write) {
       ByteBuffer tmp = b.slice();
       tmp.position(off);
       tmp.limit(off + l);
       block.position(blockOffset);
       block.put(tmp);
     } else {
       block.position(blockOffset);
       ByteBuffer tmp = block.slice();
       tmp.limit(l);
       int oldPosition = b.position();
       b.position(off);
       b.put(tmp);
       // restore old position
       b.position(oldPosition);
     }
     if (compress) {
       compressLater(data, page);
     }
     off += l;
     pos += l;
     len -= l;
   }
   return pos;
 }