This is an automated email from the ASF dual-hosted git repository.
ayushsaxena pushed a commit to branch HDFS-13891
in repository https://gitbox.apache.org/repos/asf/hadoop.git
The following commit(s) were added to refs/heads/HDFS-13891 by this push:
new 58a22e9 HDFS-13787. RBF: Add Snapshot related ClientProtocol APIs.
Contributed by Inigo Goiri.
58a22e9 is described below
commit 58a22e924954a933731c1ecb331aaba4e8b32cbc
Author: Ayush Saxena <[email protected]>
AuthorDate: Thu May 30 19:58:19 2019 +0530
HDFS-13787. RBF: Add Snapshot related ClientProtocol APIs. Contributed by
Inigo Goiri.
---
.../federation/router/RouterClientProtocol.java | 30 +--
.../server/federation/router/RouterRpcClient.java | 9 +
.../server/federation/router/RouterRpcServer.java | 16 +-
.../server/federation/router/RouterSnapshot.java | 208 +++++++++++++++++++++
.../server/federation/router/TestRouterRpc.java | 130 +++++++++++++
5 files changed, 372 insertions(+), 21 deletions(-)
diff --git
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java
index 66718fb..9d33608 100644
---
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java
+++
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java
@@ -136,6 +136,8 @@ public class RouterClientProtocol implements ClientProtocol
{
private final RouterCacheAdmin routerCacheAdmin;
/** StoragePolicy calls. **/
private final RouterStoragePolicy storagePolicy;
+ /** Snapshot calls. */
+ private final RouterSnapshot snapshotProto;
/** Router security manager to handle token operations. */
private RouterSecurityManager securityManager = null;
@@ -166,6 +168,7 @@ public class RouterClientProtocol implements ClientProtocol
{
DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_DEFAULT);
this.erasureCoding = new ErasureCoding(rpcServer);
this.storagePolicy = new RouterStoragePolicy(rpcServer);
+ this.snapshotProto = new RouterSnapshot(rpcServer);
this.routerCacheAdmin = new RouterCacheAdmin(rpcServer);
this.securityManager = rpcServer.getRouterSecurityManager();
}
@@ -1221,42 +1224,42 @@ public class RouterClientProtocol implements
ClientProtocol {
return rpcClient.invokeSequential(locations, method, String.class, null);
}
- @Override // Client Protocol
+ @Override
public void allowSnapshot(String snapshotRoot) throws IOException {
- rpcServer.checkOperation(NameNode.OperationCategory.WRITE, false);
+ snapshotProto.allowSnapshot(snapshotRoot);
}
- @Override // Client Protocol
+ @Override
public void disallowSnapshot(String snapshot) throws IOException {
- rpcServer.checkOperation(NameNode.OperationCategory.WRITE, false);
+ snapshotProto.disallowSnapshot(snapshot);
}
@Override
public void renameSnapshot(String snapshotRoot, String snapshotOldName,
String snapshotNewName) throws IOException {
- rpcServer.checkOperation(NameNode.OperationCategory.WRITE, false);
+ snapshotProto.renameSnapshot(
+ snapshotRoot, snapshotOldName, snapshotNewName);
}
@Override
public SnapshottableDirectoryStatus[] getSnapshottableDirListing()
throws IOException {
- rpcServer.checkOperation(NameNode.OperationCategory.READ, false);
- return null;
+ return snapshotProto.getSnapshottableDirListing();
}
@Override
public SnapshotDiffReport getSnapshotDiffReport(String snapshotRoot,
String earlierSnapshotName, String laterSnapshotName) throws IOException
{
- rpcServer.checkOperation(NameNode.OperationCategory.READ, false);
- return null;
+ return snapshotProto.getSnapshotDiffReport(
+ snapshotRoot, earlierSnapshotName, laterSnapshotName);
}
@Override
public SnapshotDiffReportListing getSnapshotDiffReportListing(
String snapshotRoot, String earlierSnapshotName, String
laterSnapshotName,
byte[] startPath, int index) throws IOException {
- rpcServer.checkOperation(NameNode.OperationCategory.READ, false);
- return null;
+ return snapshotProto.getSnapshotDiffReportListing(
+ snapshotRoot, earlierSnapshotName, laterSnapshotName, startPath,
index);
}
@Override
@@ -1558,14 +1561,13 @@ public class RouterClientProtocol implements
ClientProtocol {
@Override
public String createSnapshot(String snapshotRoot, String snapshotName)
throws IOException {
- rpcServer.checkOperation(NameNode.OperationCategory.WRITE);
- return null;
+ return snapshotProto.createSnapshot(snapshotRoot, snapshotName);
}
@Override
public void deleteSnapshot(String snapshotRoot, String snapshotName)
throws IOException {
- rpcServer.checkOperation(NameNode.OperationCategory.WRITE, false);
+ snapshotProto.deleteSnapshot(snapshotRoot, snapshotName);
}
@Override
diff --git
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcClient.java
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcClient.java
index 19aa13a..0370438 100644
---
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcClient.java
+++
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcClient.java
@@ -56,6 +56,7 @@ import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.NameNodeProxiesClient.ProxyAndInfo;
import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys;
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
+import org.apache.hadoop.hdfs.protocol.SnapshotException;
import
org.apache.hadoop.hdfs.server.federation.resolver.ActiveNamenodeResolver;
import
org.apache.hadoop.hdfs.server.federation.resolver.FederationNamenodeContext;
import
org.apache.hadoop.hdfs.server.federation.resolver.FederationNamenodeServiceState;
@@ -882,6 +883,14 @@ public class RouterRpcClient {
return newException;
}
+ if (ioe instanceof SnapshotException) {
+ String newMsg = processExceptionMsg(
+ ioe.getMessage(), loc.getDest(), loc.getSrc());
+ SnapshotException newException = new SnapshotException(newMsg);
+ newException.setStackTrace(ioe.getStackTrace());
+ return newException;
+ }
+
return ioe;
}
diff --git
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java
index 32f3e66..6facd7e 100644
---
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java
+++
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java
@@ -1007,12 +1007,12 @@ public class RouterRpcServer extends AbstractService
return clientProto.getLinkTarget(path);
}
- @Override // Client Protocol
+ @Override // ClientProtocol
public void allowSnapshot(String snapshotRoot) throws IOException {
clientProto.allowSnapshot(snapshotRoot);
}
- @Override // Client Protocol
+ @Override // ClientProtocol
public void disallowSnapshot(String snapshot) throws IOException {
clientProto.disallowSnapshot(snapshot);
}
@@ -1023,7 +1023,7 @@ public class RouterRpcServer extends AbstractService
clientProto.renameSnapshot(snapshotRoot, snapshotOldName, snapshotNewName);
}
- @Override // Client Protocol
+ @Override // ClientProtocol
public SnapshottableDirectoryStatus[] getSnapshottableDirListing()
throws IOException {
return clientProto.getSnapshottableDirListing();
@@ -1584,14 +1584,16 @@ public class RouterRpcServer extends AbstractService
* @param clazz Class of the values.
* @return Array with the outputs.
*/
- protected static <T> T[] merge(
+ static <T> T[] merge(
Map<FederationNamespaceInfo, T[]> map, Class<T> clazz) {
// Put all results into a set to avoid repeats
Set<T> ret = new LinkedHashSet<>();
for (T[] values : map.values()) {
- for (T val : values) {
- ret.add(val);
+ if (values != null) {
+ for (T val : values) {
+ ret.add(val);
+ }
}
}
@@ -1605,7 +1607,7 @@ public class RouterRpcServer extends AbstractService
* @param clazz Class of the values.
* @return Array with the values in set.
*/
- private static <T> T[] toArray(Collection<T> set, Class<T> clazz) {
+ static <T> T[] toArray(Collection<T> set, Class<T> clazz) {
@SuppressWarnings("unchecked")
T[] combinedData = (T[]) Array.newInstance(clazz, set.size());
combinedData = set.toArray(combinedData);
diff --git
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterSnapshot.java
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterSnapshot.java
new file mode 100644
index 0000000..7b08092
--- /dev/null
+++
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterSnapshot.java
@@ -0,0 +1,208 @@
+/**
+ * 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
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.router;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.hadoop.hdfs.protocol.ClientProtocol;
+import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport;
+import org.apache.hadoop.hdfs.protocol.SnapshotDiffReportListing;
+import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus;
+import
org.apache.hadoop.hdfs.server.federation.resolver.ActiveNamenodeResolver;
+import
org.apache.hadoop.hdfs.server.federation.resolver.FederationNamespaceInfo;
+import org.apache.hadoop.hdfs.server.federation.resolver.RemoteLocation;
+import org.apache.hadoop.hdfs.server.namenode.NameNode;
+import org.apache.hadoop.hdfs.server.namenode.NameNode.OperationCategory;
+
+/**
+ * Module that implements all the RPC calls related to snapshots in
+ * {@link ClientProtocol} in the {@link RouterRpcServer}.
+ */
+public class RouterSnapshot {
+
+ /** RPC server to receive client calls. */
+ private final RouterRpcServer rpcServer;
+ /** RPC clients to connect to the Namenodes. */
+ private final RouterRpcClient rpcClient;
+ /** Find generic locations. */
+ private final ActiveNamenodeResolver namenodeResolver;
+
+ public RouterSnapshot(RouterRpcServer server) {
+ this.rpcServer = server;
+ this.rpcClient = this.rpcServer.getRPCClient();
+ this.namenodeResolver = rpcServer.getNamenodeResolver();
+ }
+
+ public void allowSnapshot(String snapshotRoot) throws IOException {
+ rpcServer.checkOperation(OperationCategory.WRITE);
+
+ final List<RemoteLocation> locations =
+ rpcServer.getLocationsForPath(snapshotRoot, true, false);
+ RemoteMethod method = new RemoteMethod("allowSnapshot",
+ new Class<?>[] {String.class}, new RemoteParam());
+
+ if (rpcServer.isInvokeConcurrent(snapshotRoot)) {
+ rpcClient.invokeConcurrent(locations, method);
+ } else {
+ rpcClient.invokeSequential(locations, method);
+ }
+ }
+
+ public void disallowSnapshot(String snapshotRoot) throws IOException {
+ rpcServer.checkOperation(OperationCategory.WRITE);
+
+ final List<RemoteLocation> locations =
+ rpcServer.getLocationsForPath(snapshotRoot, true, false);
+ RemoteMethod method = new RemoteMethod("disallowSnapshot",
+ new Class<?>[] {String.class}, new RemoteParam());
+ if (rpcServer.isInvokeConcurrent(snapshotRoot)) {
+ rpcClient.invokeConcurrent(locations, method);
+ } else {
+ rpcClient.invokeSequential(locations, method);
+ }
+ }
+
+ public String createSnapshot(String snapshotRoot, String snapshotName)
+ throws IOException {
+ rpcServer.checkOperation(OperationCategory.WRITE);
+
+ final List<RemoteLocation> locations =
+ rpcServer.getLocationsForPath(snapshotRoot, true, false);
+ RemoteMethod method = new RemoteMethod("createSnapshot",
+ new Class<?>[] {String.class, String.class}, new RemoteParam(),
+ snapshotName);
+
+ String result = null;
+ if (rpcServer.isInvokeConcurrent(snapshotRoot)) {
+ Map<RemoteLocation, String> results = rpcClient.invokeConcurrent(
+ locations, method, String.class);
+ Entry<RemoteLocation, String> firstelement =
+ results.entrySet().iterator().next();
+ RemoteLocation loc = firstelement.getKey();
+ result = firstelement.getValue();
+ result = result.replaceFirst(loc.getDest(), loc.getSrc());
+ } else {
+ result = rpcClient.invokeSequential(
+ locations, method, String.class, null);
+ RemoteLocation loc = locations.get(0);
+ result = result.replaceFirst(loc.getDest(), loc.getSrc());
+ }
+ return result;
+ }
+
+ public void deleteSnapshot(String snapshotRoot, String snapshotName)
+ throws IOException {
+ rpcServer.checkOperation(OperationCategory.WRITE);
+
+ final List<RemoteLocation> locations =
+ rpcServer.getLocationsForPath(snapshotRoot, true, false);
+ RemoteMethod method = new RemoteMethod("deleteSnapshot",
+ new Class<?>[] {String.class, String.class},
+ new RemoteParam(), snapshotName);
+
+ if (rpcServer.isInvokeConcurrent(snapshotRoot)) {
+ rpcClient.invokeConcurrent(locations, method);
+ } else {
+ rpcClient.invokeSequential(locations, method);
+ }
+ }
+
+ public void renameSnapshot(String snapshotRoot, String oldSnapshotName,
+ String newSnapshot) throws IOException {
+ rpcServer.checkOperation(OperationCategory.WRITE);
+
+ final List<RemoteLocation> locations =
+ rpcServer.getLocationsForPath(snapshotRoot, true, false);
+ RemoteMethod method = new RemoteMethod("renameSnapshot",
+ new Class<?>[] {String.class, String.class, String.class},
+ new RemoteParam(), oldSnapshotName, newSnapshot);
+
+ if (rpcServer.isInvokeConcurrent(snapshotRoot)) {
+ rpcClient.invokeConcurrent(locations, method);
+ } else {
+ rpcClient.invokeSequential(locations, method);
+ }
+ }
+
+ public SnapshottableDirectoryStatus[] getSnapshottableDirListing()
+ throws IOException {
+ rpcServer.checkOperation(NameNode.OperationCategory.READ);
+
+ RemoteMethod method = new RemoteMethod("getSnapshottableDirListing");
+ Set<FederationNamespaceInfo> nss = namenodeResolver.getNamespaces();
+ Map<FederationNamespaceInfo, SnapshottableDirectoryStatus[]> ret =
+ rpcClient.invokeConcurrent(
+ nss, method, true, false, SnapshottableDirectoryStatus[].class);
+
+ return RouterRpcServer.merge(ret, SnapshottableDirectoryStatus.class);
+ }
+
+ public SnapshotDiffReport getSnapshotDiffReport(String snapshotRoot,
+ String earlierSnapshotName, String laterSnapshotName)
+ throws IOException {
+ rpcServer.checkOperation(NameNode.OperationCategory.READ);
+
+ final List<RemoteLocation> locations =
+ rpcServer.getLocationsForPath(snapshotRoot, true, false);
+ RemoteMethod remoteMethod = new RemoteMethod("getSnapshotDiffReport",
+ new Class<?>[] {String.class, String.class, String.class},
+ new RemoteParam(), earlierSnapshotName, laterSnapshotName);
+
+ if (rpcServer.isInvokeConcurrent(snapshotRoot)) {
+ Map<RemoteLocation, SnapshotDiffReport> ret = rpcClient.invokeConcurrent(
+ locations, remoteMethod, true, false, SnapshotDiffReport.class);
+ return ret.values().iterator().next();
+ } else {
+ return rpcClient.invokeSequential(
+ locations, remoteMethod, SnapshotDiffReport.class, null);
+ }
+ }
+
+ public SnapshotDiffReportListing getSnapshotDiffReportListing(
+ String snapshotRoot, String earlierSnapshotName, String
laterSnapshotName,
+ byte[] startPath, int index) throws IOException {
+ rpcServer.checkOperation(NameNode.OperationCategory.READ);
+
+ final List<RemoteLocation> locations =
+ rpcServer.getLocationsForPath(snapshotRoot, true, false);
+ Class<?>[] params = new Class<?>[] {
+ String.class, String.class, String.class,
+ byte[].class, int.class};
+ RemoteMethod remoteMethod = new RemoteMethod(
+ "getSnapshotDiffReportListing", params,
+ new RemoteParam(), earlierSnapshotName, laterSnapshotName,
+ startPath, index);
+
+ if (rpcServer.isInvokeConcurrent(snapshotRoot)) {
+ Map<RemoteLocation, SnapshotDiffReportListing> ret =
+ rpcClient.invokeConcurrent(locations, remoteMethod, false, false,
+ SnapshotDiffReportListing.class);
+ Collection<SnapshotDiffReportListing> listings = ret.values();
+ SnapshotDiffReportListing listing0 = listings.iterator().next();
+ return listing0;
+ } else {
+ return rpcClient.invokeSequential(
+ locations, remoteMethod, SnapshotDiffReportListing.class, null);
+ }
+ }
+}
\ No newline at end of file
diff --git
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java
index 2f7eb6e..e656e7a 100644
---
a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java
+++
b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java
@@ -86,6 +86,10 @@ import
org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
+import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport;
+import org.apache.hadoop.hdfs.protocol.SnapshotDiffReportListing;
+import org.apache.hadoop.hdfs.protocol.SnapshotException;
+import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus;
import org.apache.hadoop.hdfs.security.token.block.ExportedBlockKeys;
import org.apache.hadoop.hdfs.server.federation.MiniRouterDFSCluster;
import
org.apache.hadoop.hdfs.server.federation.MiniRouterDFSCluster.NamenodeContext;
@@ -94,6 +98,11 @@ import org.apache.hadoop.hdfs.server.federation.MockResolver;
import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder;
import org.apache.hadoop.hdfs.server.federation.metrics.NamenodeBeanMetrics;
import
org.apache.hadoop.hdfs.server.federation.resolver.FileSubclusterResolver;
+import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
+import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
+import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
+import org.apache.hadoop.hdfs.server.namenode.NameNode;
+import org.apache.hadoop.hdfs.server.namenode.NameNodeAdapter;
import org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations;
import
org.apache.hadoop.hdfs.server.protocol.BlocksWithLocations.BlockWithLocations;
import org.apache.hadoop.hdfs.server.protocol.DatanodeStorageReport;
@@ -105,6 +114,7 @@ import
org.apache.hadoop.io.erasurecode.ErasureCodeConstants;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.service.Service.STATE;
import org.apache.hadoop.test.GenericTestUtils;
+import org.apache.hadoop.test.LambdaTestUtils;
import org.codehaus.jettison.json.JSONObject;
import org.junit.AfterClass;
import org.junit.Before;
@@ -744,6 +754,126 @@ public class TestRouterRpc {
}
@Test
+ public void testAllowDisallowSnapshots() throws Exception {
+
+ // Create a directory via the router at the root level
+ String dirPath = "/testdir";
+ String filePath1 = "/sample";
+ FsPermission permission = new FsPermission("705");
+ routerProtocol.mkdirs(dirPath, permission, false);
+ createFile(routerFS, filePath1, 32);
+
+ // Check that initially doesn't allow snapshots
+ NamenodeContext nnContext = cluster.getNamenodes().get(0);
+ NameNode nn = nnContext.getNamenode();
+ FSNamesystem fsn = NameNodeAdapter.getNamesystem(nn);
+ FSDirectory fsdir = fsn.getFSDirectory();
+ INodeDirectory dirNode = fsdir.getINode4Write(dirPath).asDirectory();
+ assertFalse(dirNode.isSnapshottable());
+
+ // Allow snapshots and verify the folder allows them
+ routerProtocol.allowSnapshot("/testdir");
+ dirNode = fsdir.getINode4Write(dirPath).asDirectory();
+ assertTrue(dirNode.isSnapshottable());
+
+ // Disallow snapshot on dir and verify does not allow snapshots anymore
+ routerProtocol.disallowSnapshot("/testdir");
+ dirNode = fsdir.getINode4Write(dirPath).asDirectory();
+ assertFalse(dirNode.isSnapshottable());
+
+ // Cleanup
+ routerProtocol.delete(dirPath, true);
+ }
+
+ @Test
+ public void testManageSnapshot() throws Exception {
+
+ final String mountPoint = "/mntsnapshot";
+ final String snapshotFolder = mountPoint + "/folder";
+ LOG.info("Setup a mount point for snapshots: {}", mountPoint);
+ Router r = router.getRouter();
+ MockResolver resolver = (MockResolver) r.getSubclusterResolver();
+ String ns0 = cluster.getNameservices().get(0);
+ resolver.addLocation(mountPoint, ns0, "/");
+
+ FsPermission permission = new FsPermission("777");
+ routerProtocol.mkdirs(mountPoint, permission, false);
+ routerProtocol.mkdirs(snapshotFolder, permission, false);
+ for (int i = 1; i <= 9; i++) {
+ String folderPath = snapshotFolder + "/subfolder" + i;
+ routerProtocol.mkdirs(folderPath, permission, false);
+ }
+
+ LOG.info("Create the snapshot: {}", snapshotFolder);
+ routerProtocol.allowSnapshot(snapshotFolder);
+ String snapshotName = routerProtocol.createSnapshot(
+ snapshotFolder, "snap");
+ assertEquals(snapshotFolder + "/.snapshot/snap", snapshotName);
+ assertTrue(verifyFileExists(routerFS, snapshotFolder + "/.snapshot/snap"));
+
+ LOG.info("Rename the snapshot and check it changed");
+ routerProtocol.renameSnapshot(snapshotFolder, "snap", "newsnap");
+ assertFalse(
+ verifyFileExists(routerFS, snapshotFolder + "/.snapshot/snap"));
+ assertTrue(
+ verifyFileExists(routerFS, snapshotFolder + "/.snapshot/newsnap"));
+ LambdaTestUtils.intercept(SnapshotException.class,
+ "Cannot delete snapshot snap from path " + snapshotFolder + ":",
+ () -> routerFS.deleteSnapshot(new Path(snapshotFolder), "snap"));
+
+ LOG.info("Delete the snapshot and check it is not there");
+ routerProtocol.deleteSnapshot(snapshotFolder, "newsnap");
+ assertFalse(
+ verifyFileExists(routerFS, snapshotFolder + "/.snapshot/newsnap"));
+
+ // Cleanup
+ routerProtocol.delete(mountPoint, true);
+ }
+
+ @Test
+ public void testGetSnapshotListing() throws IOException {
+
+ // Create a directory via the router and allow snapshots
+ final String snapshotPath = "/testGetSnapshotListing";
+ final String childDir = snapshotPath + "/subdir";
+ FsPermission permission = new FsPermission("705");
+ routerProtocol.mkdirs(snapshotPath, permission, false);
+ routerProtocol.allowSnapshot(snapshotPath);
+
+ // Create two snapshots
+ final String snapshot1 = "snap1";
+ final String snapshot2 = "snap2";
+ routerProtocol.createSnapshot(snapshotPath, snapshot1);
+ routerProtocol.mkdirs(childDir, permission, false);
+ routerProtocol.createSnapshot(snapshotPath, snapshot2);
+
+ // Check for listing through the Router
+ SnapshottableDirectoryStatus[] dirList =
+ routerProtocol.getSnapshottableDirListing();
+ assertEquals(1, dirList.length);
+ SnapshottableDirectoryStatus snapshotDir0 = dirList[0];
+ assertEquals(snapshotPath, snapshotDir0.getFullPath().toString());
+
+ // Check for difference report in two snapshot
+ SnapshotDiffReport diffReport = routerProtocol.getSnapshotDiffReport(
+ snapshotPath, snapshot1, snapshot2);
+ assertEquals(2, diffReport.getDiffList().size());
+
+ // Check for difference in two snapshot
+ byte[] startPath = {};
+ SnapshotDiffReportListing diffReportListing =
+ routerProtocol.getSnapshotDiffReportListing(
+ snapshotPath, snapshot1, snapshot2, startPath, -1);
+ assertEquals(1, diffReportListing.getModifyList().size());
+ assertEquals(1, diffReportListing.getCreateList().size());
+
+ // Cleanup
+ routerProtocol.deleteSnapshot(snapshotPath, snapshot1);
+ routerProtocol.deleteSnapshot(snapshotPath, snapshot2);
+ routerProtocol.disallowSnapshot(snapshotPath);
+ }
+
+ @Test
public void testProxyGetBlockLocations() throws Exception {
// Fetch block locations via router
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]