Skip to content

Commit

Permalink
PersistenceFileWrite: Truncate file before writing
Browse files Browse the repository at this point in the history
  • Loading branch information
alvasw committed Feb 15, 2024
1 parent bf57524 commit f7443b7
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ public PersistenceFileWriter(AsyncFileWriter asyncWriter, ExecutorService writeR

public CompletableFuture<Void> write(byte[] data) {
CompletableFuture<Void> completableFuture = new CompletableFuture<>();
scheduleAsyncWrite(data, 0, data.length, completableFuture);
asyncWriter.truncate()
.thenRun(() -> scheduleAsyncWrite(data, 0, data.length, completableFuture))
.exceptionally(throwable -> {
completableFuture.completeExceptionally(throwable);
return null;
});
return completableFuture;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

package bisq.persistence;

import java.io.IOException;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
Expand All @@ -32,9 +35,13 @@
import org.junit.jupiter.api.extension.ExtendWith;

import static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.concurrent.CompletableFuture.failedFuture;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

Expand All @@ -56,8 +63,29 @@ static void teardown() {
writeRequestScheduler.shutdownNow();
}

@Test
void failTruncation() throws ExecutionException, InterruptedException, TimeoutException {
var ioException = new IOException("Truncation failed.");
doReturn(failedFuture(ioException))
.when(asyncWriter).truncate();

CountDownLatch exceptionThrownLatch = new CountDownLatch(1);
fileWriter.write(DATA)
.exceptionally(throwable -> {
assertThat(throwable.getCause(), is(ioException));
exceptionThrownLatch.countDown();
return null;
})
.get(30, TimeUnit.SECONDS);

assertThat(exceptionThrownLatch.getCount(), is(0L));
verify(asyncWriter, times(1)).truncate();
verify(asyncWriter, never()).write(any(), anyInt());
}

@Test
void writeInOneGo() throws InterruptedException, ExecutionException, TimeoutException {
doReturn(completedFuture(null)).when(asyncWriter).truncate();
doReturn(completedFuture(DATA.length))
.when(asyncWriter).write(any(), anyInt());

Expand All @@ -69,6 +97,7 @@ void writeInOneGo() throws InterruptedException, ExecutionException, TimeoutExce

@Test
void writeInTwoPhases() throws InterruptedException, ExecutionException, TimeoutException {
doReturn(completedFuture(null)).when(asyncWriter).truncate();
doReturn(completedFuture(25), completedFuture(75))
.when(asyncWriter).write(any(), anyInt());

Expand All @@ -80,6 +109,7 @@ void writeInTwoPhases() throws InterruptedException, ExecutionException, Timeout

@Test
void writeInFivePhases() throws InterruptedException, ExecutionException, TimeoutException {
doReturn(completedFuture(null)).when(asyncWriter).truncate();
doReturn(completedFuture(10), completedFuture(20),
completedFuture(30), completedFuture(15),
completedFuture(25))
Expand Down

0 comments on commit f7443b7

Please sign in to comment.