OAK-9914 read-only mode for Azure segment store does not start recovery if archive is not closed
diff --git a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManagerTest.java b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManagerTest.java
index 1a97334..918c5fe 100644
--- a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManagerTest.java
+++ b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManagerTest.java
@@ -29,6 +29,7 @@
import org.apache.jackrabbit.oak.segment.file.FileStore;
import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.segment.file.ReadOnlyFileStore;
import org.apache.jackrabbit.oak.segment.spi.RepositoryNotReachableException;
import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitorAdapter;
import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitorAdapter;
@@ -321,4 +322,31 @@
// SegmentNotFoundException should be thrown here
fileStore.readSegment(new SegmentId(fileStore, u.getMostSignificantBits(), u.getLeastSignificantBits()));
}
+
+ @Test
+ public void testRecoveryNotStartedForReadOnlyMode() throws URISyntaxException, CommitFailedException, IOException, InvalidFileStoreVersionException, StorageException {
+ AzurePersistence rwPersistence = new AzurePersistence(container.getDirectoryReference("oak"));
+ FileStore rwFileStore = FileStoreBuilder.fileStoreBuilder(new File("target")).withCustomPersistence(rwPersistence).build();
+ SegmentNodeStore segmentNodeStore = SegmentNodeStoreBuilders.builder(rwFileStore).build();
+ NodeBuilder builder = segmentNodeStore.getRoot().builder();
+ builder.setProperty("foo", "bar");
+ segmentNodeStore.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ rwFileStore.flush();
+
+ assertTrue(container.getDirectoryReference("oak/data00000a.tar").listBlobs().iterator().hasNext());
+ assertFalse(container.getDirectoryReference("oak/data00000a.tar.ro.bak").listBlobs().iterator().hasNext());
+
+ // create read-only FS
+ AzurePersistence roPersistence = new AzurePersistence(container.getDirectoryReference("oak"));
+ ReadOnlyFileStore roFileStore = FileStoreBuilder.fileStoreBuilder(new File("target")).withCustomPersistence(roPersistence).buildReadOnly();
+
+ assertTrue(container.getDirectoryReference("oak/data00000a.tar").listBlobs().iterator().hasNext());
+ // after creating a read-only FS, the recovery procedure should not be started since
+ // there was another running Oak process that kept archive directory open
+ assertFalse(container.getDirectoryReference("oak/data00000a.tar.ro.bak").listBlobs().iterator().hasNext());
+
+ roFileStore.close();
+ rwFileStore.close();
+ }
+
}
diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
index 8b7722c..e56876c 100644
--- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
+++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
@@ -59,7 +59,7 @@
private static final Logger log = LoggerFactory.getLogger(TarReader.class);
static TarReader open(String file, SegmentArchiveManager archiveManager) throws IOException {
- TarReader reader = openFirstFileWithValidIndex(singletonList(file), archiveManager);
+ TarReader reader = openFirstFileWithValidIndex(singletonList(file), archiveManager, false);
if (reader != null) {
return reader;
} else {
@@ -88,7 +88,7 @@
List<String> list = newArrayList(sorted.values());
Collections.reverse(list);
- TarReader reader = openFirstFileWithValidIndex(list, archiveManager);
+ TarReader reader = openFirstFileWithValidIndex(list, archiveManager, false);
if (reader != null) {
return reader;
}
@@ -104,7 +104,7 @@
String file = sorted.values().iterator().next();
generateTarFile(entries, file, recovery, archiveManager);
- reader = openFirstFileWithValidIndex(singletonList(file), archiveManager);
+ reader = openFirstFileWithValidIndex(singletonList(file), archiveManager, false);
if (reader != null) {
return reader;
} else {
@@ -116,10 +116,17 @@
// for readonly store only try the latest generation of a given
// tar file to prevent any rollback or rewrite
String file = files.get(Collections.max(files.keySet()));
- TarReader reader = openFirstFileWithValidIndex(singletonList(file), archiveManager);
+ TarReader reader = openFirstFileWithValidIndex(singletonList(file), archiveManager, false);
if (reader != null) {
return reader;
}
+
+ log.warn("Could not find a valid tar index in {}, trying to force-open.", file);
+ reader = openFirstFileWithValidIndex(singletonList(file), archiveManager, true);
+ if (reader != null) {
+ return reader;
+ }
+
log.warn("Could not find a valid tar index in {}, recovering read-only", file);
// collecting the entries (without touching the original file) and
// writing them into an artificial tar file '.ro.bak'
@@ -127,7 +134,7 @@
collectFileEntries(file, entries, false, archiveManager);
file = findAvailGen(file, ".ro.bak", archiveManager);
generateTarFile(entries, file, recovery, archiveManager);
- reader = openFirstFileWithValidIndex(singletonList(file), archiveManager);
+ reader = openFirstFileWithValidIndex(singletonList(file), archiveManager, false);
if (reader != null) {
return reader;
}
@@ -226,10 +233,17 @@
return backup;
}
- private static TarReader openFirstFileWithValidIndex(List<String> archives, SegmentArchiveManager archiveManager) {
+ private static TarReader openFirstFileWithValidIndex(List<String> archives, SegmentArchiveManager archiveManager, boolean forceOpen) {
for (String name : archives) {
try {
- SegmentArchiveReader reader = archiveManager.open(name);
+ SegmentArchiveReader reader = null;
+
+ if (forceOpen) {
+ reader = archiveManager.forceOpen(name);
+ } else {
+ reader = archiveManager.open(name);
+ }
+
if (reader != null) {
for (String other : archives) {
if (other != name) {
@@ -560,7 +574,7 @@
writer.close();
- TarReader reader = openFirstFileWithValidIndex(singletonList(newFile), archiveManager);
+ TarReader reader = openFirstFileWithValidIndex(singletonList(newFile), archiveManager, false);
if (reader != null) {
reclaimed.addAll(cleaned);
return reader;