Program: 15872
Project: 15872
Buggy source:
/** 
 * Revert to the beginning of the given version. All later changes (stored or not) are forgotten. All maps that were created later are closed. A rollback to a version before the last stored version is immediately persisted. Rollback to version 0 means all data is removed.
 * @param version the version to revert to
 */
public synchronized void rollbackTo(long version){
  checkOpen();
  if (version == 0) {
    for (    MVMap<?,?> m : maps.values()) {
      m.close();
    }
    meta.clear();
    chunks.clear();
    if (fileStore != null) {
      fileStore.clear();
    }
    maps.clear();
    freedPageSpace.clear();
    currentVersion=version;
    setWriteVersion(version);
    lastCommittedVersion=version;
    metaChanged=false;
    return;
  }
  DataUtils.checkArgument(isKnownVersion(version),"String_Node_Str",version);
  for (  MVMap<?,?> m : maps.values()) {
    m.rollbackTo(version);
  }
synchronized (freedPageSpace) {
    for (long v=currentVersion; v >= version; v--) {
      if (freedPageSpace.size() == 0) {
        break;
      }
      freedPageSpace.remove(v);
    }
  }
  meta.rollbackTo(version);
  metaChanged=false;
  boolean loadFromFile=false;
  int removeChunksNewerThan=-1;
  for (int chunkId=lastChunkId; ; chunkId--) {
    Chunk x=chunks.get(chunkId);
    if (x == null) {
      break;
    }
 else     if (x.version >= version) {
      removeChunksNewerThan=x.id;
    }
  }
  if (removeChunksNewerThan >= 0 && lastChunkId > removeChunksNewerThan) {
    revertTemp(version);
    loadFromFile=true;
    Chunk last=null;
    while (true) {
      last=chunks.get(lastChunkId);
      if (last == null) {
        break;
      }
 else       if (last.id <= removeChunksNewerThan) {
        break;
      }
      chunks.remove(lastChunkId);
      int len=MathUtils.roundUpInt(last.length,BLOCK_SIZE) + BLOCK_SIZE;
      fileStore.free(last.start,len);
      lastChunkId--;
    }
    rootChunkStart=last.start;
    writeStoreHeader();
    byte[] bytes=getStoreHeaderBytes();
    ByteBuffer header=ByteBuffer.allocate(BLOCK_SIZE);
    header.put(bytes);
    header.rewind();
    fileStore.writeFully(fileStore.size(),header);
    readStoreHeader();
    readMeta();
  }
  for (  MVMap<?,?> m : New.arrayList(maps.values())) {
    int id=m.getId();
    if (m.getCreateVersion() >= version) {
      m.close();
      maps.remove(id);
    }
 else {
      if (loadFromFile) {
        String r=meta.get("String_Node_Str" + id);
        long root=r == null ? 0 : Long.parseLong(r);
        m.setRootPos(root,-1);
      }
    }
  }
  Chunk c=chunks.get(lastChunkId - 1);
  if (c != null) {
    markMetaChanged();
    meta.put("String_Node_Str" + c.id,c.asString());
  }
  currentVersion=version;
  setWriteVersion(version);
  lastCommittedVersion=version;
}

Fixed version (ground truth):
/** 
 * Revert to the beginning of the given version. All later changes (stored or not) are forgotten. All maps that were created later are closed. A rollback to a version before the last stored version is immediately persisted. Rollback to version 0 means all data is removed.
 * @param version the version to revert to
 */
public synchronized void rollbackTo(long version){
  checkOpen();
  if (version == 0) {
    for (    MVMap<?,?> m : maps.values()) {
      m.close();
    }
    meta.clear();
    chunks.clear();
    if (fileStore != null) {
      fileStore.clear();
    }
    maps.clear();
    freedPageSpace.clear();
    currentVersion=version;
    setWriteVersion(version);
    lastCommittedVersion=version;
    metaChanged=false;
    return;
  }
  DataUtils.checkArgument(isKnownVersion(version),"String_Node_Str",version);
  for (  MVMap<?,?> m : maps.values()) {
    m.rollbackTo(version);
  }
  for (long v=currentVersion; v >= version; v--) {
    if (freedPageSpace.size() == 0) {
      break;
    }
    freedPageSpace.remove(v);
  }
  meta.rollbackTo(version);
  metaChanged=false;
  boolean loadFromFile=false;
  int removeChunksNewerThan=-1;
  for (int chunkId=lastChunkId; ; chunkId--) {
    Chunk x=chunks.get(chunkId);
    if (x == null) {
      break;
    }
 else     if (x.version >= version) {
      removeChunksNewerThan=x.id;
    }
  }
  if (removeChunksNewerThan >= 0 && lastChunkId > removeChunksNewerThan) {
    revertTemp(version);
    loadFromFile=true;
    Chunk last=null;
    while (true) {
      last=chunks.get(lastChunkId);
      if (last == null) {
        break;
      }
 else       if (last.id <= removeChunksNewerThan) {
        break;
      }
      chunks.remove(lastChunkId);
      int len=MathUtils.roundUpInt(last.length,BLOCK_SIZE) + BLOCK_SIZE;
      fileStore.free(last.start,len);
      lastChunkId--;
    }
    rootChunkStart=last.start;
    writeStoreHeader();
    byte[] bytes=getStoreHeaderBytes();
    ByteBuffer header=ByteBuffer.allocate(BLOCK_SIZE);
    header.put(bytes);
    header.rewind();
    fileStore.writeFully(fileStore.size(),header);
    readStoreHeader();
    readMeta();
  }
  for (  MVMap<?,?> m : New.arrayList(maps.values())) {
    int id=m.getId();
    if (m.getCreateVersion() >= version) {
      m.close();
      maps.remove(id);
    }
 else {
      if (loadFromFile) {
        String r=meta.get("String_Node_Str" + id);
        long root=r == null ? 0 : Long.parseLong(r);
        m.setRootPos(root,-1);
      }
    }
  }
  Chunk c=chunks.get(lastChunkId - 1);
  if (c != null) {
    markMetaChanged();
    meta.put("String_Node_Str" + c.id,c.asString());
  }
  currentVersion=version;
  setWriteVersion(version);
  lastCommittedVersion=version;
}