PersistenceFileWrite: Truncate file before writing

This commit is contained in:
Alva Swanson 2024-02-15 14:41:53 +01:00
parent bf57524671
commit f7443b7676
No known key found for this signature in database
GPG key ID: 004760E77F753090
2 changed files with 36 additions and 1 deletions

View file

@ -34,7 +34,12 @@ public class PersistenceFileWriter {
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;
}

View file

@ -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;
@ -32,9 +35,13 @@ import org.junit.jupiter.api.Test;
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;
@ -56,8 +63,29 @@ public class PersistenceFileWriterTests {
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());
@ -69,6 +97,7 @@ public class PersistenceFileWriterTests {
@Test
void writeInTwoPhases() throws InterruptedException, ExecutionException, TimeoutException {
doReturn(completedFuture(null)).when(asyncWriter).truncate();
doReturn(completedFuture(25), completedFuture(75))
.when(asyncWriter).write(any(), anyInt());
@ -80,6 +109,7 @@ public class PersistenceFileWriterTests {
@Test
void writeInFivePhases() throws InterruptedException, ExecutionException, TimeoutException {
doReturn(completedFuture(null)).when(asyncWriter).truncate();
doReturn(completedFuture(10), completedFuture(20),
completedFuture(30), completedFuture(15),
completedFuture(25))