|
27 | 27 | import static org.junit.Assert.assertEquals; |
28 | 28 | import static org.junit.Assert.assertTrue; |
29 | 29 | import static org.junit.Assert.assertFalse; |
| 30 | +import static org.junit.Assert.assertNotNull; |
30 | 31 | import static org.junit.Assert.fail; |
31 | 32 |
|
32 | 33 | import java.io.Closeable; |
|
48 | 49 | import org.apache.hadoop.hdfs.AppendTestUtil; |
49 | 50 | import org.apache.hadoop.hdfs.MiniDFSNNTopology; |
50 | 51 | import org.apache.hadoop.hdfs.protocol.ExtendedBlock; |
| 52 | +import org.apache.hadoop.hdfs.server.blockmanagement.SequentialBlockIdGenerator; |
51 | 53 | import org.apache.hadoop.hdfs.server.datanode.FsDatasetTestUtils.MaterializedReplica; |
52 | 54 | import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsDatasetSpi; |
53 | 55 | import org.apache.hadoop.hdfs.server.datanode.VolumeScanner.ScanResultHandler; |
@@ -1119,6 +1121,57 @@ public Boolean get() { |
1119 | 1121 | } |
1120 | 1122 | } |
1121 | 1123 |
|
| 1124 | + @Test |
| 1125 | + public void testNextBlock() throws Exception { |
| 1126 | + DataNodeFaultInjector oldInjector = DataNodeFaultInjector.get(); |
| 1127 | + try { |
| 1128 | + Configuration conf = new Configuration(); |
| 1129 | + disableBlockScanner(conf); |
| 1130 | + |
| 1131 | + // Need to manually delete block to trigger error |
| 1132 | + final DataNodeFaultInjector injector = new DataNodeFaultInjector() { |
| 1133 | + @Override |
| 1134 | + public void delayDeleteReplica() { |
| 1135 | + while (true) { |
| 1136 | + try { |
| 1137 | + Thread.sleep(1000); |
| 1138 | + } catch (InterruptedException e) { |
| 1139 | + throw new RuntimeException(e); |
| 1140 | + } |
| 1141 | + } |
| 1142 | + } |
| 1143 | + }; |
| 1144 | + DataNodeFaultInjector.set(injector); |
| 1145 | + |
| 1146 | + TestContext ctx = new TestContext(conf, 1); |
| 1147 | + SequentialBlockIdGenerator blockIdGenerator = |
| 1148 | + ctx.cluster.getNamesystem().getBlockManager().getBlockIdManager().getBlockIdGenerator(); |
| 1149 | + |
| 1150 | + // /subdir24/subdir4 |
| 1151 | + blockIdGenerator.skipTo(1356375042); |
| 1152 | + ctx.createFiles(0, 1, 1); |
| 1153 | + // /subdir24/subdir29 |
| 1154 | + blockIdGenerator.skipTo(1356381682); |
| 1155 | + ctx.createFiles(0, 1, 1); |
| 1156 | + |
| 1157 | + FsVolumeSpi volume = ctx.volumes.get(0); |
| 1158 | + BlockIterator iter = volume.newBlockIterator(ctx.bpids[0], "test"); |
| 1159 | + |
| 1160 | + // Get the subdir29 block. It comes before the subdir4 block. |
| 1161 | + ExtendedBlock nextBlock = iter.nextBlock(); |
| 1162 | + assertNotNull(nextBlock); |
| 1163 | + FinalizedReplica replica = (FinalizedReplica) ctx.datanode.getFSDataset() |
| 1164 | + .getReplica(ctx.cluster.getNamesystem().getBlockPoolId(), nextBlock.getBlockId()); |
| 1165 | + replica.deleteBlockData(); |
| 1166 | + replica.deleteMetadata(); |
| 1167 | + |
| 1168 | + // subdir29 has been cleaned up, nextBlock() will skip directly to subdir4 |
| 1169 | + assertNotNull(iter.nextBlock()); |
| 1170 | + } finally { |
| 1171 | + DataNodeFaultInjector.set(oldInjector); |
| 1172 | + } |
| 1173 | + } |
| 1174 | + |
1122 | 1175 | private static class DelayVolumeScannerResponseToInterrupt extends |
1123 | 1176 | VolumeScannerCBInjector { |
1124 | 1177 | final private long delayAmountNS; |
|
0 commit comments