Skip to content

Commit 1534f32

Browse files
author
fuchaohong
committed
RBF: The construction of the trash path in the downstream nameservice should be based on src locations.
1 parent 4bd873b commit 1534f32

File tree

4 files changed

+101
-1
lines changed

4 files changed

+101
-1
lines changed

hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/MountTableResolver.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import static org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys.FEDERATION_MOUNT_TABLE_MAX_CACHE_SIZE_DEFAULT;
2525
import static org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys.FEDERATION_MOUNT_TABLE_CACHE_ENABLE;
2626
import static org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys.FEDERATION_MOUNT_TABLE_CACHE_ENABLE_DEFAULT;
27+
import static org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys.DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT;
28+
import static org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys.DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT_DEFAULT;
2729
import static org.apache.hadoop.hdfs.DFSUtil.isParentEntry;
2830

2931
import java.io.IOException;
@@ -90,6 +92,8 @@ public class MountTableResolver
9092
private final StateStoreService stateStore;
9193
/** Interface to the mount table store. */
9294
private MountTableStore mountTableStore;
95+
/** Configuration for the RPC server. */
96+
private Configuration conf;
9397

9498
/** If the tree has been initialized. */
9599
private boolean init = false;
@@ -131,6 +135,7 @@ public MountTableResolver(Configuration conf, StateStoreService store) {
131135
public MountTableResolver(Configuration conf, Router routerService,
132136
StateStoreService store) {
133137
this.router = routerService;
138+
this.conf = conf;
134139
if (store != null) {
135140
this.stateStore = store;
136141
} else if (this.router != null) {
@@ -460,9 +465,13 @@ public PathLocation getDestinationForPath(final String path)
460465
this.getLocCacheAccess().increment();
461466
}
462467
if (isTrashPath(path)) {
468+
boolean useMountPointCreateTrashPath = conf.getBoolean(
469+
DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT,
470+
DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT_DEFAULT);
463471
List<RemoteLocation> remoteLocations = new ArrayList<>();
464472
for (RemoteLocation remoteLocation : res.getDestinations()) {
465-
remoteLocations.add(new RemoteLocation(remoteLocation, path));
473+
remoteLocations.add(new RemoteLocation(remoteLocation,
474+
useMountPointCreateTrashPath ? path : getTrashRoot() + "/Current" + remoteLocation.getDest()));
466475
}
467476
return new PathLocation(path, remoteLocations,
468477
res.getDestinationOrder());

hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RBFConfigKeys.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ public class RBFConfigKeys extends CommonConfigurationKeysPublic {
8686
public static final int
8787
DFS_ROUTER_METRICS_TOP_NUM_TOKEN_OWNERS_KEY_DEFAULT = 10;
8888

89+
public static final String DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT =
90+
FEDERATION_ROUTER_PREFIX + "trash-path.created-by.mount-point";
91+
public static final boolean DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT_DEFAULT = false;
92+
8993
// HDFS Router heartbeat
9094
public static final String DFS_ROUTER_HEARTBEAT_ENABLE =
9195
FEDERATION_ROUTER_PREFIX + "heartbeat.enable";

hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/resources/hdfs-rbf-default.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,15 @@
673673
</description>
674674
</property>
675675

676+
<property>
677+
<name>dfs.federation.router.trash-path.created-by.mount-point</name>
678+
<value>false</value>
679+
<description>
680+
Set to true to use the mount point to create trash path
681+
when path is the trail associated with the Trash.
682+
</description>
683+
</property>
684+
676685
<property>
677686
<name>dfs.federation.router.keytab.file</name>
678687
<value></value>

hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterTrash.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import java.util.Collections;
4747

4848
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY;
49+
import static org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys.DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT;
4950
import static org.junit.Assert.assertTrue;
5051
import static org.junit.Assert.assertFalse;
5152
import static org.junit.Assert.assertEquals;
@@ -70,6 +71,8 @@ public class TestRouterTrash {
7071
private static String ns1;
7172
private static final String MOUNT_POINT = "/home/data";
7273
private static final String FILE = MOUNT_POINT + "/file1";
74+
private static final String DST_PATH = "/home/dst_data";
75+
private static final String DST_FILE = DST_PATH + "/file1";
7376
private static final String TRASH_ROOT = "/user/" + TEST_USER + "/.Trash";
7477
private static final String CURRENT = "/Current";
7578

@@ -276,6 +279,81 @@ public void testDeleteToTrashExistMountPoint() throws IOException,
276279
assertEquals(2, fileStatuses.length);
277280
}
278281

282+
private void deleteToTrashExistMountPoint() throws IOException,
283+
URISyntaxException, InterruptedException {
284+
MountTable addEntry = MountTable.newInstance(MOUNT_POINT,
285+
Collections.singletonMap(ns0, DST_PATH));
286+
assertTrue(addMountTable(addEntry));
287+
288+
// current user client
289+
DFSClient client = nnContext.getClient();
290+
client.setOwner("/", TEST_USER, TEST_USER);
291+
UserGroupInformation ugi = UserGroupInformation.
292+
createRemoteUser(TEST_USER);
293+
// test user client
294+
client = nnContext.getClient(ugi);
295+
client.mkdirs(DST_PATH, new FsPermission("777"), true);
296+
assertTrue(client.exists(DST_PATH));
297+
// create test file
298+
client.create(DST_FILE, true);
299+
300+
Path filePath = new Path(FILE);
301+
FileStatus[] fileStatuses = routerFs.listStatus(filePath);
302+
assertEquals(1, fileStatuses.length);
303+
assertEquals(TEST_USER, fileStatuses[0].getOwner());
304+
305+
// move to Trash.
306+
Configuration routerConf = routerContext.getConf();
307+
FileSystem fs =
308+
DFSTestUtil.getFileSystemAs(ugi, routerConf);
309+
Trash trash = new Trash(fs, routerConf);
310+
assertTrue(trash.moveToTrash(filePath));
311+
}
312+
313+
@Test
314+
public void testTrashPathStructure() throws IOException,
315+
URISyntaxException, InterruptedException {
316+
// Trash path created by dst_path by default.
317+
deleteToTrashExistMountPoint();
318+
FileStatus[] fileStatuses = nnFs.listStatus(
319+
new Path(TRASH_ROOT + CURRENT + DST_PATH));
320+
assertEquals(1, fileStatuses.length);
321+
assertTrue(nnFs.exists(new Path(TRASH_ROOT + CURRENT + DST_FILE)));
322+
323+
// Re-build and start a federated cluster with dfs.federation.router.trash-path.created-by.mount-point=true.
324+
tearDown();
325+
cluster = new StateStoreDFSCluster(false, 2);
326+
Configuration conf = new RouterConfigBuilder()
327+
.stateStore()
328+
.admin()
329+
.rpc()
330+
.http()
331+
.build();
332+
conf.set(FS_TRASH_INTERVAL_KEY, "100");
333+
conf.setBoolean(DFS_ROUTER_TRASH_PATH_CREATED_BY_MOUNT_POINT, true);
334+
cluster.addRouterOverrides(conf);
335+
cluster.startCluster();
336+
cluster.startRouters();
337+
cluster.waitClusterUp();
338+
339+
ns0 = cluster.getNameservices().get(0);
340+
ns1 = cluster.getNameservices().get(1);
341+
342+
routerContext = cluster.getRandomRouter();
343+
routerFs = routerContext.getFileSystem();
344+
nnContext = cluster.getNamenode(ns0, null);
345+
nnFs = nnContext.getFileSystem();
346+
Router router = routerContext.getRouter();
347+
mountTable = (MountTableResolver) router.getSubclusterResolver();
348+
349+
// Trash path created by mount_point.
350+
deleteToTrashExistMountPoint();
351+
fileStatuses = nnFs.listStatus(
352+
new Path(TRASH_ROOT + CURRENT + MOUNT_POINT));
353+
assertEquals(1, fileStatuses.length);
354+
assertTrue(nnFs.exists(new Path(TRASH_ROOT + CURRENT + FILE)));
355+
}
356+
279357
@Test
280358
public void testIsTrashPath() throws IOException {
281359
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();

0 commit comments

Comments
 (0)