HDFS-15817. Rename snapshots while marking them deleted. (#2677)
This commit is contained in:
parent
0b05dd8802
commit
2df2dfb9ed
@ -61,6 +61,10 @@ public static String generateDefaultSnapshotName() {
|
|||||||
return new SimpleDateFormat(DEFAULT_SNAPSHOT_NAME_PATTERN).format(new Date());
|
return new SimpleDateFormat(DEFAULT_SNAPSHOT_NAME_PATTERN).format(new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String generateDeletedSnapshotName(Snapshot s) {
|
||||||
|
return getSnapshotName(s) + "#" + s.getId();
|
||||||
|
}
|
||||||
|
|
||||||
public static String getSnapshotPath(String snapshottableDir,
|
public static String getSnapshotPath(String snapshottableDir,
|
||||||
String snapshotRelativePath) {
|
String snapshotRelativePath) {
|
||||||
final StringBuilder b = new StringBuilder(snapshottableDir);
|
final StringBuilder b = new StringBuilder(snapshottableDir);
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
import org.apache.hadoop.metrics2.util.MBeans;
|
import org.apache.hadoop.metrics2.util.MBeans;
|
||||||
|
|
||||||
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
|
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
|
||||||
|
import org.apache.hadoop.util.Time;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -533,6 +534,8 @@ public void deleteSnapshot(final INodesInPath iip, final String snapshotName,
|
|||||||
INodesInPath.append(iip, snapshot.getRoot(),
|
INodesInPath.append(iip, snapshot.getRoot(),
|
||||||
DFSUtil.string2Bytes(snapshotName)), xattrs,
|
DFSUtil.string2Bytes(snapshotName)), xattrs,
|
||||||
EnumSet.of(XAttrSetFlag.CREATE, XAttrSetFlag.REPLACE));
|
EnumSet.of(XAttrSetFlag.CREATE, XAttrSetFlag.REPLACE));
|
||||||
|
renameSnapshot(iip, srcRoot.getFullPathName(), snapshotName,
|
||||||
|
Snapshot.generateDeletedSnapshotName(snapshot), Time.now());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,18 +92,25 @@ public void testOrderedSnapshotDeletion() throws Exception {
|
|||||||
assertXAttrSet("s2", hdfs, null);
|
assertXAttrSet("s2", hdfs, null);
|
||||||
hdfs.deleteSnapshot(snapshottableDir, "s0");
|
hdfs.deleteSnapshot(snapshottableDir, "s0");
|
||||||
assertXAttrSet("s2", hdfs, null);
|
assertXAttrSet("s2", hdfs, null);
|
||||||
hdfs.deleteSnapshot(snapshottableDir, "s1");
|
hdfs.deleteSnapshot(snapshottableDir,
|
||||||
hdfs.deleteSnapshot(snapshottableDir, "s2");
|
getDeletedSnapshotName(hdfs, snapshottableDir, "s1"));
|
||||||
|
hdfs.deleteSnapshot(snapshottableDir,
|
||||||
|
getDeletedSnapshotName(hdfs, snapshottableDir, "s2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assertMarkedAsDeleted(Path snapshotRoot, MiniDFSCluster cluster)
|
static void assertMarkedAsDeleted(Path snapshotRoot, Path snapshottableDir,
|
||||||
throws IOException {
|
MiniDFSCluster cluster) throws IOException {
|
||||||
|
final String snapName =
|
||||||
|
getDeletedSnapshotName(cluster.getFileSystem(), snapshottableDir,
|
||||||
|
snapshotRoot.getName());
|
||||||
|
final Path snapPathNew =
|
||||||
|
SnapshotTestHelper.getSnapshotRoot(snapshottableDir, snapName);
|
||||||
// Check if the path exists
|
// Check if the path exists
|
||||||
Assert.assertNotNull(cluster.getFileSystem().getFileStatus(snapshotRoot));
|
Assert.assertNotNull(cluster.getFileSystem().getFileStatus(snapPathNew));
|
||||||
|
|
||||||
// Check xAttr for snapshotRoot
|
// Check xAttr for snapshotRoot
|
||||||
final INode inode = cluster.getNamesystem().getFSDirectory()
|
final INode inode = cluster.getNamesystem().getFSDirectory()
|
||||||
.getINode(snapshotRoot.toString());
|
.getINode(snapPathNew.toString());
|
||||||
final XAttrFeature f = inode.getXAttrFeature();
|
final XAttrFeature f = inode.getXAttrFeature();
|
||||||
final XAttr xAttr = f.getXAttr(XATTR_SNAPSHOT_DELETED);
|
final XAttr xAttr = f.getXAttr(XATTR_SNAPSHOT_DELETED);
|
||||||
Assert.assertNotNull(xAttr);
|
Assert.assertNotNull(xAttr);
|
||||||
@ -114,7 +121,7 @@ static void assertMarkedAsDeleted(Path snapshotRoot, MiniDFSCluster cluster)
|
|||||||
|
|
||||||
// Check inode
|
// Check inode
|
||||||
Assert.assertTrue(inode instanceof Snapshot.Root);
|
Assert.assertTrue(inode instanceof Snapshot.Root);
|
||||||
Assert.assertTrue(((Snapshot.Root)inode).isMarkedAsDeleted());
|
Assert.assertTrue(((Snapshot.Root) inode).isMarkedAsDeleted());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assertNotMarkedAsDeleted(Path snapshotRoot,
|
static void assertNotMarkedAsDeleted(Path snapshotRoot,
|
||||||
@ -139,12 +146,16 @@ static void assertNotMarkedAsDeleted(Path snapshotRoot,
|
|||||||
void assertXAttrSet(String snapshot,
|
void assertXAttrSet(String snapshot,
|
||||||
DistributedFileSystem hdfs, XAttr newXattr)
|
DistributedFileSystem hdfs, XAttr newXattr)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
hdfs.deleteSnapshot(snapshottableDir, snapshot);
|
String snapName = getDeletedSnapshotName(hdfs, snapshottableDir, snapshot);
|
||||||
|
hdfs.deleteSnapshot(snapshottableDir, snapName);
|
||||||
// Check xAttr for parent directory
|
// Check xAttr for parent directory
|
||||||
Path snapshotRoot = SnapshotTestHelper.getSnapshotRoot(snapshottableDir,
|
Path snapshotRoot =
|
||||||
snapshot);
|
SnapshotTestHelper.getSnapshotRoot(snapshottableDir, snapshot);
|
||||||
assertMarkedAsDeleted(snapshotRoot, cluster);
|
assertMarkedAsDeleted(snapshotRoot, snapshottableDir, cluster);
|
||||||
|
// Check xAttr for parent directory
|
||||||
|
snapName = getDeletedSnapshotName(hdfs, snapshottableDir, snapshot);
|
||||||
|
snapshotRoot =
|
||||||
|
SnapshotTestHelper.getSnapshotRoot(snapshottableDir, snapName);
|
||||||
// Make sure its not user visible
|
// Make sure its not user visible
|
||||||
if (cluster.getNameNode().getConf().getBoolean(DFSConfigKeys.
|
if (cluster.getNameNode().getConf().getBoolean(DFSConfigKeys.
|
||||||
DFS_NAMENODE_XATTRS_ENABLED_KEY,
|
DFS_NAMENODE_XATTRS_ENABLED_KEY,
|
||||||
@ -261,4 +272,11 @@ public void testSnapshotXAttrWithPreExistingXattrs() throws Exception {
|
|||||||
hdfs.createSnapshot(snapshottableDir, "s1");
|
hdfs.createSnapshot(snapshottableDir, "s1");
|
||||||
assertXAttrSet("s1", hdfs, newXAttr);
|
assertXAttrSet("s1", hdfs, newXAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getDeletedSnapshotName(DistributedFileSystem hdfs,
|
||||||
|
Path snapshottableDir, String snapshot) throws IOException {
|
||||||
|
return Arrays.stream(hdfs.getSnapshotListing(snapshottableDir))
|
||||||
|
.filter(p -> p.getFullPath().getName().startsWith(snapshot)).findFirst()
|
||||||
|
.get().getFullPath().getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
import static org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotManager.DFS_NAMENODE_SNAPSHOT_DELETION_ORDERED_GC_PERIOD_MS;
|
import static org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotManager.DFS_NAMENODE_SNAPSHOT_DELETION_ORDERED_GC_PERIOD_MS;
|
||||||
import static org.apache.hadoop.hdfs.server.namenode.snapshot.TestOrderedSnapshotDeletion.assertMarkedAsDeleted;
|
import static org.apache.hadoop.hdfs.server.namenode.snapshot.TestOrderedSnapshotDeletion.assertMarkedAsDeleted;
|
||||||
import static org.apache.hadoop.hdfs.server.namenode.snapshot.TestOrderedSnapshotDeletion.assertNotMarkedAsDeleted;
|
import static org.apache.hadoop.hdfs.server.namenode.snapshot.TestOrderedSnapshotDeletion.assertNotMarkedAsDeleted;
|
||||||
|
import static org.apache.hadoop.hdfs.server.namenode.snapshot.TestOrderedSnapshotDeletion.getDeletedSnapshotName;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@ -112,23 +113,32 @@ public void testSingleDir() throws Exception {
|
|||||||
hdfs.deleteSnapshot(snapshottableDir, "s2");
|
hdfs.deleteSnapshot(snapshottableDir, "s2");
|
||||||
assertNotMarkedAsDeleted(s0path, cluster);
|
assertNotMarkedAsDeleted(s0path, cluster);
|
||||||
assertNotMarkedAsDeleted(s1path, cluster);
|
assertNotMarkedAsDeleted(s1path, cluster);
|
||||||
assertMarkedAsDeleted(s2path, cluster);
|
assertMarkedAsDeleted(s2path, snapshottableDir, cluster);
|
||||||
|
final Path s2pathNew = new Path(s2path.getParent(),
|
||||||
|
getDeletedSnapshotName(hdfs, snapshottableDir, s2path.getName()));
|
||||||
|
Assert.assertFalse(exist(s2path, hdfs));
|
||||||
|
Assert.assertTrue(exist(s2pathNew, hdfs));
|
||||||
|
Assert.assertFalse(s2path.equals(s2pathNew));
|
||||||
|
|
||||||
hdfs.deleteSnapshot(snapshottableDir, "s1");
|
hdfs.deleteSnapshot(snapshottableDir, "s1");
|
||||||
assertNotMarkedAsDeleted(s0path, cluster);
|
assertNotMarkedAsDeleted(s0path, cluster);
|
||||||
assertMarkedAsDeleted(s1path, cluster);
|
assertMarkedAsDeleted(s1path, snapshottableDir, cluster);
|
||||||
assertMarkedAsDeleted(s2path, cluster);
|
assertMarkedAsDeleted(s2path, snapshottableDir, cluster);
|
||||||
|
final Path s1pathNew = new Path(s1path.getParent(),
|
||||||
|
getDeletedSnapshotName(hdfs, snapshottableDir, s1path.getName()));
|
||||||
|
Assert.assertFalse(exist(s1path, hdfs));
|
||||||
|
Assert.assertTrue(exist(s1pathNew, hdfs));
|
||||||
|
Assert.assertFalse(s1path.equals(s1pathNew));
|
||||||
// should not be gc'ed
|
// should not be gc'ed
|
||||||
Thread.sleep(10*GC_PERIOD);
|
Thread.sleep(10*GC_PERIOD);
|
||||||
assertNotMarkedAsDeleted(s0path, cluster);
|
assertNotMarkedAsDeleted(s0path, cluster);
|
||||||
assertMarkedAsDeleted(s1path, cluster);
|
assertMarkedAsDeleted(s1path, snapshottableDir, cluster);
|
||||||
assertMarkedAsDeleted(s2path, cluster);
|
assertMarkedAsDeleted(s2path, snapshottableDir, cluster);
|
||||||
|
|
||||||
hdfs.deleteSnapshot(snapshottableDir, "s0");
|
hdfs.deleteSnapshot(snapshottableDir, "s0");
|
||||||
Assert.assertFalse(exist(s0path, hdfs));
|
Assert.assertFalse(exist(s0path, hdfs));
|
||||||
|
|
||||||
waitForGc(Arrays.asList(s1path, s2path), hdfs);
|
waitForGc(Arrays.asList(s1pathNew, s2pathNew), hdfs);
|
||||||
// total no of edit log records created for delete snapshot will be equal
|
// total no of edit log records created for delete snapshot will be equal
|
||||||
// to sum of no of user deleted snapshots and no of snapshots gc'ed with
|
// to sum of no of user deleted snapshots and no of snapshots gc'ed with
|
||||||
// snapshotDeletion gc thread
|
// snapshotDeletion gc thread
|
||||||
|
Loading…
Reference in New Issue
Block a user