Skip to content

Commit

Permalink
fix for h2database#3909
Browse files Browse the repository at this point in the history
  • Loading branch information
andreitokar committed Feb 19, 2024
1 parent 4497462 commit d280e30
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 21 deletions.
7 changes: 4 additions & 3 deletions h2/src/main/org/h2/mvstore/FileStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ public final void setAutoCommitDelay(int millis) {
stopBackgroundThread(millis >= 0);
// start the background thread if needed
if (millis > 0 && mvStore.isOpen()) {
int sleep = Math.max(1, millis / 10);
int sleep = Math.max(1, millis / 5);
BackgroundWriterThread t = new BackgroundWriterThread(this, sleep, toString());
if (backgroundWriterThread.compareAndSet(null, t)) {
t.start();
Expand Down Expand Up @@ -622,7 +622,7 @@ protected final boolean hasPersistentData() {
}

protected final boolean isIdle() {
return autoCompactLastFileOpCount == getWriteCount() + getReadCount();
return autoCompactLastFileOpCount >= getWriteCount() + getReadCount();
}

protected final void setLastChunk(C last) {
Expand Down Expand Up @@ -1835,7 +1835,8 @@ void writeInBackground() {
mvStore.tryCommit();
}
doHousekeeping(mvStore);
autoCompactLastFileOpCount = getWriteCount() + getReadCount();
// less than 10 I/O operations will still count as "idle"
autoCompactLastFileOpCount = getWriteCount() + getReadCount() + 10;
}
} catch (InterruptedException ignore) {
} catch (Throwable e) {
Expand Down
6 changes: 2 additions & 4 deletions h2/src/main/org/h2/mvstore/FreeSpaceBitSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,8 @@ private int allocate(int blocks, int reservedLow, int reservedHigh, boolean allo
int freeBlocks = end - start;
if (end < 0 || freeBlocks >= blocks) {
if ((reservedHigh < 0 || start < reservedHigh) && start + blocks > reservedLow) { // overlap detected
if (reservedHigh < 0) {
start = getAfterLastBlock();
end = -1;
} else {
if (reservedHigh >= 0) {
freeBlocksTotal += freeBlocks;
i = reservedHigh;
continue;
}
Expand Down
34 changes: 20 additions & 14 deletions h2/src/main/org/h2/mvstore/RandomAccessStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public abstract class RandomAccessStore extends FileStore<SFChunk>
private long reservedLow;
private long reservedHigh;
private boolean stopIdleHousekeeping;
private int restoreHousekeepingAtRate;

public RandomAccessStore(Map<String, Object> config) {
super(config);
Expand Down Expand Up @@ -703,45 +704,50 @@ private void shrinkIfPossible(int minPercent) {
@Override
protected void doHousekeeping(MVStore mvStore) throws InterruptedException {
boolean idle = isIdle();
if (idle && stopIdleHousekeeping) {
int rewritableChunksFillRate = getRewritableChunksFillRate();
if (idle && stopIdleHousekeeping && rewritableChunksFillRate > restoreHousekeepingAtRate) {
return;
}
int autoCommitMemory = mvStore.getAutoCommitMemory();
int fillRate = getFillRate();
if (isFragmented() && fillRate < getAutoCompactFillRate()) {
if (isFragmented() && getFillRate() < getAutoCompactFillRate()) {
mvStore.tryExecuteUnderStoreLock(() -> {
int moveSize = 2 * autoCommitMemory;
if (isIdle()) {
if (idle) {
moveSize *= 4;
}
compactMoveChunks(101, moveSize, mvStore);
return true;
});
}

int chunksFillRate = getRewritableChunksFillRate();
int adjustedChunksFillRate = 100 - (100 - chunksFillRate) / 2;
int fillRateToCompare = isIdle() ? chunksFillRate : adjustedChunksFillRate;
if (fillRateToCompare < getTargetFillRate()) {
int chunksFillRate = getChunksFillRate();
int adjustedChunksFillRate = 50 + rewritableChunksFillRate / 2;
int fillRateToCompare = idle ? rewritableChunksFillRate : adjustedChunksFillRate;
if (fillRateToCompare < getTargetFillRate(idle)) {
mvStore.tryExecuteUnderStoreLock(() -> {
int writeLimit = autoCommitMemory;
if (!isIdle()) {
if (!idle) {
writeLimit /= 4;
}
if (rewriteChunks(writeLimit, isIdle() ? adjustedChunksFillRate : chunksFillRate)) {
if (rewriteChunks(writeLimit, idle ? adjustedChunksFillRate : rewritableChunksFillRate)) {
dropUnusedChunks();
}
return true;
});
}
stopIdleHousekeeping = idle && getFillRate() <= fillRate && getRewritableChunksFillRate() <= chunksFillRate;
stopIdleHousekeeping = idle && getChunksFillRate() < chunksFillRate;
if (stopIdleHousekeeping) {
// this rate can change with the time, even when database is idle,
// since chunks become older and may become eligible for re-writing
restoreHousekeepingAtRate = getRewritableChunksFillRate() - 2;
}
}

private int getTargetFillRate() {
private int getTargetFillRate(boolean idle) {
int targetRate = getAutoCompactFillRate();
// use a lower fill rate if there were any file operations since the last time
if (!isIdle()) {
targetRate /= 2;
if (!idle) {
targetRate = targetRate * targetRate / 100;
}
return targetRate;
}
Expand Down

0 comments on commit d280e30

Please sign in to comment.