HDFS-4514. Add CLI for supporting snapshot rename, diff report, and snapshottable directory listing. Contributed by Jing Zhao
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-2802@1449956 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d8ccf4e521
commit
59e968a114
|
@ -2241,6 +2241,19 @@ public abstract class FileSystem extends Configured implements Closeable {
|
||||||
+ " doesn't support createSnapshot");
|
+ " doesn't support createSnapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rename a snapshot
|
||||||
|
* @param path The directory path where the snapshot was taken
|
||||||
|
* @param snapshotOldName Old name of the snapshot
|
||||||
|
* @param snapshotNewName New name of the snapshot
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void renameSnapshot(Path path, String snapshotOldName,
|
||||||
|
String snapshotNewName) throws IOException {
|
||||||
|
throw new UnsupportedOperationException(getClass().getSimpleName()
|
||||||
|
+ " doesn't support renameSnapshot");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a snapshot of a directory
|
* Delete a snapshot of a directory
|
||||||
* @param path The directory that the to-be-deleted snapshot belongs to
|
* @param path The directory that the to-be-deleted snapshot belongs to
|
||||||
|
|
|
@ -25,6 +25,8 @@ import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.classification.InterfaceStability;
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.fs.PathIsNotDirectoryException;
|
import org.apache.hadoop.fs.PathIsNotDirectoryException;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Snapshot related operations
|
* Snapshot related operations
|
||||||
*/
|
*/
|
||||||
|
@ -34,10 +36,12 @@ import org.apache.hadoop.fs.PathIsNotDirectoryException;
|
||||||
class SnapshotCommands extends FsCommand {
|
class SnapshotCommands extends FsCommand {
|
||||||
private final static String CREATE_SNAPSHOT = "createSnapshot";
|
private final static String CREATE_SNAPSHOT = "createSnapshot";
|
||||||
private final static String DELETE_SNAPSHOT = "deleteSnapshot";
|
private final static String DELETE_SNAPSHOT = "deleteSnapshot";
|
||||||
|
private final static String RENAME_SNAPSHOT = "renameSnapshot";
|
||||||
|
|
||||||
public static void registerCommands(CommandFactory factory) {
|
public static void registerCommands(CommandFactory factory) {
|
||||||
factory.addClass(CreateSnapshot.class, "-" + CREATE_SNAPSHOT);
|
factory.addClass(CreateSnapshot.class, "-" + CREATE_SNAPSHOT);
|
||||||
factory.addClass(DeleteSnapshot.class, "-" + DELETE_SNAPSHOT);
|
factory.addClass(DeleteSnapshot.class, "-" + DELETE_SNAPSHOT);
|
||||||
|
factory.addClass(RenameSnapshot.class, "-" + RENAME_SNAPSHOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,10 +49,10 @@ class SnapshotCommands extends FsCommand {
|
||||||
*/
|
*/
|
||||||
public static class CreateSnapshot extends FsCommand {
|
public static class CreateSnapshot extends FsCommand {
|
||||||
public static final String NAME = CREATE_SNAPSHOT;
|
public static final String NAME = CREATE_SNAPSHOT;
|
||||||
public static final String USAGE = "<snapshotName> <snapshotRoot>";
|
public static final String USAGE = "<snapshotDir> <snapshotName>";
|
||||||
public static final String DESCRIPTION = "Create a snapshot on a directory";
|
public static final String DESCRIPTION = "Create a snapshot on a directory";
|
||||||
|
|
||||||
private static String snapshotName;
|
private String snapshotName;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void processPath(PathData item) throws IOException {
|
protected void processPath(PathData item) throws IOException {
|
||||||
|
@ -62,7 +66,7 @@ class SnapshotCommands extends FsCommand {
|
||||||
if (args.size() != 2) {
|
if (args.size() != 2) {
|
||||||
throw new IOException("args number not 2:" + args.size());
|
throw new IOException("args number not 2:" + args.size());
|
||||||
}
|
}
|
||||||
snapshotName = args.removeFirst();
|
snapshotName = args.removeLast();
|
||||||
// TODO: name length check
|
// TODO: name length check
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -85,11 +89,11 @@ class SnapshotCommands extends FsCommand {
|
||||||
*/
|
*/
|
||||||
public static class DeleteSnapshot extends FsCommand {
|
public static class DeleteSnapshot extends FsCommand {
|
||||||
public static final String NAME = DELETE_SNAPSHOT;
|
public static final String NAME = DELETE_SNAPSHOT;
|
||||||
public static final String USAGE = "<snapshotName> <snapshotDir>";
|
public static final String USAGE = "<snapshotDir> <snapshotName>";
|
||||||
public static final String DESCRIPTION =
|
public static final String DESCRIPTION =
|
||||||
"Delete a snapshot from a directory";
|
"Delete a snapshot from a directory";
|
||||||
|
|
||||||
private static String snapshotName;
|
private String snapshotName;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void processPath(PathData item) throws IOException {
|
protected void processPath(PathData item) throws IOException {
|
||||||
|
@ -103,7 +107,7 @@ class SnapshotCommands extends FsCommand {
|
||||||
if (args.size() != 2) {
|
if (args.size() != 2) {
|
||||||
throw new IOException("args number not 2: " + args.size());
|
throw new IOException("args number not 2: " + args.size());
|
||||||
}
|
}
|
||||||
snapshotName = args.removeFirst();
|
snapshotName = args.removeLast();
|
||||||
// TODO: name length check
|
// TODO: name length check
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -120,5 +124,49 @@ class SnapshotCommands extends FsCommand {
|
||||||
sroot.fs.deleteSnapshot(sroot.path, snapshotName);
|
sroot.fs.deleteSnapshot(sroot.path, snapshotName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rename a snapshot
|
||||||
|
*/
|
||||||
|
public static class RenameSnapshot extends FsCommand {
|
||||||
|
public static final String NAME = RENAME_SNAPSHOT;
|
||||||
|
public static final String USAGE = "<snapshotDir> <oldName> <newName>";
|
||||||
|
public static final String DESCRIPTION =
|
||||||
|
"Rename a snapshot from oldName to newName";
|
||||||
|
|
||||||
|
private String oldName;
|
||||||
|
private String newName;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processPath(PathData item) throws IOException {
|
||||||
|
if (!item.stat.isDirectory()) {
|
||||||
|
throw new PathIsNotDirectoryException(item.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processOptions(LinkedList<String> args) throws IOException {
|
||||||
|
if (args.size() != 3) {
|
||||||
|
throw new IOException("args number not 3: " + args.size());
|
||||||
|
}
|
||||||
|
newName = args.removeLast();
|
||||||
|
oldName = args.removeLast();
|
||||||
|
|
||||||
|
// TODO: new name length check
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processArguments(LinkedList<PathData> items)
|
||||||
|
throws IOException {
|
||||||
|
super.processArguments(items);
|
||||||
|
if (exitCode != 0) { // check for error collecting paths
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Preconditions.checkArgument(items.size() == 1);
|
||||||
|
PathData sroot = items.getFirst();
|
||||||
|
sroot.fs.renameSnapshot(sroot.path, oldName, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,3 +173,6 @@ Branch-2802 Snapshot (Unreleased)
|
||||||
|
|
||||||
HDFS-4520. Support listing snapshots under a snapshottable directory using ls.
|
HDFS-4520. Support listing snapshots under a snapshottable directory using ls.
|
||||||
(Jing Zhao via szetszwo)
|
(Jing Zhao via szetszwo)
|
||||||
|
|
||||||
|
HDFS-4514. Add CLI for supporting snapshot rename, diff report, and
|
||||||
|
snapshottable directory listing. (Jing Zhao via szetszwo)
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.apache.hadoop.fs.PathFilter;
|
||||||
import org.apache.hadoop.fs.RemoteIterator;
|
import org.apache.hadoop.fs.RemoteIterator;
|
||||||
import org.apache.hadoop.fs.VolumeId;
|
import org.apache.hadoop.fs.VolumeId;
|
||||||
import org.apache.hadoop.fs.permission.FsPermission;
|
import org.apache.hadoop.fs.permission.FsPermission;
|
||||||
|
import org.apache.hadoop.hdfs.client.HdfsAdmin;
|
||||||
import org.apache.hadoop.hdfs.client.HdfsDataInputStream;
|
import org.apache.hadoop.hdfs.client.HdfsDataInputStream;
|
||||||
import org.apache.hadoop.hdfs.client.HdfsDataOutputStream;
|
import org.apache.hadoop.hdfs.client.HdfsDataOutputStream;
|
||||||
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
||||||
|
@ -906,21 +907,12 @@ public class DistributedFileSystem extends FileSystem {
|
||||||
return setSafeMode(SafeModeAction.SAFEMODE_GET, true);
|
return setSafeMode(SafeModeAction.SAFEMODE_GET, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @see HdfsAdmin#allowSnapshot(String) */
|
||||||
* Allow snapshot on a directory.
|
|
||||||
*
|
|
||||||
* @param path the directory to be taken snapshots
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void allowSnapshot(String path) throws IOException {
|
public void allowSnapshot(String path) throws IOException {
|
||||||
dfs.allowSnapshot(path);
|
dfs.allowSnapshot(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @see HdfsAdmin#disallowSnapshot(String) */
|
||||||
* Disallow snapshot on a directory.
|
|
||||||
* @param path the snapshottable directory.
|
|
||||||
* @throws IOException on error
|
|
||||||
*/
|
|
||||||
public void disallowSnapshot(String path) throws IOException {
|
public void disallowSnapshot(String path) throws IOException {
|
||||||
dfs.disallowSnapshot(path);
|
dfs.disallowSnapshot(path);
|
||||||
}
|
}
|
||||||
|
@ -931,13 +923,7 @@ public class DistributedFileSystem extends FileSystem {
|
||||||
dfs.createSnapshot(getPathName(path), snapshotName);
|
dfs.createSnapshot(getPathName(path), snapshotName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Rename a snapshot
|
|
||||||
* @param path The directory path where the snapshot was taken
|
|
||||||
* @param snapshotOldName Old name of the snapshot
|
|
||||||
* @param snapshotNewName New name of the snapshot
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void renameSnapshot(Path path, String snapshotOldName,
|
public void renameSnapshot(Path path, String snapshotOldName,
|
||||||
String snapshotNewName) throws IOException {
|
String snapshotNewName) throws IOException {
|
||||||
dfs.renameSnapshot(getPathName(path), snapshotOldName, snapshotNewName);
|
dfs.renameSnapshot(getPathName(path), snapshotOldName, snapshotNewName);
|
||||||
|
|
|
@ -105,4 +105,20 @@ public class HdfsAdmin {
|
||||||
public void clearSpaceQuota(Path src) throws IOException {
|
public void clearSpaceQuota(Path src) throws IOException {
|
||||||
dfs.setQuota(src, HdfsConstants.QUOTA_DONT_SET, HdfsConstants.QUOTA_RESET);
|
dfs.setQuota(src, HdfsConstants.QUOTA_DONT_SET, HdfsConstants.QUOTA_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow snapshot on a directory.
|
||||||
|
* @param the path of the directory where snapshots will be taken
|
||||||
|
*/
|
||||||
|
public void allowSnapshot(String path) throws IOException {
|
||||||
|
dfs.allowSnapshot(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disallow snapshot on a directory.
|
||||||
|
* @param path of the snapshottable directory.
|
||||||
|
*/
|
||||||
|
public void disallowSnapshot(String path) throws IOException {
|
||||||
|
dfs.disallowSnapshot(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,9 +106,9 @@ public class SnapshotDiffReport {
|
||||||
public String getRelativePathString() {
|
public String getRelativePathString() {
|
||||||
String path = DFSUtil.bytes2String(relativePath);
|
String path = DFSUtil.bytes2String(relativePath);
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
return ".";
|
return Path.CUR_DIR;
|
||||||
} else {
|
} else {
|
||||||
return "." + Path.SEPARATOR + path;
|
return Path.CUR_DIR + Path.SEPARATOR + path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ public class SnapshotDiffReport {
|
||||||
"current directory" : "snapshot " + fromSnapshot;
|
"current directory" : "snapshot " + fromSnapshot;
|
||||||
String to = toSnapshot == null || toSnapshot.isEmpty() ? "current directory"
|
String to = toSnapshot == null || toSnapshot.isEmpty() ? "current directory"
|
||||||
: "snapshot " + toSnapshot;
|
: "snapshot " + toSnapshot;
|
||||||
str.append("Diffence between snapshot " + from + " and " + to
|
str.append("Difference between " + from + " and " + to
|
||||||
+ " under directory " + snapshotRoot + ":" + LINE_SEPARATOR);
|
+ " under directory " + snapshotRoot + ":" + LINE_SEPARATOR);
|
||||||
for (DiffReportEntry entry : diffList) {
|
for (DiffReportEntry entry : diffList) {
|
||||||
str.append(entry.toString() + LINE_SEPARATOR);
|
str.append(entry.toString() + LINE_SEPARATOR);
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hdfs.protocol;
|
package org.apache.hadoop.hdfs.protocol;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.fs.permission.FsPermission;
|
import org.apache.hadoop.fs.permission.FsPermission;
|
||||||
import org.apache.hadoop.hdfs.DFSUtil;
|
import org.apache.hadoop.hdfs.DFSUtil;
|
||||||
|
@ -85,4 +89,59 @@ public class SnapshottableDirectoryStatus {
|
||||||
return parentFullPathStr == null ? new Path(dirStatus.getLocalName())
|
return parentFullPathStr == null ? new Path(dirStatus.getLocalName())
|
||||||
: new Path(parentFullPathStr, dirStatus.getLocalName());
|
: new Path(parentFullPathStr, dirStatus.getLocalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print a list of {@link SnapshottableDirectoryStatus} out to a given stream.
|
||||||
|
* @param stats The list of {@link SnapshottableDirectoryStatus}
|
||||||
|
* @param out The given stream for printing.
|
||||||
|
*/
|
||||||
|
public static void print(SnapshottableDirectoryStatus[] stats,
|
||||||
|
PrintStream out) {
|
||||||
|
if (stats == null || stats.length == 0) {
|
||||||
|
out.println();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int maxRepl = 0, maxLen = 0, maxOwner = 0, maxGroup = 0;
|
||||||
|
int maxSnapshotNum = 0, maxSnapshotQuota = 0;
|
||||||
|
for (SnapshottableDirectoryStatus status : stats) {
|
||||||
|
maxRepl = maxLength(maxRepl, status.dirStatus.getReplication());
|
||||||
|
maxLen = maxLength(maxLen, status.dirStatus.getLen());
|
||||||
|
maxOwner = maxLength(maxOwner, status.dirStatus.getOwner());
|
||||||
|
maxGroup = maxLength(maxGroup, status.dirStatus.getGroup());
|
||||||
|
maxSnapshotNum = maxLength(maxSnapshotNum, status.snapshotNumber);
|
||||||
|
maxSnapshotQuota = maxLength(maxSnapshotQuota, status.snapshotQuota);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder fmt = new StringBuilder();
|
||||||
|
fmt.append("%s%s "); // permission string
|
||||||
|
fmt.append("%" + maxRepl + "s ");
|
||||||
|
fmt.append((maxOwner > 0) ? "%-" + maxOwner + "s " : "%s");
|
||||||
|
fmt.append((maxGroup > 0) ? "%-" + maxGroup + "s " : "%s");
|
||||||
|
fmt.append("%" + maxLen + "s ");
|
||||||
|
fmt.append("%s "); // mod time
|
||||||
|
fmt.append("%" + maxSnapshotNum + "s ");
|
||||||
|
fmt.append("%" + maxSnapshotQuota + "s ");
|
||||||
|
fmt.append("%s"); // path
|
||||||
|
|
||||||
|
String lineFormat = fmt.toString();
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
|
||||||
|
for (SnapshottableDirectoryStatus status : stats) {
|
||||||
|
String line = String.format(lineFormat, "d",
|
||||||
|
status.dirStatus.getPermission(),
|
||||||
|
status.dirStatus.getReplication(),
|
||||||
|
status.dirStatus.getOwner(),
|
||||||
|
status.dirStatus.getGroup(),
|
||||||
|
String.valueOf(status.dirStatus.getLen()),
|
||||||
|
dateFormat.format(new Date(status.dirStatus.getModificationTime())),
|
||||||
|
status.snapshotNumber, status.snapshotQuota,
|
||||||
|
status.getFullPath().toString()
|
||||||
|
);
|
||||||
|
out.println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int maxLength(int n, Object value) {
|
||||||
|
return Math.max(n, String.valueOf(value).length());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,7 +408,7 @@ public class DFSAdmin extends FsShell {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow snapshot on a directory.
|
* Allow snapshot on a directory.
|
||||||
* Usage: java DFSAdmin -allowSnapshot <snapshotRoot>
|
* Usage: java DFSAdmin -allowSnapshot snapshotDir
|
||||||
* @param argv List of of command line parameters.
|
* @param argv List of of command line parameters.
|
||||||
* @exception IOException
|
* @exception IOException
|
||||||
*/
|
*/
|
||||||
|
@ -420,7 +420,7 @@ public class DFSAdmin extends FsShell {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow snapshot on a directory.
|
* Allow snapshot on a directory.
|
||||||
* Usage: java DFSAdmin -disallowSnapshot <snapshotRoot>
|
* Usage: java DFSAdmin -disallowSnapshot snapshotDir
|
||||||
* @param argv List of of command line parameters.
|
* @param argv List of of command line parameters.
|
||||||
* @exception IOException
|
* @exception IOException
|
||||||
*/
|
*/
|
||||||
|
@ -571,6 +571,8 @@ public class DFSAdmin extends FsShell {
|
||||||
"\t[-deleteBlockPool datanodehost:port blockpoolId [force]]\n"+
|
"\t[-deleteBlockPool datanodehost:port blockpoolId [force]]\n"+
|
||||||
"\t[-setBalancerBandwidth <bandwidth>]\n" +
|
"\t[-setBalancerBandwidth <bandwidth>]\n" +
|
||||||
"\t[-fetchImage <local directory>]\n" +
|
"\t[-fetchImage <local directory>]\n" +
|
||||||
|
"\t[-allowSnapshot <snapshotDir>]\n" +
|
||||||
|
"\t[-disallowSnapshot <snapshotDir>]\n" +
|
||||||
"\t[-help [cmd]]\n";
|
"\t[-help [cmd]]\n";
|
||||||
|
|
||||||
String report ="-report: \tReports basic filesystem information and statistics.\n";
|
String report ="-report: \tReports basic filesystem information and statistics.\n";
|
||||||
|
@ -661,6 +663,12 @@ public class DFSAdmin extends FsShell {
|
||||||
"\tDownloads the most recent fsimage from the Name Node and saves it in" +
|
"\tDownloads the most recent fsimage from the Name Node and saves it in" +
|
||||||
"\tthe specified local directory.\n";
|
"\tthe specified local directory.\n";
|
||||||
|
|
||||||
|
String allowSnapshot = "-allowSnapshot <snapshotDir>:\n" +
|
||||||
|
"\tAllow snapshots to be taken on a directory.\n";
|
||||||
|
|
||||||
|
String disallowSnapshot = "-disallowSnapshot <snapshotDir>:\n" +
|
||||||
|
"\tDo not allow snapshots to be taken on a directory any more.\n";
|
||||||
|
|
||||||
String help = "-help [cmd]: \tDisplays help for the given command or all commands if none\n" +
|
String help = "-help [cmd]: \tDisplays help for the given command or all commands if none\n" +
|
||||||
"\t\tis specified.\n";
|
"\t\tis specified.\n";
|
||||||
|
|
||||||
|
@ -704,6 +712,10 @@ public class DFSAdmin extends FsShell {
|
||||||
System.out.println(setBalancerBandwidth);
|
System.out.println(setBalancerBandwidth);
|
||||||
} else if ("fetchImage".equals(cmd)) {
|
} else if ("fetchImage".equals(cmd)) {
|
||||||
System.out.println(fetchImage);
|
System.out.println(fetchImage);
|
||||||
|
} else if ("allowSnapshot".equalsIgnoreCase(cmd)) {
|
||||||
|
System.out.println(allowSnapshot);
|
||||||
|
} else if ("disallowSnapshot".equalsIgnoreCase(cmd)) {
|
||||||
|
System.out.println(disallowSnapshot);
|
||||||
} else if ("help".equals(cmd)) {
|
} else if ("help".equals(cmd)) {
|
||||||
System.out.println(help);
|
System.out.println(help);
|
||||||
} else {
|
} else {
|
||||||
|
@ -728,6 +740,8 @@ public class DFSAdmin extends FsShell {
|
||||||
System.out.println(deleteBlockPool);
|
System.out.println(deleteBlockPool);
|
||||||
System.out.println(setBalancerBandwidth);
|
System.out.println(setBalancerBandwidth);
|
||||||
System.out.println(fetchImage);
|
System.out.println(fetchImage);
|
||||||
|
System.out.println(allowSnapshot);
|
||||||
|
System.out.println(disallowSnapshot);
|
||||||
System.out.println(help);
|
System.out.println(help);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
ToolRunner.printGenericCommandUsage(System.out);
|
ToolRunner.printGenericCommandUsage(System.out);
|
||||||
|
@ -906,10 +920,10 @@ public class DFSAdmin extends FsShell {
|
||||||
+ " [-safemode enter | leave | get | wait]");
|
+ " [-safemode enter | leave | get | wait]");
|
||||||
} else if ("-allowSnapshot".equalsIgnoreCase(cmd)) {
|
} else if ("-allowSnapshot".equalsIgnoreCase(cmd)) {
|
||||||
System.err.println("Usage: java DFSAdmin"
|
System.err.println("Usage: java DFSAdmin"
|
||||||
+ " [-allowSnapshot <snapshotRoot>]");
|
+ " [-allowSnapshot <snapshotDir>]");
|
||||||
} else if ("-disallowsnapshot".equalsIgnoreCase(cmd)) {
|
} else if ("-disallowSnapshot".equalsIgnoreCase(cmd)) {
|
||||||
System.err.println("Usage: java DFSAdmin"
|
System.err.println("Usage: java DFSAdmin"
|
||||||
+ " [-disallowSnapshot <snapshotRoot>]");
|
+ " [-disallowSnapshot <snapshotDir>]");
|
||||||
} else if ("-saveNamespace".equals(cmd)) {
|
} else if ("-saveNamespace".equals(cmd)) {
|
||||||
System.err.println("Usage: java DFSAdmin"
|
System.err.println("Usage: java DFSAdmin"
|
||||||
+ " [-saveNamespace]");
|
+ " [-saveNamespace]");
|
||||||
|
@ -969,8 +983,8 @@ public class DFSAdmin extends FsShell {
|
||||||
System.err.println("Note: Administrative commands can only be run as the HDFS superuser.");
|
System.err.println("Note: Administrative commands can only be run as the HDFS superuser.");
|
||||||
System.err.println(" [-report]");
|
System.err.println(" [-report]");
|
||||||
System.err.println(" [-safemode enter | leave | get | wait]");
|
System.err.println(" [-safemode enter | leave | get | wait]");
|
||||||
System.err.println(" [-allowSnapshot <snapshotRoot>]");
|
System.err.println(" [-allowSnapshot <snapshotDir>]");
|
||||||
System.err.println(" [-disallowSnapshot <snapshotRoot>]");
|
System.err.println(" [-disallowSnapshot <snapshotDir>]");
|
||||||
System.err.println(" [-saveNamespace]");
|
System.err.println(" [-saveNamespace]");
|
||||||
System.err.println(" [-rollEdits]");
|
System.err.println(" [-rollEdits]");
|
||||||
System.err.println(" [-restoreFailedStorage true|false|check]");
|
System.err.println(" [-restoreFailedStorage true|false|check]");
|
||||||
|
@ -1021,7 +1035,7 @@ public class DFSAdmin extends FsShell {
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
} else if ("-allowSnapshot".equalsIgnoreCase(cmd)) {
|
} else if ("-allowSnapshot".equalsIgnoreCase(cmd)) {
|
||||||
if (argv.length != 3) {
|
if (argv.length != 2) {
|
||||||
printUsage(cmd);
|
printUsage(cmd);
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.tools.snapshot;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
|
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
||||||
|
import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tool used to list all snapshottable directories that are owned by the
|
||||||
|
* current user. The tool returns all the snapshottable directories if the user
|
||||||
|
* is a super user.
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
public class LsSnapshottableDir {
|
||||||
|
public static void main(String[] argv) throws IOException {
|
||||||
|
String description = "LsSnapshottableDir: \n" +
|
||||||
|
"\tGet the list of snapshottable directories that are owned by the current user.\n" +
|
||||||
|
"\tReturn all the snapshottable directories if the current user is a super user.\n";
|
||||||
|
|
||||||
|
if(argv.length != 0) {
|
||||||
|
System.err.println("Usage: \n" + description);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
FileSystem fs = FileSystem.get(conf);
|
||||||
|
if (! (fs instanceof DistributedFileSystem)) {
|
||||||
|
System.err.println(
|
||||||
|
"LsSnapshottableDir can only be used in DistributedFileSystem");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
DistributedFileSystem dfs = (DistributedFileSystem) fs;
|
||||||
|
|
||||||
|
SnapshottableDirectoryStatus[] stats = dfs.getSnapshottableDirListing();
|
||||||
|
SnapshottableDirectoryStatus.print(stats, System.out);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.tools.snapshot;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
||||||
|
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
||||||
|
import org.apache.hadoop.hdfs.protocol.SnapshotDiffReport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tool used to get the difference report between two snapshots, or between
|
||||||
|
* a snapshot and the current status of a directory.
|
||||||
|
* <pre>
|
||||||
|
* Usage: SnapshotDiff snapshotDir from to
|
||||||
|
* For from/to, users can use "." to present the current status, and use
|
||||||
|
* ".snapshot/snapshot_name" to present a snapshot, where ".snapshot/" can be
|
||||||
|
* omitted.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
public class SnapshotDiff {
|
||||||
|
private static String getSnapshotName(String name) {
|
||||||
|
if (Path.CUR_DIR.equals(name)) { // current directory
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (name.startsWith(HdfsConstants.DOT_SNAPSHOT_DIR + Path.SEPARATOR)
|
||||||
|
|| name.startsWith(Path.SEPARATOR + HdfsConstants.DOT_SNAPSHOT_DIR
|
||||||
|
+ Path.SEPARATOR)) {
|
||||||
|
// get the snapshot name
|
||||||
|
int i = name.indexOf(HdfsConstants.DOT_SNAPSHOT_DIR);
|
||||||
|
return name.substring(i + HdfsConstants.DOT_SNAPSHOT_DIR.length() + 1);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] argv) throws IOException {
|
||||||
|
String description = "SnapshotDiff <snapshotDir> <from> <to>:\n" +
|
||||||
|
"\tGet the difference between two snapshots, \n" +
|
||||||
|
"\tor between a snapshot and the current tree of a directory.\n" +
|
||||||
|
"\tFor <from>/<to>, users can use \".\" to present the current status,\n" +
|
||||||
|
"\tand use \".snapshot/snapshot_name\" to present a snapshot,\n" +
|
||||||
|
"\twhere \".snapshot/\" can be omitted\n";
|
||||||
|
|
||||||
|
if(argv.length != 3) {
|
||||||
|
System.err.println("Usage: \n" + description);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
FileSystem fs = FileSystem.get(conf);
|
||||||
|
if (! (fs instanceof DistributedFileSystem)) {
|
||||||
|
System.err.println(
|
||||||
|
"SnapshotDiff can only be used in DistributedFileSystem");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
DistributedFileSystem dfs = (DistributedFileSystem) fs;
|
||||||
|
|
||||||
|
Path snapshotRoot = new Path(argv[0]);
|
||||||
|
String fromSnapshot = getSnapshotName(argv[1]);
|
||||||
|
String toSnapshot = getSnapshotName(argv[2]);
|
||||||
|
SnapshotDiffReport diffReport = dfs.getSnapshotDiffReport(snapshotRoot,
|
||||||
|
fromSnapshot, toSnapshot);
|
||||||
|
System.out.println(diffReport.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue