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

szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new f9584b8c2 RATIS-1871. Auto format RaftStorage when there is only one 
directory configured. (#903)
f9584b8c2 is described below

commit f9584b8c29d933b3833a6f26b69b557e6ceec607
Author: Tsz-Wo Nicholas Sze <[email protected]>
AuthorDate: Thu Aug 17 20:26:52 2023 -0700

    RATIS-1871. Auto format RaftStorage when there is only one directory 
configured. (#903)
---
 .../ratis/server/storage/StorageImplUtils.java     | 10 ++++-
 .../ratis/server/storage/TestStorageImplUtils.java | 48 +++++++++++++++++++++-
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/storage/StorageImplUtils.java
 
b/ratis-server/src/main/java/org/apache/ratis/server/storage/StorageImplUtils.java
index b6199ea02..b8974cbf6 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/storage/StorageImplUtils.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/storage/StorageImplUtils.java
@@ -87,7 +87,8 @@ public final class StorageImplUtils {
    * {@link StartupOption#RECOVER}:
    * - When there are more than one existing directories, throw an exception.
    * - When there is an existing directory, if it fails to initialize, throw 
an exception but not try a new directory.
-   * - When there is no existing directory, throw an exception.
+   * - When there is no existing directory, if only one directory is specified 
in the configuration, format it;
+   *   otherwise, there are >1 directories specified, throw an exception.
    *
    * @param storageDirName the storage directory name
    * @param option the startup option
@@ -125,7 +126,8 @@ public final class StorageImplUtils {
       if (option == StartupOption.FORMAT) {
         return format();
       } else if (option == StartupOption.RECOVER) {
-        return recover();
+        final RaftStorageImpl recovered = recover();
+        return recovered != null? recovered: format();
       } else {
         throw new IllegalArgumentException("Illegal option: " + option);
       }
@@ -160,6 +162,10 @@ public final class StorageImplUtils {
         throw new IOException("Failed to " + option + ": More than one 
existing directories found "
             + existingSubs + " for " + storageDirName);
       } else if (size == 0) {
+        if (dirsInConf.size() == 1) {
+          // fallback to FORMAT
+          return null;
+        }
         throw new IOException("Failed to " + option + ": Storage directory not 
found for "
             + storageDirName + " from " + dirsInConf);
       }
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/server/storage/TestStorageImplUtils.java
 
b/ratis-test/src/test/java/org/apache/ratis/server/storage/TestStorageImplUtils.java
index ff38a6bd9..e8661e268 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/server/storage/TestStorageImplUtils.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/server/storage/TestStorageImplUtils.java
@@ -18,6 +18,8 @@
 package org.apache.ratis.server.storage;
 
 import org.apache.ratis.BaseTest;
+import org.apache.ratis.conf.RaftProperties;
+import org.apache.ratis.server.RaftServerConfigKeys;
 import org.apache.ratis.util.FileUtils;
 import org.apache.ratis.util.JavaUtils;
 import org.junit.AfterClass;
@@ -39,7 +41,7 @@ import java.util.stream.IntStream;
 /**
  * Test cases to verify ServerState.
  */
-public class TestStorageImplUtils {
+public class TestStorageImplUtils extends BaseTest {
 
   private static final Supplier<File> rootTestDir = JavaUtils.memoize(
       () -> new File(BaseTest.getRootTestDir(),
@@ -128,4 +130,48 @@ public class TestStorageImplUtils {
       Assert.assertEquals(expectedErrMsg, ex.getMessage());
     }
   }
+
+  /**
+   * When there is only one directory specified in conf, auto format it.
+   */
+  @Test
+  public void testAutoFormatSingleDirectory() throws Exception {
+    final File testDir = new File(rootTestDir.get(), 
UUID.randomUUID().toString());
+    FileUtils.createDirectories(testDir);
+
+    final RaftProperties properties = new RaftProperties();
+    RaftServerConfigKeys.setStorageDir(properties, 
Collections.singletonList(testDir));
+
+    final RaftStorageImpl storage = StorageImplUtils.initRaftStorage(
+        "group-1", RaftStorage.StartupOption.RECOVER, properties);
+    Assert.assertNotNull(storage);
+    storage.close();
+  }
+
+  /**
+   * When there are multiple directories specified in conf, do not auto format.
+   */
+  @Test
+  public void testAutoFormatMultiDirectories() throws Exception {
+    final File testDir = new File(rootTestDir.get(), 
UUID.randomUUID().toString());
+    final List<File> directories = new ArrayList<>();
+    IntStream.range(0, 3).mapToObj((i) -> new File(testDir,
+        Integer.toString(i))).forEach((dir) -> {
+      try {
+        FileUtils.createDirectories(dir);
+        directories.add(dir);
+      } catch (IOException e) {
+        throw new RuntimeException(e);
+      }
+    });
+
+    final RaftProperties properties = new RaftProperties();
+    RaftServerConfigKeys.setStorageDir(properties, directories);
+
+    final Throwable ioe = testFailureCase("Do not auto format multi 
directories",
+        () -> StorageImplUtils.initRaftStorage(
+            "group-1", RaftStorage.StartupOption.RECOVER, properties),
+        IOException.class);
+    Assert.assertTrue(ioe.getMessage().contains("Failed to RECOVER: Storage 
directory not found"));
+  }
 }
\ No newline at end of file

Reply via email to