Author: adulceanu
Date: Tue Aug 11 10:02:52 2020
New Revision: 1880765
URL: http://svn.apache.org/viewvc?rev=1880765&view=rev
Log:
OAK-9170 - Make loading segment disk cache fail safe in case when write
operation is interrupted by failure
Contribution by Miroslav Smiljanic
Modified:
jackrabbit/oak/trunk/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/persistentcache/PersistentDiskCache.java
Modified:
jackrabbit/oak/trunk/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/persistentcache/PersistentDiskCache.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/persistentcache/PersistentDiskCache.java?rev=1880765&r1=1880764&r2=1880765&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/persistentcache/PersistentDiskCache.java
(original)
+++
jackrabbit/oak/trunk/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/persistentcache/PersistentDiskCache.java
Tue Aug 11 10:02:52 2020
@@ -33,8 +33,10 @@ import java.io.FileNotFoundException;
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;
@@ -131,15 +133,28 @@ public class PersistentDiskCache extends
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);
}