Skip to content

Commit

Permalink
OAK-9170 - Make loading segment disk cache fail safe in case when wri…
Browse files Browse the repository at this point in the history
…te operation is interrupted by failure

Contribution by Miroslav Smiljanic

git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/oak/trunk@1880765 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
dulceanu committed Aug 11, 2020
1 parent 764cd2e commit 1daa0e2
Showing 1 changed file with 18 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.Comparator;
Expand Down Expand Up @@ -131,15 +133,28 @@ public boolean containsSegment(long msb, long lsb) {
public void writeSegment(long msb, long lsb, Buffer buffer) {
String segmentId = new UUID(msb, lsb).toString();
File segmentFile = new File(directory, segmentId);
File tempSegmentFile = new File(directory, segmentId + System.nanoTime() + ".part");

Buffer bufferCopy = buffer.duplicate();

Runnable task = () -> {
if (lockSegmentWrite(segmentId)) {
try (FileChannel channel = new FileOutputStream(segmentFile).getChannel()) {
try (FileChannel channel = new FileOutputStream(tempSegmentFile).getChannel()) {
int fileSize = bufferCopy.write(channel);
try {
Files.move(tempSegmentFile.toPath(), segmentFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) {
Files.move(tempSegmentFile.toPath(), segmentFile.toPath());
}
cacheSize.addAndGet(fileSize);
} catch (Throwable t) {
logger.error("Error writing segment {} to cache: {}", segmentId, t);
} catch (Exception e) {
logger.error("Error writing segment {} to cache: {}", segmentId, e);
try {
Files.deleteIfExists(segmentFile.toPath());
Files.deleteIfExists(tempSegmentFile.toPath());
} catch (IOException i) {
logger.error("Error while deleting corrupted segment file {}", segmentId, i);
}
} finally {
unlockSegmentWrite(segmentId);
}
Expand Down

0 comments on commit 1daa0e2

Please sign in to comment.