Skip to content

Commit 15a76e8

Browse files
authored
HDFS-15524. Add edit log entry for Snapshot deletion GC thread snapshot deletion. (#2219)
1 parent aee3b97 commit 15a76e8

File tree

3 files changed

+57
-8
lines changed

3 files changed

+57
-8
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirSnapshotOp.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,15 @@ static INode.BlocksMapUpdateInfo deleteSnapshot(
269269
// time of snapshot deletion
270270
final long now = Time.now();
271271
final INode.BlocksMapUpdateInfo collectedBlocks = deleteSnapshot(
272-
fsd, snapshotManager, iip, snapshotName, now);
273-
fsd.getEditLog().logDeleteSnapshot(snapshotRoot, snapshotName,
274-
logRetryCache, now);
272+
fsd, snapshotManager, iip, snapshotName, now, snapshotRoot,
273+
logRetryCache);
275274
return collectedBlocks;
276275
}
277276

278277
static INode.BlocksMapUpdateInfo deleteSnapshot(
279278
FSDirectory fsd, SnapshotManager snapshotManager, INodesInPath iip,
280-
String snapshotName, long now) throws IOException {
279+
String snapshotName, long now, String snapshotRoot, boolean logRetryCache)
280+
throws IOException {
281281
INode.BlocksMapUpdateInfo collectedBlocks = new INode.BlocksMapUpdateInfo();
282282
ChunkedArrayList<INode> removedINodes = new ChunkedArrayList<>();
283283
INode.ReclaimContext context = new INode.ReclaimContext(
@@ -293,6 +293,8 @@ static INode.BlocksMapUpdateInfo deleteSnapshot(
293293
fsd.writeUnlock();
294294
}
295295
removedINodes.clear();
296+
fsd.getEditLog().logDeleteSnapshot(snapshotRoot, snapshotName,
297+
logRetryCache, now);
296298
return collectedBlocks;
297299
}
298300

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7235,7 +7235,7 @@ public void gcDeletedSnapshot(String snapshotRoot, String snapshotName)
72357235
final INodesInPath iip = dir.resolvePath(null, snapshotRoot, DirOp.WRITE);
72367236
snapshotManager.assertMarkedAsDeleted(iip, snapshotName);
72377237
blocksToBeDeleted = FSDirSnapshotOp.deleteSnapshot(
7238-
dir, snapshotManager, iip, snapshotName, now);
7238+
dir, snapshotManager, iip, snapshotName, now, snapshotRoot, false);
72397239
} finally {
72407240
writeUnlock(operationName, getLockReportInfoSupplier(rootPath));
72417241
}

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/snapshot/TestOrderedSnapshotDeletionGc.java

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,44 @@
2121
import org.apache.hadoop.fs.Path;
2222
import org.apache.hadoop.hdfs.DistributedFileSystem;
2323
import org.apache.hadoop.hdfs.MiniDFSCluster;
24+
import org.apache.hadoop.hdfs.server.common.Storage;
25+
import org.apache.hadoop.hdfs.server.namenode.FSImage;
26+
import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil;
27+
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
28+
import org.apache.hadoop.hdfs.server.namenode.NNStorage;
29+
import org.apache.hadoop.hdfs.server.namenode.FSEditLogOpCodes;
30+
import org.apache.hadoop.hdfs.util.Holder;
2431
import org.apache.hadoop.test.GenericTestUtils;
2532
import org.junit.After;
2633
import org.junit.Assert;
2734
import org.junit.Before;
2835
import org.junit.Test;
2936
import org.slf4j.event.Level;
3037

38+
import java.io.File;
3139
import java.io.FileNotFoundException;
3240
import java.io.IOException;
33-
import java.util.ArrayList;
3441
import java.util.Arrays;
3542
import java.util.Collections;
3643
import java.util.Iterator;
3744
import java.util.List;
3845
import java.util.Random;
46+
import java.util.EnumMap;
47+
import java.util.ArrayList;
3948

4049
import static org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotManager.DFS_NAMENODE_SNAPSHOT_DELETION_ORDERED;
4150
import static org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotManager.DFS_NAMENODE_SNAPSHOT_DELETION_ORDERED_GC_PERIOD_MS;
4251
import static org.apache.hadoop.hdfs.server.namenode.snapshot.TestOrderedSnapshotDeletion.assertMarkedAsDeleted;
4352
import static org.apache.hadoop.hdfs.server.namenode.snapshot.TestOrderedSnapshotDeletion.assertNotMarkedAsDeleted;
53+
import static org.junit.Assert.assertEquals;
54+
import static org.junit.Assert.assertTrue;
4455

4556
/**
4657
* Test {@link SnapshotDeletionGc}.
4758
*/
4859
public class TestOrderedSnapshotDeletionGc {
4960
private static final int GC_PERIOD = 10;
50-
61+
private static final int NUM_DATANODES = 0;
5162
private MiniDFSCluster cluster;
5263

5364
@Before
@@ -56,7 +67,8 @@ public void setUp() throws Exception {
5667
conf.setBoolean(DFS_NAMENODE_SNAPSHOT_DELETION_ORDERED, true);
5768
conf.setInt(DFS_NAMENODE_SNAPSHOT_DELETION_ORDERED_GC_PERIOD_MS, GC_PERIOD);
5869

59-
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0).build();
70+
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATANODES)
71+
.build();
6072
cluster.waitActive();
6173

6274
GenericTestUtils.setLogLevel(SnapshotDeletionGc.LOG, Level.TRACE);
@@ -117,6 +129,38 @@ public void testSingleDir() throws Exception {
117129
Assert.assertFalse(exist(s0path, hdfs));
118130

119131
waitForGc(Arrays.asList(s1path, s2path), hdfs);
132+
// total no of edit log records created for delete snapshot will be equal
133+
// to sum of no of user deleted snapshots and no of snapshots gc'ed with
134+
// snapshotDeletion gc thread
135+
doEditLogValidation(cluster, 5);
136+
}
137+
138+
static void doEditLogValidation(MiniDFSCluster cluster,
139+
int editLogOpCount) throws Exception {
140+
final FSNamesystem namesystem = cluster.getNamesystem();
141+
Configuration conf = cluster.getNameNode().getConf();
142+
FSImage fsimage = namesystem.getFSImage();
143+
Storage.StorageDirectory sd = fsimage.getStorage().
144+
dirIterator(NNStorage.NameNodeDirType.EDITS).next();
145+
cluster.shutdown();
146+
147+
File editFile = FSImageTestUtil.findLatestEditsLog(sd).getFile();
148+
assertTrue("Should exist: " + editFile, editFile.exists());
149+
EnumMap<FSEditLogOpCodes, Holder<Integer>> counts;
150+
counts = FSImageTestUtil.countEditLogOpTypes(editFile);
151+
if (editLogOpCount > 0) {
152+
assertEquals(editLogOpCount, (int) counts.get(FSEditLogOpCodes.
153+
OP_DELETE_SNAPSHOT).held);
154+
}
155+
// make sure the gc thread doesn't start for a long time after the restart
156+
conf.setInt(DFS_NAMENODE_SNAPSHOT_DELETION_ORDERED_GC_PERIOD_MS,
157+
(int)(24 * 60_000L));
158+
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATANODES)
159+
.build();
160+
cluster.waitActive();
161+
// ensure after the edits get replayed , all the snapshots are deleted
162+
Assert.assertEquals(0,
163+
cluster.getNamesystem().getSnapshotManager().getNumSnapshots());
120164
}
121165

122166
static boolean exist(Path snapshotRoot, DistributedFileSystem hdfs)
@@ -168,6 +212,9 @@ public void testMultipleDirs() throws Exception {
168212
}
169213

170214
waitForGc(snapshotPaths, hdfs);
215+
// don't do edit log count validation here as gc snapshot
216+
// deletion count will be random here
217+
doEditLogValidation(cluster, -1);
171218
}
172219

173220
static void createSnapshots(Path snapshottableDir, int numSnapshots,

0 commit comments

Comments
 (0)