HDFS-14654. RBF: TestRouterRpc#testNamenodeMetrics is flaky. Contributed by Chen Zhang.

This commit is contained in:
Ayush Saxena 2019-09-02 13:01:52 +05:30
parent f4d6e82075
commit 040f6e93bb
2 changed files with 41 additions and 16 deletions

View File

@ -58,6 +58,7 @@ public class MockResolver
private Set<FederationNamespaceInfo> namespaces = new HashSet<>(); private Set<FederationNamespaceInfo> namespaces = new HashSet<>();
private String defaultNamespace = null; private String defaultNamespace = null;
private boolean disableDefaultNamespace = false; private boolean disableDefaultNamespace = false;
private volatile boolean disableRegistration = false;
public MockResolver() { public MockResolver() {
this.cleanRegistrations(); this.cleanRegistrations();
@ -98,6 +99,15 @@ public class MockResolver
this.namespaces = new HashSet<>(); this.namespaces = new HashSet<>();
} }
/*
* Disable NameNode auto registration for test. This method usually used after
* {@link MockResolver#cleanRegistrations()}, and before {@link
* MockResolver#registerNamenode()}
*/
public void setDisableRegistration(boolean isDisable) {
disableRegistration = isDisable;
}
@Override @Override
public void updateActiveNamenode( public void updateActiveNamenode(
String nsId, InetSocketAddress successfulAddress) { String nsId, InetSocketAddress successfulAddress) {
@ -125,7 +135,7 @@ public class MockResolver
} }
@Override @Override
public List<? extends FederationNamenodeContext> public synchronized List<? extends FederationNamenodeContext>
getNamenodesForNameserviceId(String nameserviceId) { getNamenodesForNameserviceId(String nameserviceId) {
// Return a copy of the list because it is updated periodically // Return a copy of the list because it is updated periodically
List<? extends FederationNamenodeContext> namenodes = List<? extends FederationNamenodeContext> namenodes =
@ -137,8 +147,8 @@ public class MockResolver
} }
@Override @Override
public List<? extends FederationNamenodeContext> getNamenodesForBlockPoolId( public synchronized List<? extends FederationNamenodeContext>
String blockPoolId) { getNamenodesForBlockPoolId(String blockPoolId) {
// Return a copy of the list because it is updated periodically // Return a copy of the list because it is updated periodically
List<? extends FederationNamenodeContext> namenodes = List<? extends FederationNamenodeContext> namenodes =
this.resolver.get(blockPoolId); this.resolver.get(blockPoolId);
@ -226,6 +236,9 @@ public class MockResolver
@Override @Override
public synchronized boolean registerNamenode(NamenodeStatusReport report) public synchronized boolean registerNamenode(NamenodeStatusReport report)
throws IOException { throws IOException {
if (disableRegistration) {
return false;
}
MockNamenodeContext context = new MockNamenodeContext( MockNamenodeContext context = new MockNamenodeContext(
report.getRpcAddress(), report.getServiceAddress(), report.getRpcAddress(), report.getServiceAddress(),
@ -263,8 +276,9 @@ public class MockResolver
} }
@Override @Override
public Set<FederationNamespaceInfo> getNamespaces() throws IOException { public synchronized Set<FederationNamespaceInfo> getNamespaces()
return this.namespaces; throws IOException {
return Collections.unmodifiableSet(this.namespaces);
} }
@Override @Override

View File

@ -1575,6 +1575,13 @@ public class TestRouterRpc {
.setSafeMode(HdfsConstants.SafeModeAction.SAFEMODE_LEAVE); .setSafeMode(HdfsConstants.SafeModeAction.SAFEMODE_LEAVE);
} }
/*
* This case is used to test NameNodeMetrics on 2 purposes:
* 1. NameNodeMetrics should be cached, since the cost of gathering the
* metrics is expensive
* 2. Metrics cache should updated regularly
* 3. Without any subcluster available, we should return an empty list
*/
@Test @Test
public void testNamenodeMetrics() throws Exception { public void testNamenodeMetrics() throws Exception {
final NamenodeBeanMetrics metrics = final NamenodeBeanMetrics metrics =
@ -1606,17 +1613,21 @@ public class TestRouterRpc {
MockResolver resolver = MockResolver resolver =
(MockResolver) router.getRouter().getNamenodeResolver(); (MockResolver) router.getRouter().getNamenodeResolver();
resolver.cleanRegistrations(); resolver.cleanRegistrations();
GenericTestUtils.waitFor(new Supplier<Boolean>() { resolver.setDisableRegistration(true);
@Override try {
public Boolean get() { GenericTestUtils.waitFor(new Supplier<Boolean>() {
return !jsonString2.equals(metrics.getLiveNodes()); @Override
} public Boolean get() {
}, 500, 5 * 1000); return !jsonString2.equals(metrics.getLiveNodes());
assertEquals("{}", metrics.getLiveNodes()); }
}, 500, 5 * 1000);
// Reset the registrations again assertEquals("{}", metrics.getLiveNodes());
cluster.registerNamenodes(); } finally {
cluster.waitNamenodeRegistration(); // Reset the registrations again
resolver.setDisableRegistration(false);
cluster.registerNamenodes();
cluster.waitNamenodeRegistration();
}
} }
@Test @Test