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/incubator-ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new 2fd6c04  RATIS-692. RaftStorageDirectory.tryLock throws a very deep 
IOException.
2fd6c04 is described below

commit 2fd6c04dd12f4da9b23f4e4c5c0dd24134b42c17
Author: Tsz Wo Nicholas Sze <[email protected]>
AuthorDate: Thu Oct 24 08:53:03 2019 -0700

    RATIS-692. RaftStorageDirectory.tryLock throws a very deep IOException.
---
 .../src/main/java/org/apache/ratis/util/FileUtils.java    | 15 ++++++++++++++-
 .../src/main/java/org/apache/ratis/util/JavaUtils.java    | 10 +++++++++-
 .../src/main/java/org/apache/ratis/util/TimeDuration.java |  1 +
 ratis-common/src/test/java/org/apache/ratis/BaseTest.java |  2 +-
 .../apache/ratis/server/storage/RaftStorageDirectory.java |  6 +++---
 5 files changed, 28 insertions(+), 6 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 1033512..d3b7c75 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
@@ -1,4 +1,4 @@
-/**
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -17,6 +17,7 @@
  */
 package org.apache.ratis.util;
 
+import org.apache.ratis.util.function.CheckedSupplier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -26,10 +27,22 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.file.*;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.util.function.Supplier;
 
 public interface FileUtils {
   Logger LOG = LoggerFactory.getLogger(FileUtils.class);
 
+  int NUM_ATTEMPTS = 5;
+  TimeDuration SLEEP_TIME = TimeDuration.ONE_SECOND;
+
+  static <T> T attempt(CheckedSupplier<T, IOException> op, Supplier<?> name) 
throws IOException {
+    try {
+      return JavaUtils.attempt(op, NUM_ATTEMPTS, SLEEP_TIME, name, LOG);
+    } catch (InterruptedException e) {
+      throw IOUtils.toInterruptedIOException("Interrupted " + name.get(), e);
+    }
+  }
+
   static void truncateFile(File f, long target) throws IOException {
     final long original = f.length();
     LogUtils.runAndLog(LOG,
diff --git a/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java 
b/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java
index c37b792..22215af 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/JavaUtils.java
@@ -143,6 +143,14 @@ public interface JavaUtils {
       CheckedSupplier<RETURN, THROWABLE> supplier,
       int numAttempts, TimeDuration sleepTime, String name, Logger log)
       throws THROWABLE, InterruptedException {
+    return attempt(supplier, numAttempts, sleepTime, () -> name, log);
+  }
+
+  /** Attempt to get a return value from the given supplier multiple times. */
+  static <RETURN, THROWABLE extends Throwable> RETURN attempt(
+      CheckedSupplier<RETURN, THROWABLE> supplier,
+      int numAttempts, TimeDuration sleepTime, Supplier<?> name, Logger log)
+      throws THROWABLE, InterruptedException {
     Objects.requireNonNull(supplier, "supplier == null");
     Preconditions.assertTrue(numAttempts > 0, () -> "numAttempts = " + 
numAttempts + " <= 0");
     Preconditions.assertTrue(!sleepTime.isNegative(), () -> "sleepTime = " + 
sleepTime + " < 0");
@@ -155,7 +163,7 @@ public interface JavaUtils {
           throw t;
         }
         if (log != null && log.isWarnEnabled()) {
-          log.warn("FAILED \"" + name + "\", attempt #" + i + "/" + numAttempts
+          log.warn("FAILED \"" + name.get() + "\", attempt #" + i + "/" + 
numAttempts
               + ": " + t + ", sleep " + sleepTime + " and then retry.", t);
         }
       }
diff --git a/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java 
b/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java
index 51dfe7a..987b628 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/TimeDuration.java
@@ -32,6 +32,7 @@ import java.util.function.LongUnaryOperator;
  * This is a value-based class.
  */
 public final class TimeDuration implements Comparable<TimeDuration> {
+  public static final TimeDuration ONE_SECOND = TimeDuration.valueOf(1, 
TimeUnit.SECONDS);
 
   /** Abbreviations of {@link TimeUnit}. */
   public enum Abbreviation {
diff --git a/ratis-common/src/test/java/org/apache/ratis/BaseTest.java 
b/ratis-common/src/test/java/org/apache/ratis/BaseTest.java
index 5edbf38..7e8868d 100644
--- a/ratis-common/src/test/java/org/apache/ratis/BaseTest.java
+++ b/ratis-common/src/test/java/org/apache/ratis/BaseTest.java
@@ -47,7 +47,7 @@ public abstract class BaseTest {
   public final Logger LOG = LoggerFactory.getLogger(getClass());
 
   public static final TimeDuration HUNDRED_MILLIS = TimeDuration.valueOf(100, 
TimeUnit.MILLISECONDS);
-  public static final TimeDuration ONE_SECOND = TimeDuration.valueOf(1, 
TimeUnit.SECONDS);
+  public static final TimeDuration ONE_SECOND = TimeDuration.ONE_SECOND;
   public static final TimeDuration FIVE_SECONDS = TimeDuration.valueOf(5, 
TimeUnit.SECONDS);
 
   {
diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftStorageDirectory.java
 
b/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftStorageDirectory.java
index 9cc7db0..7a09442 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftStorageDirectory.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/storage/RaftStorageDirectory.java
@@ -288,7 +288,8 @@ public class RaftStorageDirectory {
    * @throws IOException if locking fails
    */
   public void lock() throws IOException {
-    FileLock newLock = tryLock();
+    final File lockF = new File(root, STORAGE_FILE_LOCK);
+    final FileLock newLock = FileUtils.attempt(() -> tryLock(lockF), () -> 
"tryLock " + lockF);
     if (newLock == null) {
       String msg = "Cannot lock storage " + this.root
           + ". The directory is already locked";
@@ -308,9 +309,8 @@ public class RaftStorageDirectory {
    * <code>null</code> if storage is already locked.
    * @throws IOException if locking fails.
    */
-  private FileLock tryLock() throws IOException {
+  private FileLock tryLock(File lockF) throws IOException {
     boolean deletionHookAdded = false;
-    File lockF = new File(root, STORAGE_FILE_LOCK);
     if (!lockF.exists()) {
       lockF.deleteOnExit();
       deletionHookAdded = true;

Reply via email to