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 499a79375 RATIS-1752. Clean md5 file created by old ratis version. 
(#790)
499a79375 is described below

commit 499a79375a58bb37718abe2176f8df279b66d521
Author: qian0817 <[email protected]>
AuthorDate: Tue Nov 29 02:33:50 2022 +0800

    RATIS-1752. Clean md5 file created by old ratis version. (#790)
---
 .../main/java/org/apache/ratis/util/FileUtils.java | 22 +++++++++--
 .../impl/SimpleStateMachineStorage.java            | 43 ++++++++++++++++------
 .../ratis/server/storage/TestRaftStorage.java      | 13 ++++++-
 3 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/ratis-common/src/main/java/org/apache/ratis/util/FileUtils.java 
b/ratis-common/src/main/java/org/apache/ratis/util/FileUtils.java
index f978a79c3..15ec6ea94 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/FileUtils.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/FileUtils.java
@@ -143,13 +143,29 @@ public interface FileUtils {
     deleteFully(source);
   }
 
-  /** The same as passing f.toPath() to {@link #delete(Path)}. */
+  /**
+   * The same as passing f.toPath() to {@link #deletePathQuietly(Path)}.
+   *
+   * @param f file to delete
+   * @return true if the file is successfully deleted false otherwise
+   */
   static boolean deleteFileQuietly(File f) {
+    return deletePathQuietly(f.toPath());
+  }
+
+  /**
+   * Delete the given path quietly.
+   * Only print a debug message in case that there is an exception,
+   *
+   * @param p path to delete
+   * @return true if the path is successfully deleted false otherwise
+   */
+  static boolean deletePathQuietly(Path p) {
     try {
-      delete(f.toPath());
+      delete(p);
       return true;
     } catch (Exception ex) {
-      LOG.debug("File delete was not successful {}", f.getAbsoluteFile(), ex);
+      LOG.debug("Failed to delete " + p.toAbsolutePath(), ex);
       return false;
     }
   }
diff --git 
a/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/SimpleStateMachineStorage.java
 
b/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/SimpleStateMachineStorage.java
index 0a6ce2936..37e94a8a0 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/SimpleStateMachineStorage.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/statemachine/impl/SimpleStateMachineStorage.java
@@ -17,6 +17,8 @@
  */
 package org.apache.ratis.statemachine.impl;
 
+import static org.apache.ratis.util.MD5FileUtil.MD5_SUFFIX;
+
 import org.apache.ratis.io.MD5Hash;
 import org.apache.ratis.server.protocol.TermIndex;
 import org.apache.ratis.server.storage.FileInfo;
@@ -44,7 +46,6 @@ import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 
 /**
  * A StateMachineStorage that stores the snapshot in a single file.
@@ -58,6 +59,14 @@ public class SimpleStateMachineStorage implements 
StateMachineStorage {
   /** snapshot.term_index */
   public static final Pattern SNAPSHOT_REGEX =
       Pattern.compile(SNAPSHOT_FILE_PREFIX + "\\.(\\d+)_(\\d+)");
+  public static final Pattern SNAPSHOT_MD5_REGEX =
+      Pattern.compile(SNAPSHOT_FILE_PREFIX + "\\.(\\d+)_(\\d+)" + MD5_SUFFIX);
+  private static final DirectoryStream.Filter<Path> SNAPSHOT_MD5_FILTER
+      = entry -> Optional.ofNullable(entry.getFileName())
+      .map(Path::toString)
+      .map(SNAPSHOT_MD5_REGEX::matcher)
+      .filter(Matcher::matches)
+      .isPresent();
 
   private volatile File stateMachineDir = null;
   private final AtomicReference<SingleFileSnapshotInfo> latestSnapshot = new 
AtomicReference<>();
@@ -109,16 +118,28 @@ public class SimpleStateMachineStorage implements 
StateMachineStorage {
 
     if (allSnapshotFiles.size() > 
snapshotRetentionPolicy.getNumSnapshotsRetained()) {
       
allSnapshotFiles.sort(Comparator.comparing(SingleFileSnapshotInfo::getIndex).reversed());
-      List<File> snapshotFilesToBeCleaned = allSnapshotFiles.subList(
-              snapshotRetentionPolicy.getNumSnapshotsRetained(), 
allSnapshotFiles.size()).stream()
-          .map(singleFileSnapshotInfo -> 
singleFileSnapshotInfo.getFile().getPath().toFile())
-          .collect(Collectors.toList());
-      for (File snapshotFile : snapshotFilesToBeCleaned) {
-        LOG.info("Deleting old snapshot at {}", 
snapshotFile.getAbsolutePath());
-        final boolean deleted = FileUtils.deleteFileQuietly(snapshotFile);
-        if (deleted) {
-          final File md5file = MD5FileUtil.getDigestFileForFile(snapshotFile);
-          FileUtils.deleteFileQuietly(md5file);
+      allSnapshotFiles.subList(numSnapshotsRetained, allSnapshotFiles.size())
+          .stream()
+          .map(SingleFileSnapshotInfo::getFile)
+          .map(FileInfo::getPath)
+          .forEach(snapshotPath -> {
+            LOG.info("Deleting old snapshot at {}", 
snapshotPath.toAbsolutePath());
+            FileUtils.deletePathQuietly(snapshotPath);
+          });
+      // clean up the md5 files if the corresponding snapshot file does not 
exist
+      try (DirectoryStream<Path> stream = 
Files.newDirectoryStream(stateMachineDir.toPath(),
+          SNAPSHOT_MD5_FILTER)) {
+        for (Path md5path : stream) {
+          Path md5FileNamePath = md5path.getFileName();
+          if (md5FileNamePath == null) {
+            continue;
+          }
+          final String md5FileName = md5FileNamePath.toString();
+          final File snapshotFile = new File(stateMachineDir,
+              md5FileName.substring(0, md5FileName.length() - 
MD5_SUFFIX.length()));
+          if (!snapshotFile.exists()) {
+            FileUtils.deletePathQuietly(md5path);
+          }
         }
       }
     }
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/server/storage/TestRaftStorage.java 
b/ratis-test/src/test/java/org/apache/ratis/server/storage/TestRaftStorage.java
index 7027bd8ea..4465cfdf3 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/server/storage/TestRaftStorage.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/server/storage/TestRaftStorage.java
@@ -18,6 +18,7 @@
 package org.apache.ratis.server.storage;
 
 import static 
org.apache.ratis.statemachine.impl.SimpleStateMachineStorage.SNAPSHOT_REGEX;
+import static org.apache.ratis.util.MD5FileUtil.MD5_SUFFIX;
 
 import org.apache.ratis.BaseTest;
 import org.apache.ratis.RaftTestUtil;
@@ -237,14 +238,22 @@ public class TestRaftStorage extends BaseTest {
     //Create 5 snapshot files in storage dir.
     for (int i = 0; i < 5; i++) {
       final long term = ThreadLocalRandom.current().nextLong(10L);
-      final long index = ThreadLocalRandom.current().nextLong(1000L);
+      final long index = ThreadLocalRandom.current().nextLong(100, 1000L);
       indices.add(index);
       File file = simpleStateMachineStorage.getSnapshotFile(term, index);
       file.createNewFile();
     }
+    // create MD5 files that will not be deleted in older version
+    for (int i = 0; i < 2; i++) {
+      final long index = ThreadLocalRandom.current().nextLong(0, 100L);
+      indices.add(index);
+      File file = simpleStateMachineStorage.getSnapshotFile(1, index);
+      File snapshotFile = new File(file.getParent(), file.getName() + 
MD5_SUFFIX);
+      snapshotFile.createNewFile();
+    }
 
     File stateMachineDir = storage.getStorageDir().getStateMachineDir();
-    Assert.assertTrue(stateMachineDir.listFiles().length == 5);
+    Assert.assertTrue(stateMachineDir.listFiles().length == 7);
     simpleStateMachineStorage.cleanupOldSnapshots(snapshotRetentionPolicy);
     File[] remainingFiles = stateMachineDir.listFiles();
     Assert.assertTrue(remainingFiles.length == 3);

Reply via email to