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;