HDFS-9347. Invariant assumption in TestQuorumJournalManager.shutdown() is wrong. Contributed by Wei-Chiu Chuang.
Change-Id: Idde8522e11c77f82b376e0c90a9bf33d163d5cb9
This commit is contained in:
parent
1147b086d9
commit
223b47b398
|
@ -417,6 +417,26 @@ public abstract class GenericTestUtils {
|
||||||
+ expectedMax + ")", expectedMin <= actual && actual <= expectedMax);
|
+ expectedMax + ")", expectedMin <= actual && actual <= expectedMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if there are any threads whose name matches the regex.
|
||||||
|
* @param pattern a Pattern object used to match thread names
|
||||||
|
* @return true if there is any thread that matches the pattern
|
||||||
|
*/
|
||||||
|
public static boolean anyThreadMatching(Pattern pattern) {
|
||||||
|
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
|
||||||
|
|
||||||
|
ThreadInfo[] infos =
|
||||||
|
threadBean.getThreadInfo(threadBean.getAllThreadIds(), 20);
|
||||||
|
for (ThreadInfo info : infos) {
|
||||||
|
if (info == null)
|
||||||
|
continue;
|
||||||
|
if (pattern.matcher(info.getThreadName()).matches()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert that there are no threads running whose name matches the
|
* Assert that there are no threads running whose name matches the
|
||||||
* given regular expression.
|
* given regular expression.
|
||||||
|
@ -424,18 +444,34 @@ public abstract class GenericTestUtils {
|
||||||
*/
|
*/
|
||||||
public static void assertNoThreadsMatching(String regex) {
|
public static void assertNoThreadsMatching(String regex) {
|
||||||
Pattern pattern = Pattern.compile(regex);
|
Pattern pattern = Pattern.compile(regex);
|
||||||
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
|
if (anyThreadMatching(pattern)) {
|
||||||
|
Assert.fail("Leaked thread matches " + regex);
|
||||||
ThreadInfo[] infos = threadBean.getThreadInfo(threadBean.getAllThreadIds(), 20);
|
|
||||||
for (ThreadInfo info : infos) {
|
|
||||||
if (info == null) continue;
|
|
||||||
if (pattern.matcher(info.getThreadName()).matches()) {
|
|
||||||
Assert.fail("Leaked thread: " + info + "\n" +
|
|
||||||
Joiner.on("\n").join(info.getStackTrace()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Periodically check and wait for any threads whose name match the
|
||||||
|
* given regular expression.
|
||||||
|
*
|
||||||
|
* @param regex the regex to match against.
|
||||||
|
* @param checkEveryMillis time (in milliseconds) between checks.
|
||||||
|
* @param waitForMillis total time (in milliseconds) to wait before throwing
|
||||||
|
* a time out exception.
|
||||||
|
* @throws TimeoutException
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
public static void waitForThreadTermination(String regex,
|
||||||
|
int checkEveryMillis, final int waitForMillis) throws TimeoutException,
|
||||||
|
InterruptedException {
|
||||||
|
final Pattern pattern = Pattern.compile(regex);
|
||||||
|
waitFor(new Supplier<Boolean>() {
|
||||||
|
@Override public Boolean get() {
|
||||||
|
return !anyThreadMatching(pattern);
|
||||||
|
}
|
||||||
|
}, checkEveryMillis, waitForMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skip test if native build profile of Maven is not activated.
|
* Skip test if native build profile of Maven is not activated.
|
||||||
* Sub-project using this must set 'runningWithNative' property to true
|
* Sub-project using this must set 'runningWithNative' property to true
|
||||||
|
|
|
@ -1664,6 +1664,9 @@ Release 2.8.0 - UNRELEASED
|
||||||
replicas should go through BlockPlacementPolicy
|
replicas should go through BlockPlacementPolicy
|
||||||
(J.Andreina via vinayakumarb)
|
(J.Andreina via vinayakumarb)
|
||||||
|
|
||||||
|
HDFS-9347. Invariant assumption in TestQuorumJournalManager.shutdown()
|
||||||
|
is wrong. (Wei-Chiu Chuang via zhz)
|
||||||
|
|
||||||
Release 2.7.3 - UNRELEASED
|
Release 2.7.3 - UNRELEASED
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
|
|
@ -38,6 +38,7 @@ import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -103,21 +104,23 @@ public class TestQuorumJournalManager {
|
||||||
qjm.recoverUnfinalizedSegments();
|
qjm.recoverUnfinalizedSegments();
|
||||||
assertEquals(1, qjm.getLoggerSetForTests().getEpoch());
|
assertEquals(1, qjm.getLoggerSetForTests().getEpoch());
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void shutdown() throws IOException {
|
public void shutdown() throws IOException, InterruptedException,
|
||||||
|
TimeoutException {
|
||||||
IOUtils.cleanup(LOG, toClose.toArray(new Closeable[0]));
|
IOUtils.cleanup(LOG, toClose.toArray(new Closeable[0]));
|
||||||
|
|
||||||
// Should not leak clients between tests -- this can cause flaky tests.
|
// Should not leak clients between tests -- this can cause flaky tests.
|
||||||
// (See HDFS-4643)
|
// (See HDFS-4643)
|
||||||
GenericTestUtils.assertNoThreadsMatching(".*IPC Client.*");
|
// Wait for IPC clients to terminate to avoid flaky tests
|
||||||
|
GenericTestUtils.waitForThreadTermination(".*IPC Client.*", 100, 1000);
|
||||||
|
|
||||||
if (cluster != null) {
|
if (cluster != null) {
|
||||||
cluster.shutdown();
|
cluster.shutdown();
|
||||||
cluster = null;
|
cluster = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enqueue a QJM for closing during shutdown. This makes the code a little
|
* Enqueue a QJM for closing during shutdown. This makes the code a little
|
||||||
* easier to follow, with fewer try..finally clauses necessary.
|
* easier to follow, with fewer try..finally clauses necessary.
|
||||||
|
|
Loading…
Reference in New Issue