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;