You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by in...@apache.org on 2019/02/20 22:21:29 UTC
[hadoop] 03/41: HDFS-13845. RBF: The default MountTableResolver
should fail resolving multi-destination paths. Contributed by yanghuafeng.
This is an automated email from the ASF dual-hosted git repository.
inigoiri pushed a commit to branch HDFS-13891
in repository https://gitbox.apache.org/repos/asf/hadoop.git
commit f61a816d35863f524d5d5885f9b8a4dd17daeb77
Author: Brahma Reddy Battula <br...@apache.org>
AuthorDate: Tue Oct 30 11:21:08 2018 +0530
HDFS-13845. RBF: The default MountTableResolver should fail resolving multi-destination paths. Contributed by yanghuafeng.
---
.../federation/resolver/MountTableResolver.java | 15 ++++++--
.../resolver/TestMountTableResolver.java | 45 +++++++++++++++++-----
.../federation/router/TestDisableNameservices.java | 36 ++++++++++-------
3 files changed, 70 insertions(+), 26 deletions(-)
diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/MountTableResolver.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/MountTableResolver.java
index 121469f..9e69840 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/MountTableResolver.java
+++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/MountTableResolver.java
@@ -539,21 +539,28 @@ public class MountTableResolver
* @param entry Mount table entry.
* @return PathLocation containing the namespace, local path.
*/
- private static PathLocation buildLocation(
- final String path, final MountTable entry) {
-
+ private PathLocation buildLocation(
+ final String path, final MountTable entry) throws IOException {
String srcPath = entry.getSourcePath();
if (!path.startsWith(srcPath)) {
LOG.error("Cannot build location, {} not a child of {}", path, srcPath);
return null;
}
+
+ List<RemoteLocation> dests = entry.getDestinations();
+ if (getClass() == MountTableResolver.class && dests.size() > 1) {
+ throw new IOException("Cannnot build location, "
+ + getClass().getSimpleName()
+ + " should not resolve multiple destinations for " + path);
+ }
+
String remainingPath = path.substring(srcPath.length());
if (remainingPath.startsWith(Path.SEPARATOR)) {
remainingPath = remainingPath.substring(1);
}
List<RemoteLocation> locations = new LinkedList<>();
- for (RemoteLocation oneDst : entry.getDestinations()) {
+ for (RemoteLocation oneDst : dests) {
String nsId = oneDst.getNameserviceId();
String dest = oneDst.getDest();
String newPath = dest;
diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/resolver/TestMountTableResolver.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/resolver/TestMountTableResolver.java
index 5e3b861..14ccb61 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/resolver/TestMountTableResolver.java
+++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/resolver/TestMountTableResolver.java
@@ -79,6 +79,8 @@ public class TestMountTableResolver {
* __usr
* ____bin -> 2:/bin
* __readonly -> 2:/tmp
+ * __multi -> 5:/dest1
+ * 6:/dest2
*
* @throws IOException If it cannot set the mount table.
*/
@@ -126,6 +128,12 @@ public class TestMountTableResolver {
MountTable readOnlyEntry = MountTable.newInstance("/readonly", map);
readOnlyEntry.setReadOnly(true);
mountTable.addEntry(readOnlyEntry);
+
+ // /multi
+ map = getMountTableEntry("5", "/dest1");
+ map.put("6", "/dest2");
+ MountTable multiEntry = MountTable.newInstance("/multi", map);
+ mountTable.addEntry(multiEntry);
}
@Before
@@ -201,6 +209,17 @@ public class TestMountTableResolver {
}
}
+ @Test
+ public void testMuiltipleDestinations() throws IOException {
+ try {
+ mountTable.getDestinationForPath("/multi");
+ fail("The getDestinationForPath call should fail.");
+ } catch (IOException ioe) {
+ GenericTestUtils.assertExceptionContains(
+ "MountTableResolver should not resolve multiple destinations", ioe);
+ }
+ }
+
private void compareLists(List<String> list1, String[] list2) {
assertEquals(list1.size(), list2.length);
for (String item : list2) {
@@ -236,8 +255,9 @@ public class TestMountTableResolver {
// Check getting all mount points (virtual and real) beneath a path
List<String> mounts = mountTable.getMountPoints("/");
- assertEquals(4, mounts.size());
- compareLists(mounts, new String[] {"tmp", "user", "usr", "readonly"});
+ assertEquals(5, mounts.size());
+ compareLists(mounts, new String[] {"tmp", "user", "usr",
+ "readonly", "multi"});
mounts = mountTable.getMountPoints("/user");
assertEquals(2, mounts.size());
@@ -263,6 +283,9 @@ public class TestMountTableResolver {
mounts = mountTable.getMountPoints("/unknownpath");
assertNull(mounts);
+
+ mounts = mountTable.getMountPoints("/multi");
+ assertEquals(0, mounts.size());
}
private void compareRecords(List<MountTable> list1, String[] list2) {
@@ -282,10 +305,10 @@ public class TestMountTableResolver {
// Check listing the mount table records at or beneath a path
List<MountTable> records = mountTable.getMounts("/");
- assertEquals(9, records.size());
+ assertEquals(10, records.size());
compareRecords(records, new String[] {"/", "/tmp", "/user", "/usr/bin",
"user/a", "/user/a/demo/a", "/user/a/demo/b", "/user/b/file1.txt",
- "readonly"});
+ "readonly", "multi"});
records = mountTable.getMounts("/user");
assertEquals(5, records.size());
@@ -305,6 +328,10 @@ public class TestMountTableResolver {
assertEquals(1, records.size());
compareRecords(records, new String[] {"/readonly"});
assertTrue(records.get(0).isReadOnly());
+
+ records = mountTable.getMounts("/multi");
+ assertEquals(1, records.size());
+ compareRecords(records, new String[] {"/multi"});
}
@Test
@@ -313,7 +340,7 @@ public class TestMountTableResolver {
// 3 mount points are present /tmp, /user, /usr
compareLists(mountTable.getMountPoints("/"),
- new String[] {"user", "usr", "tmp", "readonly"});
+ new String[] {"user", "usr", "tmp", "readonly", "multi"});
// /tmp currently points to namespace 2
assertEquals("2", mountTable.getDestinationForPath("/tmp/testfile.txt")
@@ -324,7 +351,7 @@ public class TestMountTableResolver {
// Now 2 mount points are present /user, /usr
compareLists(mountTable.getMountPoints("/"),
- new String[] {"user", "usr", "readonly"});
+ new String[] {"user", "usr", "readonly", "multi"});
// /tmp no longer exists, uses default namespace for mapping /
assertEquals("1", mountTable.getDestinationForPath("/tmp/testfile.txt")
@@ -337,7 +364,7 @@ public class TestMountTableResolver {
// 3 mount points are present /tmp, /user, /usr
compareLists(mountTable.getMountPoints("/"),
- new String[] {"user", "usr", "tmp", "readonly"});
+ new String[] {"user", "usr", "tmp", "readonly", "multi"});
// /usr is virtual, uses namespace 1->/
assertEquals("1", mountTable.getDestinationForPath("/usr/testfile.txt")
@@ -348,7 +375,7 @@ public class TestMountTableResolver {
// Verify the remove failed
compareLists(mountTable.getMountPoints("/"),
- new String[] {"user", "usr", "tmp", "readonly"});
+ new String[] {"user", "usr", "tmp", "readonly", "multi"});
}
@Test
@@ -380,7 +407,7 @@ public class TestMountTableResolver {
// Initial table loaded
testDestination();
- assertEquals(9, mountTable.getMounts("/").size());
+ assertEquals(10, mountTable.getMounts("/").size());
// Replace table with /1 and /2
List<MountTable> records = new ArrayList<>();
diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestDisableNameservices.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestDisableNameservices.java
index 15b104d..610927d 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestDisableNameservices.java
+++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestDisableNameservices.java
@@ -21,6 +21,7 @@ import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.simul
import static org.apache.hadoop.util.Time.monotonicNow;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.Iterator;
@@ -43,13 +44,13 @@ import org.apache.hadoop.hdfs.server.federation.metrics.FederationMetrics;
import org.apache.hadoop.hdfs.server.federation.resolver.MembershipNamenodeResolver;
import org.apache.hadoop.hdfs.server.federation.resolver.MountTableManager;
import org.apache.hadoop.hdfs.server.federation.resolver.MountTableResolver;
-import org.apache.hadoop.hdfs.server.federation.resolver.order.DestinationOrder;
import org.apache.hadoop.hdfs.server.federation.store.DisabledNameserviceStore;
import org.apache.hadoop.hdfs.server.federation.store.StateStoreService;
import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryRequest;
import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
import org.apache.hadoop.hdfs.server.federation.store.records.MountTable;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
+import org.apache.hadoop.test.GenericTestUtils;
import org.codehaus.jettison.json.JSONObject;
import org.junit.After;
import org.junit.AfterClass;
@@ -106,14 +107,18 @@ public class TestDisableNameservices {
// Setup a mount table to map to the two namespaces
MountTableManager mountTable = routerAdminClient.getMountTableManager();
Map<String, String> destinations = new TreeMap<>();
- destinations.put("ns0", "/");
- destinations.put("ns1", "/");
- MountTable newEntry = MountTable.newInstance("/", destinations);
- newEntry.setDestOrder(DestinationOrder.RANDOM);
+ destinations.put("ns0", "/dirns0");
+ MountTable newEntry = MountTable.newInstance("/dirns0", destinations);
AddMountTableEntryRequest request =
AddMountTableEntryRequest.newInstance(newEntry);
mountTable.addMountTableEntry(request);
+ destinations = new TreeMap<>();
+ destinations.put("ns1", "/dirns1");
+ newEntry = MountTable.newInstance("/dirns1", destinations);
+ request = AddMountTableEntryRequest.newInstance(newEntry);
+ mountTable.addMountTableEntry(request);
+
// Refresh the cache in the Router
Router router = routerContext.getRouter();
MountTableResolver mountTableResolver =
@@ -122,9 +127,9 @@ public class TestDisableNameservices {
// Add a folder to each namespace
NamenodeContext nn0 = cluster.getNamenode("ns0", null);
- nn0.getFileSystem().mkdirs(new Path("/dirns0"));
+ nn0.getFileSystem().mkdirs(new Path("/dirns0/0"));
NamenodeContext nn1 = cluster.getNamenode("ns1", null);
- nn1.getFileSystem().mkdirs(new Path("/dirns1"));
+ nn1.getFileSystem().mkdirs(new Path("/dirns1/1"));
}
@AfterClass
@@ -153,14 +158,12 @@ public class TestDisableNameservices {
@Test
public void testWithoutDisabling() throws IOException {
-
// ns0 is slow and renewLease should take a long time
long t0 = monotonicNow();
routerProtocol.renewLease("client0");
long t = monotonicNow() - t0;
assertTrue("It took too little: " + t + "ms",
t > TimeUnit.SECONDS.toMillis(1));
-
// Return the results from all subclusters even if slow
FileSystem routerFs = routerContext.getFileSystem();
FileStatus[] filesStatus = routerFs.listStatus(new Path("/"));
@@ -171,7 +174,6 @@ public class TestDisableNameservices {
@Test
public void testDisabling() throws Exception {
-
disableNameservice("ns0");
// renewLease should be fast as we are skipping ns0
@@ -180,12 +182,20 @@ public class TestDisableNameservices {
long t = monotonicNow() - t0;
assertTrue("It took too long: " + t + "ms",
t < TimeUnit.SECONDS.toMillis(1));
-
// We should not report anything from ns0
FileSystem routerFs = routerContext.getFileSystem();
- FileStatus[] filesStatus = routerFs.listStatus(new Path("/"));
+ FileStatus[] filesStatus = null;
+ try {
+ routerFs.listStatus(new Path("/"));
+ fail("The listStatus call should fail.");
+ } catch (IOException ioe) {
+ GenericTestUtils.assertExceptionContains(
+ "No remote locations available", ioe);
+ }
+
+ filesStatus = routerFs.listStatus(new Path("/dirns1"));
assertEquals(1, filesStatus.length);
- assertEquals("dirns1", filesStatus[0].getPath().getName());
+ assertEquals("1", filesStatus[0].getPath().getName());
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org