/// <summary>Corrupt a block on a data node.</summary> /// <remarks> /// Corrupt a block on a data node. Replace the block file content with content /// of 1, 2, ...BLOCK_SIZE. /// </remarks> /// <param name="block">the ExtendedBlock to be corrupted</param> /// <param name="dn">the data node where the block needs to be corrupted</param> /// <exception cref="System.IO.FileNotFoundException"/> /// <exception cref="System.IO.IOException"/> private static void CorruptBlock(ExtendedBlock block, DataNode dn) { FilePath f = DataNodeTestUtils.GetBlockFile(dn, block.GetBlockPoolId(), block.GetLocalBlock ()); RandomAccessFile raFile = new RandomAccessFile(f, "rw"); byte[] bytes = new byte[(int)BlockSize]; for (int i = 0; i < BlockSize; i++) { bytes[i] = unchecked ((byte)(i)); } raFile.Write(bytes); raFile.Close(); }
/// <summary>TC7: Corrupted replicas are present.</summary> /// <exception cref="System.IO.IOException">an exception might be thrown</exception> /// <exception cref="System.Exception"/> private void TestTC7(bool appendToNewBlock) { short repl = 2; Path p = new Path("/TC7/foo" + (appendToNewBlock ? "0" : "1")); System.Console.Out.WriteLine("p=" + p); //a. Create file with replication factor of 2. Write half block of data. Close file. int len1 = (int)(BlockSize / 2); { FSDataOutputStream @out = fs.Create(p, false, buffersize, repl, BlockSize); AppendTestUtil.Write(@out, 0, len1); @out.Close(); } DFSTestUtil.WaitReplication(fs, p, repl); //b. Log into one datanode that has one replica of this block. // Find the block file on this datanode and truncate it to zero size. LocatedBlocks locatedblocks = fs.dfs.GetNamenode().GetBlockLocations(p.ToString() , 0L, len1); NUnit.Framework.Assert.AreEqual(1, locatedblocks.LocatedBlockCount()); LocatedBlock lb = locatedblocks.Get(0); ExtendedBlock blk = lb.GetBlock(); NUnit.Framework.Assert.AreEqual(len1, lb.GetBlockSize()); DatanodeInfo[] datanodeinfos = lb.GetLocations(); NUnit.Framework.Assert.AreEqual(repl, datanodeinfos.Length); DataNode dn = cluster.GetDataNode(datanodeinfos[0].GetIpcPort()); FilePath f = DataNodeTestUtils.GetBlockFile(dn, blk.GetBlockPoolId(), blk.GetLocalBlock ()); RandomAccessFile raf = new RandomAccessFile(f, "rw"); AppendTestUtil.Log.Info("dn=" + dn + ", blk=" + blk + " (length=" + blk.GetNumBytes () + ")"); NUnit.Framework.Assert.AreEqual(len1, raf.Length()); raf.SetLength(0); raf.Close(); //c. Open file in "append mode". Append a new block worth of data. Close file. int len2 = (int)BlockSize; { FSDataOutputStream @out = appendToNewBlock ? fs.Append(p, EnumSet.Of(CreateFlag.Append , CreateFlag.NewBlock), 4096, null) : fs.Append(p); AppendTestUtil.Write(@out, len1, len2); @out.Close(); } //d. Reopen file and read two blocks worth of data. AppendTestUtil.Check(fs, p, len1 + len2); }
/// <summary> /// Test when a block's replica is removed from RBW folder in one of the /// datanode, namenode should ask to invalidate that corrupted block and /// schedule replication for one more replica for that under replicated block. /// </summary> /// <exception cref="System.IO.IOException"/> /// <exception cref="System.Exception"/> public virtual void TestBlockInvalidationWhenRBWReplicaMissedInDN() { // This test cannot pass on Windows due to file locking enforcement. It will // reject the attempt to delete the block file from the RBW folder. Assume.AssumeTrue(!Path.Windows); Configuration conf = new HdfsConfiguration(); conf.SetInt(DFSConfigKeys.DfsReplicationKey, 2); conf.SetLong(DFSConfigKeys.DfsBlockreportIntervalMsecKey, 300); conf.SetLong(DFSConfigKeys.DfsDatanodeDirectoryscanIntervalKey, 1); conf.SetLong(DFSConfigKeys.DfsHeartbeatIntervalKey, 1); MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).NumDataNodes(2).Build(); FSDataOutputStream @out = null; try { FSNamesystem namesystem = cluster.GetNamesystem(); FileSystem fs = cluster.GetFileSystem(); Path testPath = new Path("/tmp/TestRBWBlockInvalidation", "foo1"); @out = fs.Create(testPath, (short)2); @out.WriteBytes("HDFS-3157: " + testPath); @out.Hsync(); cluster.StartDataNodes(conf, 1, true, null, null, null); string bpid = namesystem.GetBlockPoolId(); ExtendedBlock blk = DFSTestUtil.GetFirstBlock(fs, testPath); Block block = blk.GetLocalBlock(); DataNode dn = cluster.GetDataNodes()[0]; // Delete partial block and its meta information from the RBW folder // of first datanode. FilePath blockFile = DataNodeTestUtils.GetBlockFile(dn, bpid, block); FilePath metaFile = DataNodeTestUtils.GetMetaFile(dn, bpid, block); NUnit.Framework.Assert.IsTrue("Could not delete the block file from the RBW folder" , blockFile.Delete()); NUnit.Framework.Assert.IsTrue("Could not delete the block meta file from the RBW folder" , metaFile.Delete()); @out.Close(); int liveReplicas = 0; while (true) { if ((liveReplicas = CountReplicas(namesystem, blk).LiveReplicas()) < 2) { // This confirms we have a corrupt replica Log.Info("Live Replicas after corruption: " + liveReplicas); break; } Sharpen.Thread.Sleep(100); } NUnit.Framework.Assert.AreEqual("There should be less than 2 replicas in the " + "liveReplicasMap", 1, liveReplicas); while (true) { if ((liveReplicas = CountReplicas(namesystem, blk).LiveReplicas()) > 1) { //Wait till the live replica count becomes equal to Replication Factor Log.Info("Live Replicas after Rereplication: " + liveReplicas); break; } Sharpen.Thread.Sleep(100); } NUnit.Framework.Assert.AreEqual("There should be two live replicas", 2, liveReplicas ); while (true) { Sharpen.Thread.Sleep(100); if (CountReplicas(namesystem, blk).CorruptReplicas() == 0) { Log.Info("Corrupt Replicas becomes 0"); break; } } } finally { if (@out != null) { @out.Close(); } cluster.Shutdown(); } }