|
@@ -21,6 +21,7 @@ import java.io.IOException;
|
|
|
import java.io.PrintWriter;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
+import java.util.Iterator;
|
|
|
import java.util.List;
|
|
|
|
|
|
import org.apache.hadoop.HadoopIllegalArgumentException;
|
|
@@ -30,7 +31,12 @@ import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.INodeDirectoryWithQuota;
|
|
|
import org.apache.hadoop.util.Time;
|
|
|
|
|
|
-/** Directories where taking snapshots is allowed. */
|
|
|
+/**
|
|
|
+ * Directories where taking snapshots is allowed.
|
|
|
+ *
|
|
|
+ * Like other {@link INode} subclasses, this class is synchronized externally
|
|
|
+ * by the namesystem and FSDirectory locks.
|
|
|
+ */
|
|
|
@InterfaceAudience.Private
|
|
|
public class INodeDirectorySnapshottable extends INodeDirectoryWithQuota {
|
|
|
static public INodeDirectorySnapshottable newInstance(
|
|
@@ -51,43 +57,48 @@ public class INodeDirectorySnapshottable extends INodeDirectoryWithQuota {
|
|
|
INode inode, String src) throws IOException {
|
|
|
final INodeDirectory dir = INodeDirectory.valueOf(inode, src);
|
|
|
if (!dir.isSnapshottable()) {
|
|
|
- throw new SnapshotException(src + " is not a snapshottable directory.");
|
|
|
+ throw new SnapshotException(
|
|
|
+ "Directory is not a snapshottable directory: " + src);
|
|
|
}
|
|
|
return (INodeDirectorySnapshottable)dir;
|
|
|
}
|
|
|
|
|
|
- /** A list of snapshots of this directory. */
|
|
|
- private final List<INodeDirectoryWithSnapshot> snapshots
|
|
|
- = new ArrayList<INodeDirectoryWithSnapshot>();
|
|
|
+ /** Snapshots of this directory in ascending order of snapshot id. */
|
|
|
+ private final List<Snapshot> snapshots = new ArrayList<Snapshot>();
|
|
|
+
|
|
|
+ /** Number of snapshots allowed. */
|
|
|
+ private int snapshotQuota;
|
|
|
+
|
|
|
+ private INodeDirectorySnapshottable(long nsQuota, long dsQuota,
|
|
|
+ INodeDirectory dir, final int snapshotQuota) {
|
|
|
+ super(nsQuota, dsQuota, dir);
|
|
|
+ setSnapshotQuota(snapshotQuota);
|
|
|
+ }
|
|
|
+
|
|
|
+ int getNumSnapshots() {
|
|
|
+ return snapshots.size();
|
|
|
+ }
|
|
|
|
|
|
- public INode getSnapshotINode(byte[] name) {
|
|
|
+ /** @return the root directory of a snapshot. */
|
|
|
+ public INodeDirectory getSnapshotRoot(byte[] snapshotName) {
|
|
|
if (snapshots == null || snapshots.size() == 0) {
|
|
|
return null;
|
|
|
}
|
|
|
- int low = Collections.binarySearch(snapshots, name);
|
|
|
+ int low = Collections.binarySearch(snapshots, snapshotName);
|
|
|
if (low >= 0) {
|
|
|
- return snapshots.get(low);
|
|
|
+ return snapshots.get(low).getRoot();
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
-
|
|
|
- /** Number of snapshots is allowed. */
|
|
|
- private int snapshotQuota;
|
|
|
-
|
|
|
- private INodeDirectorySnapshottable(long nsQuota, long dsQuota,
|
|
|
- INodeDirectory dir, final int snapshotQuota) {
|
|
|
- super(nsQuota, dsQuota, dir);
|
|
|
- setSnapshotQuota(snapshotQuota);
|
|
|
- }
|
|
|
|
|
|
public int getSnapshotQuota() {
|
|
|
return snapshotQuota;
|
|
|
}
|
|
|
|
|
|
public void setSnapshotQuota(int snapshotQuota) {
|
|
|
- if (snapshotQuota <= 0) {
|
|
|
+ if (snapshotQuota < 0) {
|
|
|
throw new HadoopIllegalArgumentException(
|
|
|
- "Cannot set snapshot quota to " + snapshotQuota + " <= 0");
|
|
|
+ "Cannot set snapshot quota to " + snapshotQuota + " < 0");
|
|
|
}
|
|
|
this.snapshotQuota = snapshotQuota;
|
|
|
}
|
|
@@ -98,8 +109,7 @@ public class INodeDirectorySnapshottable extends INodeDirectoryWithQuota {
|
|
|
}
|
|
|
|
|
|
/** Add a snapshot root under this directory. */
|
|
|
- INodeDirectoryWithSnapshot addSnapshotRoot(final String name
|
|
|
- ) throws SnapshotException {
|
|
|
+ void addSnapshot(final Snapshot s) throws SnapshotException {
|
|
|
//check snapshot quota
|
|
|
if (snapshots.size() + 1 > snapshotQuota) {
|
|
|
throw new SnapshotException("Failed to add snapshot: there are already "
|
|
@@ -107,14 +117,12 @@ public class INodeDirectorySnapshottable extends INodeDirectoryWithQuota {
|
|
|
+ snapshotQuota);
|
|
|
}
|
|
|
|
|
|
- final INodeDirectoryWithSnapshot r = new INodeDirectoryWithSnapshot(name, this);
|
|
|
- snapshots.add(r);
|
|
|
+ snapshots.add(s);
|
|
|
|
|
|
//set modification time
|
|
|
final long timestamp = Time.now();
|
|
|
- r.setModificationTime(timestamp);
|
|
|
+ s.getRoot().setModificationTime(timestamp);
|
|
|
setModificationTime(timestamp);
|
|
|
- return r;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -126,6 +134,28 @@ public class INodeDirectorySnapshottable extends INodeDirectoryWithQuota {
|
|
|
out.print(snapshots.size() <= 1 ? " snapshot of " : " snapshots of ");
|
|
|
out.println(getLocalName());
|
|
|
|
|
|
- dumpTreeRecursively(out, prefix, snapshots);
|
|
|
+ dumpTreeRecursively(out, prefix, new Iterable<INodeDirectoryWithSnapshot>() {
|
|
|
+ @Override
|
|
|
+ public Iterator<INodeDirectoryWithSnapshot> iterator() {
|
|
|
+ return new Iterator<INodeDirectoryWithSnapshot>() {
|
|
|
+ final Iterator<Snapshot> i = snapshots.iterator();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasNext() {
|
|
|
+ return i.hasNext();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public INodeDirectoryWithSnapshot next() {
|
|
|
+ return i.next().getRoot();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void remove() {
|
|
|
+ throw new UnsupportedOperationException();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
}
|