/// <summary> /// Generate testing environment and return a collection of blocks /// on which to run the tests. /// </summary> /// <param name="bpid">Block pool ID to generate blocks for</param> /// <param name="dataSet">Namespace in which to insert blocks</param> /// <returns>Contrived blocks for further testing.</returns> /// <exception cref="System.IO.IOException"/> private ExtendedBlock[] Setup(string bpid, FsDatasetImpl dataSet) { // setup replicas map ExtendedBlock[] blocks = new ExtendedBlock[] { new ExtendedBlock(bpid, 1, 1, 2001 ), new ExtendedBlock(bpid, 2, 1, 2002), new ExtendedBlock(bpid, 3, 1, 2003), new ExtendedBlock(bpid, 4, 1, 2004), new ExtendedBlock(bpid, 5, 1, 2005), new ExtendedBlock (bpid, 6, 1, 2006) }; ReplicaMap replicasMap = dataSet.volumeMap; FsVolumeImpl vol = (FsVolumeImpl)dataSet.volumes.GetNextVolume(StorageType.Default , 0).GetVolume(); ReplicaInfo replicaInfo = new FinalizedReplica(blocks[Finalized].GetLocalBlock(), vol, vol.GetCurrentDir().GetParentFile()); replicasMap.Add(bpid, replicaInfo); replicaInfo.GetBlockFile().CreateNewFile(); replicaInfo.GetMetaFile().CreateNewFile(); replicasMap.Add(bpid, new ReplicaInPipeline(blocks[Temporary].GetBlockId(), blocks [Temporary].GetGenerationStamp(), vol, vol.CreateTmpFile(bpid, blocks[Temporary] .GetLocalBlock()).GetParentFile(), 0)); replicaInfo = new ReplicaBeingWritten(blocks[Rbw].GetLocalBlock(), vol, vol.CreateRbwFile (bpid, blocks[Rbw].GetLocalBlock()).GetParentFile(), null); replicasMap.Add(bpid, replicaInfo); replicaInfo.GetBlockFile().CreateNewFile(); replicaInfo.GetMetaFile().CreateNewFile(); replicasMap.Add(bpid, new ReplicaWaitingToBeRecovered(blocks[Rwr].GetLocalBlock() , vol, vol.CreateRbwFile(bpid, blocks[Rwr].GetLocalBlock()).GetParentFile())); replicasMap.Add(bpid, new ReplicaUnderRecovery(new FinalizedReplica(blocks[Rur].GetLocalBlock (), vol, vol.GetCurrentDir().GetParentFile()), 2007)); return(blocks); }
/// <summary> /// This method is invoked during DN startup when volumes are scanned to /// build up the volumeMap. /// </summary> /// <remarks> /// This method is invoked during DN startup when volumes are scanned to /// build up the volumeMap. /// Given two replicas, decide which one to keep. The preference is as /// follows: /// 1. Prefer the replica with the higher generation stamp. /// 2. If generation stamps are equal, prefer the replica with the /// larger on-disk length. /// 3. If on-disk length is the same, prefer the replica on persistent /// storage volume. /// 4. All other factors being equal, keep replica1. /// The other replica is removed from the volumeMap and is deleted from /// its storage volume. /// </remarks> /// <param name="replica1"/> /// <param name="replica2"/> /// <param name="volumeMap"/> /// <returns>the replica that is retained.</returns> /// <exception cref="System.IO.IOException"/> internal virtual ReplicaInfo ResolveDuplicateReplicas(ReplicaInfo replica1, ReplicaInfo replica2, ReplicaMap volumeMap) { if (!deleteDuplicateReplicas) { // Leave both block replicas in place. return(replica1); } ReplicaInfo replicaToDelete = SelectReplicaToDelete(replica1, replica2); ReplicaInfo replicaToKeep = (replicaToDelete != replica1) ? replica1 : replica2; // Update volumeMap and delete the replica volumeMap.Add(bpid, replicaToKeep); if (replicaToDelete != null) { DeleteReplica(replicaToDelete); } return(replicaToKeep); }
public virtual void Setup() { map.Add(bpid, new FinalizedReplica(block, null, null)); }
public virtual void TestInitReplicaRecovery() { long firstblockid = 10000L; long gs = 7777L; long length = 22L; ReplicaMap map = new ReplicaMap(this); string bpid = "BP-TEST"; Block[] blocks = new Block[5]; for (int i = 0; i < blocks.Length; i++) { blocks[i] = new Block(firstblockid + i, length, gs); map.Add(bpid, CreateReplicaInfo(blocks[i])); } { //normal case Block b = blocks[0]; ReplicaInfo originalInfo = map.Get(bpid, b); long recoveryid = gs + 1; ReplicaRecoveryInfo recoveryInfo = FsDatasetImpl.InitReplicaRecovery(bpid, map, blocks [0], recoveryid, DFSConfigKeys.DfsDatanodeXceiverStopTimeoutMillisDefault); AssertEquals(originalInfo, recoveryInfo); ReplicaUnderRecovery updatedInfo = (ReplicaUnderRecovery)map.Get(bpid, b); NUnit.Framework.Assert.AreEqual(originalInfo.GetBlockId(), updatedInfo.GetBlockId ()); NUnit.Framework.Assert.AreEqual(recoveryid, updatedInfo.GetRecoveryID()); //recover one more time long recoveryid2 = gs + 2; ReplicaRecoveryInfo recoveryInfo2 = FsDatasetImpl.InitReplicaRecovery(bpid, map, blocks[0], recoveryid2, DFSConfigKeys.DfsDatanodeXceiverStopTimeoutMillisDefault ); AssertEquals(originalInfo, recoveryInfo2); ReplicaUnderRecovery updatedInfo2 = (ReplicaUnderRecovery)map.Get(bpid, b); NUnit.Framework.Assert.AreEqual(originalInfo.GetBlockId(), updatedInfo2.GetBlockId ()); NUnit.Framework.Assert.AreEqual(recoveryid2, updatedInfo2.GetRecoveryID()); //case RecoveryInProgressException try { FsDatasetImpl.InitReplicaRecovery(bpid, map, b, recoveryid, DFSConfigKeys.DfsDatanodeXceiverStopTimeoutMillisDefault ); NUnit.Framework.Assert.Fail(); } catch (RecoveryInProgressException ripe) { System.Console.Out.WriteLine("GOOD: getting " + ripe); } } { // BlockRecoveryFI_01: replica not found long recoveryid = gs + 1; Block b = new Block(firstblockid - 1, length, gs); ReplicaRecoveryInfo r = FsDatasetImpl.InitReplicaRecovery(bpid, map, b, recoveryid , DFSConfigKeys.DfsDatanodeXceiverStopTimeoutMillisDefault); NUnit.Framework.Assert.IsNull("Data-node should not have this replica.", r); } { // BlockRecoveryFI_02: "THIS IS NOT SUPPOSED TO HAPPEN" with recovery id < gs long recoveryid = gs - 1; Block b = new Block(firstblockid + 1, length, gs); try { FsDatasetImpl.InitReplicaRecovery(bpid, map, b, recoveryid, DFSConfigKeys.DfsDatanodeXceiverStopTimeoutMillisDefault ); NUnit.Framework.Assert.Fail(); } catch (IOException ioe) { System.Console.Out.WriteLine("GOOD: getting " + ioe); } } { // BlockRecoveryFI_03: Replica's gs is less than the block's gs long recoveryid = gs + 1; Block b = new Block(firstblockid, length, gs + 1); try { FsDatasetImpl.InitReplicaRecovery(bpid, map, b, recoveryid, DFSConfigKeys.DfsDatanodeXceiverStopTimeoutMillisDefault ); NUnit.Framework.Assert.Fail("InitReplicaRecovery should fail because replica's " + "gs is less than the block's gs"); } catch (IOException e) { e.Message.StartsWith("replica.getGenerationStamp() < block.getGenerationStamp(), block=" ); } } }
/// <summary>Add replicas under the given directory to the volume map</summary> /// <param name="volumeMap">the replicas map</param> /// <param name="dir">an input directory</param> /// <param name="lazyWriteReplicaMap"> /// Map of replicas on transient /// storage. /// </param> /// <param name="isFinalized"> /// true if the directory has finalized replicas; /// false if the directory has rbw replicas /// </param> /// <exception cref="System.IO.IOException"/> internal virtual void AddToReplicasMap(ReplicaMap volumeMap, FilePath dir, RamDiskReplicaTracker lazyWriteReplicaMap, bool isFinalized) { FilePath[] files = FileUtil.ListFiles(dir); foreach (FilePath file in files) { if (file.IsDirectory()) { AddToReplicasMap(volumeMap, file, lazyWriteReplicaMap, isFinalized); } if (isFinalized && FsDatasetUtil.IsUnlinkTmpFile(file)) { file = RecoverTempUnlinkedBlock(file); if (file == null) { // the original block still exists, so we cover it // in another iteration and can continue here continue; } } if (!Block.IsBlockFilename(file)) { continue; } long genStamp = FsDatasetUtil.GetGenerationStampFromFile(files, file); long blockId = Block.Filename2id(file.GetName()); ReplicaInfo newReplica = null; if (isFinalized) { newReplica = new FinalizedReplica(blockId, file.Length(), genStamp, volume, file. GetParentFile()); } else { bool loadRwr = true; FilePath restartMeta = new FilePath(file.GetParent() + FilePath.pathSeparator + "." + file.GetName() + ".restart"); Scanner sc = null; try { sc = new Scanner(restartMeta, "UTF-8"); // The restart meta file exists if (sc.HasNextLong() && (sc.NextLong() > Time.Now())) { // It didn't expire. Load the replica as a RBW. // We don't know the expected block length, so just use 0 // and don't reserve any more space for writes. newReplica = new ReplicaBeingWritten(blockId, ValidateIntegrityAndSetLength(file, genStamp), genStamp, volume, file.GetParentFile(), null, 0); loadRwr = false; } sc.Close(); if (!restartMeta.Delete()) { FsDatasetImpl.Log.Warn("Failed to delete restart meta file: " + restartMeta.GetPath ()); } } catch (FileNotFoundException) { } finally { // nothing to do hereFile dir = if (sc != null) { sc.Close(); } } // Restart meta doesn't exist or expired. if (loadRwr) { newReplica = new ReplicaWaitingToBeRecovered(blockId, ValidateIntegrityAndSetLength (file, genStamp), genStamp, volume, file.GetParentFile()); } } ReplicaInfo oldReplica = volumeMap.Get(bpid, newReplica.GetBlockId()); if (oldReplica == null) { volumeMap.Add(bpid, newReplica); } else { // We have multiple replicas of the same block so decide which one // to keep. newReplica = ResolveDuplicateReplicas(newReplica, oldReplica, volumeMap); } // If we are retaining a replica on transient storage make sure // it is in the lazyWriteReplicaMap so it can be persisted // eventually. if (newReplica.GetVolume().IsTransientStorage()) { lazyWriteReplicaMap.AddReplica(bpid, blockId, (FsVolumeImpl)newReplica.GetVolume( )); } else { lazyWriteReplicaMap.DiscardReplica(bpid, blockId, false); } } }