You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mi...@apache.org on 2022/09/01 11:39:13 UTC

[jackrabbit-oak] 01/01: OAK-9914 adding system property to control whether recovery should be started for unclosed azure archive directory

This is an automated email from the ASF dual-hosted git repository.

miroslav pushed a commit to branch read_only_recovery
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 8e0ae9f1e1d3fa9cee9a0bdf9d5e65305f3eab51
Author: smiroslav <mi...@apache.org>
AuthorDate: Thu Sep 1 13:36:20 2022 +0200

    OAK-9914 adding system property to control whether recovery should be started for unclosed azure archive directory
---
 oak-lucene/pom.xml                                 |  1 -
 oak-parent/pom.xml                                 |  6 ++
 oak-search-elastic/pom.xml                         |  1 -
 oak-segment-azure/pom.xml                          |  5 ++
 .../oak/segment/azure/AzureArchiveManager.java     |  4 +-
 .../oak/segment/azure/AzureArchiveManagerTest.java | 64 ++++++++++++++++++++++
 6 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/oak-lucene/pom.xml b/oak-lucene/pom.xml
index f9a4986e80..cff61286a9 100644
--- a/oak-lucene/pom.xml
+++ b/oak-lucene/pom.xml
@@ -448,7 +448,6 @@
     <dependency>
       <groupId>com.github.stefanbirkner</groupId>
       <artifactId>system-rules</artifactId>
-      <version>1.19.0</version>
       <scope>test</scope>
     </dependency>
 
diff --git a/oak-parent/pom.xml b/oak-parent/pom.xml
index 3ef7bb9722..52459c1ff7 100644
--- a/oak-parent/pom.xml
+++ b/oak-parent/pom.xml
@@ -781,6 +781,12 @@
         <version>1</version>
         <scope>test</scope>
       </dependency>
+      <dependency>
+        <groupId>com.github.stefanbirkner</groupId>
+        <artifactId>system-rules</artifactId>
+        <version>1.19.0</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
diff --git a/oak-search-elastic/pom.xml b/oak-search-elastic/pom.xml
index 25a910eb02..72d18a745c 100644
--- a/oak-search-elastic/pom.xml
+++ b/oak-search-elastic/pom.xml
@@ -348,7 +348,6 @@
     <dependency>
       <groupId>com.github.stefanbirkner</groupId>
       <artifactId>system-rules</artifactId>
-      <version>1.19.0</version>
       <scope>test</scope>
     </dependency>
 
diff --git a/oak-segment-azure/pom.xml b/oak-segment-azure/pom.xml
index 73391f8eab..b86ce5478e 100644
--- a/oak-segment-azure/pom.xml
+++ b/oak-segment-azure/pom.xml
@@ -224,6 +224,11 @@
             <version>1.0.9</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.github.stefanbirkner</groupId>
+            <artifactId>system-rules</artifactId>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 
diff --git a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
index 7e2d28b9e8..0f3b4751e4 100644
--- a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
+++ b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
@@ -56,6 +56,8 @@ public class AzureArchiveManager implements SegmentArchiveManager {
 
     private static final Logger log = LoggerFactory.getLogger(AzureSegmentArchiveReader.class);
 
+    private boolean skipArchiveClosedCheck = Boolean.getBoolean("segment.azure.skipArchiveClosedCheck");
+
     protected final CloudBlobDirectory cloudBlobDirectory;
 
     protected final IOMonitor ioMonitor;
@@ -110,7 +112,7 @@ public class AzureArchiveManager implements SegmentArchiveManager {
     public SegmentArchiveReader open(String archiveName) throws IOException {
         try {
             CloudBlobDirectory archiveDirectory = getDirectory(archiveName);
-            if (!archiveDirectory.getBlockBlobReference("closed").exists()) {
+             if (!skipArchiveClosedCheck && !archiveDirectory.getBlockBlobReference("closed").exists()) {
                 throw new IOException("The archive " + archiveName + " hasn't been closed correctly.");
             }
             return new AzureSegmentArchiveReader(archiveDirectory, ioMonitor);
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 1a97334a10..c165c207c2 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.SegmentNotFoundException;
 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;
@@ -42,7 +43,10 @@ import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.rules.TestRule;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -69,6 +73,9 @@ public class AzureArchiveManagerTest {
 
     private CloudBlobContainer container;
 
+    @Rule
+    public final TestRule restoreSystemProperties = new RestoreSystemProperties();
+
     @Before
     public void setup() throws StorageException, InvalidKeyException, URISyntaxException {
         container = azurite.getContainer("oak-test");
@@ -321,4 +328,61 @@ public class AzureArchiveManagerTest {
         // SegmentNotFoundException should be thrown here
         fileStore.readSegment(new SegmentId(fileStore, u.getMostSignificantBits(), u.getLeastSignificantBits()));
     }
+
+    @Test
+    public void testReadOnlyWithoutRecovery() throws URISyntaxException, InvalidFileStoreVersionException, IOException, CommitFailedException, 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());
+
+        // set the system property so that the check if archive dir is closed is skipped
+        System.setProperty("segment.azure.skipArchiveClosedCheck", "true");
+
+        // create read-only FS
+        AzurePersistence roPersistence = new AzurePersistence(container.getDirectoryReference("oak"));
+        ReadOnlyFileStore roFileStore = FileStoreBuilder.fileStoreBuilder(new File("target")).withCustomPersistence(roPersistence).buildReadOnly();
+
+        roFileStore.close();
+        rwFileStore.close();
+
+        assertTrue(container.getDirectoryReference("oak/data00000a.tar").listBlobs().iterator().hasNext());
+        // after creating a read-only FS, the recovery procedure should not be started since there is another running Oak process
+        assertFalse(container.getDirectoryReference("oak/data00000a.tar.ro.bak").listBlobs().iterator().hasNext());
+
+    }
+
+    @Test
+    public void testReadOnlyWithRecovery() throws URISyntaxException, InvalidFileStoreVersionException, IOException, CommitFailedException, 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();
+
+        roFileStore.close();
+        rwFileStore.close();
+
+        assertTrue(container.getDirectoryReference("oak/data00000a.tar").listBlobs().iterator().hasNext());
+        // after creating a read-only FS, the recovery procedure has happened started since there is another running Oak process
+        // and the last archive is not closed
+        assertTrue(container.getDirectoryReference("oak/data00000a.tar.ro.bak").listBlobs().iterator().hasNext());
+    }
 }