private void upgradeRatings(BinaryFormat newFormat) throws IOException { Preconditions.checkArgument( newFormat.getRatingSize() > format.getRatingSize(), "new format is not wider than old"); logger.info("upgrading {} ratings from {} to {}", index, format, newFormat); ByteBuffer oldBuffer = ByteBuffer.allocateDirect(format.getRatingSize()); ByteBuffer newBuffer = ByteBuffer.allocateDirect(newFormat.getRatingSize()); MutableRating scratch = new MutableRating(); long oldPos = BinaryHeader.HEADER_SIZE + index * format.getRatingSize(); Preconditions.checkState(channel.position() == oldPos, "channel is at the wrong position"); long newPos = BinaryHeader.HEADER_SIZE + index * newFormat.getRatingSize(); channel.position(newPos); // loop backwards, coping each rating to later in the file for (int i = index - 1; i >= 0; i--) { oldPos -= format.getRatingSize(); newPos -= newFormat.getRatingSize(); // read the old rating BinaryUtils.readBuffer(channel, oldBuffer, oldPos); oldBuffer.flip(); format.readRating(oldBuffer, scratch); oldBuffer.clear(); // write the new rating newFormat.renderRating(scratch, newBuffer); newBuffer.flip(); BinaryUtils.writeBuffer(channel, newBuffer, newPos); newBuffer.clear(); } assert oldPos == BinaryHeader.HEADER_SIZE; assert newPos == BinaryHeader.HEADER_SIZE; format = newFormat; ratingBuffer = ByteBuffer.allocateDirect(newFormat.getRatingSize()); }