h2/src/main/org/h2/mvstore/MVStore.java
/**
     * Compact the store by moving all chunks next to each other, if there is
     * free space between chunks. This might temporarily double the file size.
     * Chunks are overwritten irrespective of the current retention time. Before
     * overwriting chunks and before resizing the file, syncFile() is called.
     *
     * @return if anything was written
     */
Compact the store by moving all chunks next to each other, if there is
free space between chunks. This might temporarily double the file size.
Chunks are overwritten irrespective of the current retention time. Before
overwriting chunks and before resizing the file, syncFile() is called.

@return if anything was written
Compact the store by moving all chunks next to each other if there is free space between chunks . This might temporarily double the file size . Chunks are overwritten irrespective of the current retention time . Before overwriting chunks and before resizing the file syncFile () is called . @return if anything was written
public synchronized boolean compactMoveChunks() {
        checkOpen();
        if (chunks.size() == 0) {
            return false;
        }
        int oldRetentionTime = retentionTime;
        retentionTime = 0;
        long time = getTime();
        ArrayList<Chunk> free = New.arrayList();
        for (Chunk c : chunks.values()) {
            if (c.maxLengthLive == 0) {
                if (canOverwriteChunk(c, time)) {
                    free.add(c);
                }
            }
        }
        for (Chunk c : free) {
            chunks.remove(c.id);
            markMetaChanged();
            meta.remove("chunk." + c.id);
            int length = MathUtils.roundUpInt(c.length, BLOCK_SIZE)
                    + BLOCK_SIZE;
            fileStore.free(c.start, length);
        }
        if (fileStore.getFillRate() == 100) {
            return false;
        }
        long firstFree = fileStore.getFirstFree();
        ArrayList<Chunk> move = New.arrayList();
        for (Chunk c : chunks.values()) {
            if (c.start > firstFree) {
                move.add(c);
            }
        }
        for (Chunk c : move) {
            WriteBuffer buff = getWriteBuffer();
            int length = MathUtils.roundUpInt(c.length, BLOCK_SIZE)
                    + BLOCK_SIZE;
            buff.limit(length);
            ByteBuffer buff2 = fileStore.readFully(c.start, length);
            buff.put(buff2);
            long end = getFileLengthInUse();
            fileStore.markUsed(end, length);
            fileStore.free(c.start, length);
            c.start = end;
            buff.position(0);
            c.writeHeader(buff);
            buff.position(buff.limit() - BLOCK_SIZE);
            byte[] header = getStoreHeaderBytes();
            buff.put(header);
            buff.put(new byte[BLOCK_SIZE - header.length]);
            buff.position(0);
            fileStore.writeFully(end, buff.getBuffer());
            releaseWriteBuffer(buff);
            markMetaChanged();
            meta.put("chunk." + c.id, c.asString());
        }
        boolean oldReuse = reuseSpace;
        reuseSpace = false;
        commitAndSave();
        sync();
        reuseSpace = true;
        for (Chunk c : move) {
            if (!chunks.containsKey(c.id)) {
                continue;
            }
            WriteBuffer buff = getWriteBuffer();
            int length = MathUtils.roundUpInt(c.length, BLOCK_SIZE)
                    + BLOCK_SIZE;
            buff.limit(length);
            ByteBuffer buff2 = fileStore.readFully(c.start, length);
            buff.put(buff2);
            long pos = fileStore.allocate(length);
            fileStore.free(c.start, length);
            buff.position(0);
            c.start = pos;
            c.writeHeader(buff);
            buff.position(buff.limit() - BLOCK_SIZE);
            byte[] header = getStoreHeaderBytes();
            buff.put(header);
            buff.put(new byte[BLOCK_SIZE - header.length]);
            buff.position(0);
            fileStore.writeFully(pos, buff.getBuffer());
            releaseWriteBuffer(buff);
            markMetaChanged();
            meta.put("chunk." + c.id, c.asString());
        }
        commitAndSave();
        sync();
        shrinkFileIfPossible(0);
        reuseSpace = oldReuse;
        retentionTime = oldRetentionTime;
        return true;
    }
public synchronized boolean compactMoveChunks ( ) { checkOpen ( ) ; if ( chunks . size ( ) == 0 ) { return false ; } int oldRetentionTime = retentionTime ; retentionTime = 0 ; long time = getTime ( ) ; ArrayList < Chunk > free = New . arrayList ( ) ; for ( Chunk c : chunks . values ( ) ) { if ( c . maxLengthLive == 0 ) { if ( canOverwriteChunk ( c , time ) ) { free . add ( c ) ; } } } for ( Chunk c : free ) { chunks . remove ( c . id ) ; markMetaChanged ( ) ; meta . remove ( "chunk." + c . id ) ; int length = MathUtils . roundUpInt ( c . length , BLOCK_SIZE ) + BLOCK_SIZE ; fileStore . free ( c . start , length ) ; } if ( fileStore . getFillRate ( ) == 100 ) { return false ; } long firstFree = fileStore . getFirstFree ( ) ; ArrayList < Chunk > move = New . arrayList ( ) ; for ( Chunk c : chunks . values ( ) ) { if ( c . start > firstFree ) { move . add ( c ) ; } } for ( Chunk c : move ) { WriteBuffer buff = getWriteBuffer ( ) ; int length = MathUtils . roundUpInt ( c . length , BLOCK_SIZE ) + BLOCK_SIZE ; buff . limit ( length ) ; ByteBuffer buff2 = fileStore . readFully ( c . start , length ) ; buff . put ( buff2 ) ; long end = getFileLengthInUse ( ) ; fileStore . markUsed ( end , length ) ; fileStore . free ( c . start , length ) ; c . start = end ; buff . position ( 0 ) ; c . writeHeader ( buff ) ; buff . position ( buff . limit ( ) - BLOCK_SIZE ) ; byte [ ] header = getStoreHeaderBytes ( ) ; buff . put ( header ) ; buff . put ( new byte [ BLOCK_SIZE - header . length ] ) ; buff . position ( 0 ) ; fileStore . writeFully ( end , buff . getBuffer ( ) ) ; releaseWriteBuffer ( buff ) ; markMetaChanged ( ) ; meta . put ( "chunk." + c . id , c . asString ( ) ) ; } boolean oldReuse = reuseSpace ; reuseSpace = false ; commitAndSave ( ) ; sync ( ) ; reuseSpace = true ; for ( Chunk c : move ) { if ( ! chunks . containsKey ( c . id ) ) { continue ; } WriteBuffer buff = getWriteBuffer ( ) ; int length = MathUtils . roundUpInt ( c . length , BLOCK_SIZE ) + BLOCK_SIZE ; buff . limit ( length ) ; ByteBuffer buff2 = fileStore . readFully ( c . start , length ) ; buff . put ( buff2 ) ; long pos = fileStore . allocate ( length ) ; fileStore . free ( c . start , length ) ; buff . position ( 0 ) ; c . start = pos ; c . writeHeader ( buff ) ; buff . position ( buff . limit ( ) - BLOCK_SIZE ) ; byte [ ] header = getStoreHeaderBytes ( ) ; buff . put ( header ) ; buff . put ( new byte [ BLOCK_SIZE - header . length ] ) ; buff . position ( 0 ) ; fileStore . writeFully ( pos , buff . getBuffer ( ) ) ; releaseWriteBuffer ( buff ) ; markMetaChanged ( ) ; meta . put ( "chunk." + c . id , c . asString ( ) ) ; } commitAndSave ( ) ; sync ( ) ; shrinkFileIfPossible ( 0 ) ; reuseSpace = oldReuse ; retentionTime = oldRetentionTime ; return true ; }
Compact the store by moving all chunks next to each other, if there is
 free space between chunks.
Compact the store by moving all chunks next to each other if there is free space between chunks .
// nothing to do // fill the header with zeroes // update the metadata (store at the end of the file) // now re-use the empty space // already removed during the // previous store operation // fill the header with zeroes // update the metadata (within the file)