/// <exception cref="System.Exception"/> public virtual void TestBlockReaderLocalLegacyWithAppend() { short ReplFactor = 1; HdfsConfiguration conf = GetConfiguration(null); conf.SetBoolean(DFSConfigKeys.DfsClientUseLegacyBlockreaderlocal, true); MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).NumDataNodes(1).Build(); cluster.WaitActive(); DistributedFileSystem dfs = cluster.GetFileSystem(); Path path = new Path("/testBlockReaderLocalLegacy"); DFSTestUtil.CreateFile(dfs, path, 10, ReplFactor, 0); DFSTestUtil.WaitReplication(dfs, path, ReplFactor); ClientDatanodeProtocol proxy; Org.Apache.Hadoop.Security.Token.Token <BlockTokenIdentifier> token; ExtendedBlock originalBlock; long originalGS; { LocatedBlock lb = cluster.GetNameNode().GetRpcServer().GetBlockLocations(path.ToString (), 0, 1).Get(0); proxy = DFSUtil.CreateClientDatanodeProtocolProxy(lb.GetLocations()[0], conf, 60000 , false); token = lb.GetBlockToken(); // get block and generation stamp ExtendedBlock blk = new ExtendedBlock(lb.GetBlock()); originalBlock = new ExtendedBlock(blk); originalGS = originalBlock.GetGenerationStamp(); // test getBlockLocalPathInfo BlockLocalPathInfo info = proxy.GetBlockLocalPathInfo(blk, token); NUnit.Framework.Assert.AreEqual(originalGS, info.GetBlock().GetGenerationStamp()); } { // append one byte FSDataOutputStream @out = dfs.Append(path); @out.Write(1); @out.Close(); } { // get new generation stamp LocatedBlock lb = cluster.GetNameNode().GetRpcServer().GetBlockLocations(path.ToString (), 0, 1).Get(0); long newGS = lb.GetBlock().GetGenerationStamp(); NUnit.Framework.Assert.IsTrue(newGS > originalGS); // getBlockLocalPathInfo using the original block. NUnit.Framework.Assert.AreEqual(originalGS, originalBlock.GetGenerationStamp()); BlockLocalPathInfo info = proxy.GetBlockLocalPathInfo(originalBlock, token); NUnit.Framework.Assert.AreEqual(newGS, info.GetBlock().GetGenerationStamp()); } cluster.Shutdown(); }
/// <summary>Convert an ExtendedBlock to a Json map.</summary> private static IDictionary <string, object> ToJsonMap(ExtendedBlock extendedblock) { if (extendedblock == null) { return(null); } IDictionary <string, object> m = new SortedDictionary <string, object>(); m["blockPoolId"] = extendedblock.GetBlockPoolId(); m["blockId"] = extendedblock.GetBlockId(); m["numBytes"] = extendedblock.GetNumBytes(); m["generationStamp"] = extendedblock.GetGenerationStamp(); return(m); }
/* fill up a cluster with <code>numNodes</code> datanodes * whose used space to be <code>size</code> */ /// <exception cref="System.IO.IOException"/> /// <exception cref="System.Exception"/> /// <exception cref="Sharpen.TimeoutException"/> private static ExtendedBlock[][] GenerateBlocks(TestBalancerWithMultipleNameNodes.Suite s, long size) { ExtendedBlock[][] blocks = new ExtendedBlock[s.clients.Length][]; for (int n = 0; n < s.clients.Length; n++) { long fileLen = size / s.replication; CreateFile(s, n, fileLen); IList <LocatedBlock> locatedBlocks = s.clients[n].GetBlockLocations(FileName, 0, fileLen ).GetLocatedBlocks(); int numOfBlocks = locatedBlocks.Count; blocks[n] = new ExtendedBlock[numOfBlocks]; for (int i = 0; i < numOfBlocks; i++) { ExtendedBlock b = locatedBlocks[i].GetBlock(); blocks[n][i] = new ExtendedBlock(b.GetBlockPoolId(), b.GetBlockId(), b.GetNumBytes (), b.GetGenerationStamp()); } } return(blocks); }
public virtual void TestGetNewStamp() { int numDataNodes = 1; Configuration conf = new HdfsConfiguration(); MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).NumDataNodes(numDataNodes ).Build(); try { cluster.WaitActive(); FileSystem fileSys = cluster.GetFileSystem(); NamenodeProtocols namenode = cluster.GetNameNodeRpc(); /* Test writing to finalized replicas */ Path file = new Path("dataprotocol.dat"); DFSTestUtil.CreateFile(fileSys, file, 1L, (short)numDataNodes, 0L); // get the first blockid for the file ExtendedBlock firstBlock = DFSTestUtil.GetFirstBlock(fileSys, file); // test getNewStampAndToken on a finalized block try { namenode.UpdateBlockForPipeline(firstBlock, string.Empty); NUnit.Framework.Assert.Fail("Can not get a new GS from a finalized block"); } catch (IOException e) { NUnit.Framework.Assert.IsTrue(e.Message.Contains("is not under Construction")); } // test getNewStampAndToken on a non-existent block try { long newBlockId = firstBlock.GetBlockId() + 1; ExtendedBlock newBlock = new ExtendedBlock(firstBlock.GetBlockPoolId(), newBlockId , 0, firstBlock.GetGenerationStamp()); namenode.UpdateBlockForPipeline(newBlock, string.Empty); NUnit.Framework.Assert.Fail("Cannot get a new GS from a non-existent block"); } catch (IOException e) { NUnit.Framework.Assert.IsTrue(e.Message.Contains("does not exist")); } /* Test RBW replicas */ // change first block to a RBW DFSOutputStream @out = null; try { @out = (DFSOutputStream)(fileSys.Append(file).GetWrappedStream()); @out.Write(1); @out.Hflush(); FSDataInputStream @in = null; try { @in = fileSys.Open(file); firstBlock = DFSTestUtil.GetAllBlocks(@in)[0].GetBlock(); } finally { IOUtils.CloseStream(@in); } // test non-lease holder DFSClient dfs = ((DistributedFileSystem)fileSys).dfs; try { namenode.UpdateBlockForPipeline(firstBlock, "test" + dfs.clientName); NUnit.Framework.Assert.Fail("Cannot get a new GS for a non lease holder"); } catch (LeaseExpiredException e) { NUnit.Framework.Assert.IsTrue(e.Message.StartsWith("Lease mismatch")); } // test null lease holder try { namenode.UpdateBlockForPipeline(firstBlock, null); NUnit.Framework.Assert.Fail("Cannot get a new GS for a null lease holder"); } catch (LeaseExpiredException e) { NUnit.Framework.Assert.IsTrue(e.Message.StartsWith("Lease mismatch")); } // test getNewStampAndToken on a rbw block namenode.UpdateBlockForPipeline(firstBlock, dfs.clientName); } finally { IOUtils.CloseStream(@out); } } finally { cluster.Shutdown(); } }
public virtual void TestBlockSynchronization() { int OrgFileSize = 3000; Configuration conf = new HdfsConfiguration(); conf.SetLong(DFSConfigKeys.DfsBlockSizeKey, BlockSize); cluster = new MiniDFSCluster.Builder(conf).NumDataNodes(5).Build(); cluster.WaitActive(); //create a file DistributedFileSystem dfs = cluster.GetFileSystem(); string filestr = "/foo"; Path filepath = new Path(filestr); DFSTestUtil.CreateFile(dfs, filepath, OrgFileSize, ReplicationNum, 0L); NUnit.Framework.Assert.IsTrue(dfs.Exists(filepath)); DFSTestUtil.WaitReplication(dfs, filepath, ReplicationNum); //get block info for the last block LocatedBlock locatedblock = TestInterDatanodeProtocol.GetLastLocatedBlock(dfs.dfs .GetNamenode(), filestr); DatanodeInfo[] datanodeinfos = locatedblock.GetLocations(); NUnit.Framework.Assert.AreEqual(ReplicationNum, datanodeinfos.Length); //connect to data nodes DataNode[] datanodes = new DataNode[ReplicationNum]; for (int i = 0; i < ReplicationNum; i++) { datanodes[i] = cluster.GetDataNode(datanodeinfos[i].GetIpcPort()); NUnit.Framework.Assert.IsTrue(datanodes[i] != null); } //verify Block Info ExtendedBlock lastblock = locatedblock.GetBlock(); DataNode.Log.Info("newblocks=" + lastblock); for (int i_1 = 0; i_1 < ReplicationNum; i_1++) { CheckMetaInfo(lastblock, datanodes[i_1]); } DataNode.Log.Info("dfs.dfs.clientName=" + dfs.dfs.clientName); cluster.GetNameNodeRpc().Append(filestr, dfs.dfs.clientName, new EnumSetWritable < CreateFlag>(EnumSet.Of(CreateFlag.Append))); // expire lease to trigger block recovery. WaitLeaseRecovery(cluster); Block[] updatedmetainfo = new Block[ReplicationNum]; long oldSize = lastblock.GetNumBytes(); lastblock = TestInterDatanodeProtocol.GetLastLocatedBlock(dfs.dfs.GetNamenode(), filestr).GetBlock(); long currentGS = lastblock.GetGenerationStamp(); for (int i_2 = 0; i_2 < ReplicationNum; i_2++) { updatedmetainfo[i_2] = DataNodeTestUtils.GetFSDataset(datanodes[i_2]).GetStoredBlock (lastblock.GetBlockPoolId(), lastblock.GetBlockId()); NUnit.Framework.Assert.AreEqual(lastblock.GetBlockId(), updatedmetainfo[i_2].GetBlockId ()); NUnit.Framework.Assert.AreEqual(oldSize, updatedmetainfo[i_2].GetNumBytes()); NUnit.Framework.Assert.AreEqual(currentGS, updatedmetainfo[i_2].GetGenerationStamp ()); } // verify that lease recovery does not occur when namenode is in safemode System.Console.Out.WriteLine("Testing that lease recovery cannot happen during safemode." ); filestr = "/foo.safemode"; filepath = new Path(filestr); dfs.Create(filepath, (short)1); cluster.GetNameNodeRpc().SetSafeMode(HdfsConstants.SafeModeAction.SafemodeEnter, false); NUnit.Framework.Assert.IsTrue(dfs.dfs.Exists(filestr)); DFSTestUtil.WaitReplication(dfs, filepath, (short)1); WaitLeaseRecovery(cluster); // verify that we still cannot recover the lease LeaseManager lm = NameNodeAdapter.GetLeaseManager(cluster.GetNamesystem()); NUnit.Framework.Assert.IsTrue("Found " + lm.CountLease() + " lease, expected 1", lm.CountLease() == 1); cluster.GetNameNodeRpc().SetSafeMode(HdfsConstants.SafeModeAction.SafemodeLeave, false); }
public virtual void TestOpWrite() { int numDataNodes = 1; long BlockIdFudge = 128; Configuration conf = new HdfsConfiguration(); MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).NumDataNodes(numDataNodes ).Build(); try { cluster.WaitActive(); string poolId = cluster.GetNamesystem().GetBlockPoolId(); datanode = DataNodeTestUtils.GetDNRegistrationForBP(cluster.GetDataNodes()[0], poolId ); dnAddr = NetUtils.CreateSocketAddr(datanode.GetXferAddr()); FileSystem fileSys = cluster.GetFileSystem(); /* Test writing to finalized replicas */ Path file = new Path("dataprotocol.dat"); DFSTestUtil.CreateFile(fileSys, file, 1L, (short)numDataNodes, 0L); // get the first blockid for the file ExtendedBlock firstBlock = DFSTestUtil.GetFirstBlock(fileSys, file); // test PIPELINE_SETUP_CREATE on a finalized block TestWrite(firstBlock, BlockConstructionStage.PipelineSetupCreate, 0L, "Cannot create an existing block" , true); // test PIPELINE_DATA_STREAMING on a finalized block TestWrite(firstBlock, BlockConstructionStage.DataStreaming, 0L, "Unexpected stage" , true); // test PIPELINE_SETUP_STREAMING_RECOVERY on an existing block long newGS = firstBlock.GetGenerationStamp() + 1; TestWrite(firstBlock, BlockConstructionStage.PipelineSetupStreamingRecovery, newGS , "Cannot recover data streaming to a finalized replica", true); // test PIPELINE_SETUP_APPEND on an existing block newGS = firstBlock.GetGenerationStamp() + 1; TestWrite(firstBlock, BlockConstructionStage.PipelineSetupAppend, newGS, "Append to a finalized replica" , false); firstBlock.SetGenerationStamp(newGS); // test PIPELINE_SETUP_APPEND_RECOVERY on an existing block file = new Path("dataprotocol1.dat"); DFSTestUtil.CreateFile(fileSys, file, 1L, (short)numDataNodes, 0L); firstBlock = DFSTestUtil.GetFirstBlock(fileSys, file); newGS = firstBlock.GetGenerationStamp() + 1; TestWrite(firstBlock, BlockConstructionStage.PipelineSetupAppendRecovery, newGS, "Recover appending to a finalized replica", false); // test PIPELINE_CLOSE_RECOVERY on an existing block file = new Path("dataprotocol2.dat"); DFSTestUtil.CreateFile(fileSys, file, 1L, (short)numDataNodes, 0L); firstBlock = DFSTestUtil.GetFirstBlock(fileSys, file); newGS = firstBlock.GetGenerationStamp() + 1; TestWrite(firstBlock, BlockConstructionStage.PipelineCloseRecovery, newGS, "Recover failed close to a finalized replica" , false); firstBlock.SetGenerationStamp(newGS); // Test writing to a new block. Don't choose the next sequential // block ID to avoid conflicting with IDs chosen by the NN. long newBlockId = firstBlock.GetBlockId() + BlockIdFudge; ExtendedBlock newBlock = new ExtendedBlock(firstBlock.GetBlockPoolId(), newBlockId , 0, firstBlock.GetGenerationStamp()); // test PIPELINE_SETUP_CREATE on a new block TestWrite(newBlock, BlockConstructionStage.PipelineSetupCreate, 0L, "Create a new block" , false); // test PIPELINE_SETUP_STREAMING_RECOVERY on a new block newGS = newBlock.GetGenerationStamp() + 1; newBlock.SetBlockId(newBlock.GetBlockId() + 1); TestWrite(newBlock, BlockConstructionStage.PipelineSetupStreamingRecovery, newGS, "Recover a new block", true); // test PIPELINE_SETUP_APPEND on a new block newGS = newBlock.GetGenerationStamp() + 1; TestWrite(newBlock, BlockConstructionStage.PipelineSetupAppend, newGS, "Cannot append to a new block" , true); // test PIPELINE_SETUP_APPEND_RECOVERY on a new block newBlock.SetBlockId(newBlock.GetBlockId() + 1); newGS = newBlock.GetGenerationStamp() + 1; TestWrite(newBlock, BlockConstructionStage.PipelineSetupAppendRecovery, newGS, "Cannot append to a new block" , true); /* Test writing to RBW replicas */ Path file1 = new Path("dataprotocol1.dat"); DFSTestUtil.CreateFile(fileSys, file1, 1L, (short)numDataNodes, 0L); DFSOutputStream @out = (DFSOutputStream)(fileSys.Append(file1).GetWrappedStream() ); @out.Write(1); @out.Hflush(); FSDataInputStream @in = fileSys.Open(file1); firstBlock = DFSTestUtil.GetAllBlocks(@in)[0].GetBlock(); firstBlock.SetNumBytes(2L); try { // test PIPELINE_SETUP_CREATE on a RBW block TestWrite(firstBlock, BlockConstructionStage.PipelineSetupCreate, 0L, "Cannot create a RBW block" , true); // test PIPELINE_SETUP_APPEND on an existing block newGS = firstBlock.GetGenerationStamp() + 1; TestWrite(firstBlock, BlockConstructionStage.PipelineSetupAppend, newGS, "Cannot append to a RBW replica" , true); // test PIPELINE_SETUP_APPEND on an existing block TestWrite(firstBlock, BlockConstructionStage.PipelineSetupAppendRecovery, newGS, "Recover append to a RBW replica", false); firstBlock.SetGenerationStamp(newGS); // test PIPELINE_SETUP_STREAMING_RECOVERY on a RBW block file = new Path("dataprotocol2.dat"); DFSTestUtil.CreateFile(fileSys, file, 1L, (short)numDataNodes, 0L); @out = (DFSOutputStream)(fileSys.Append(file).GetWrappedStream()); @out.Write(1); @out.Hflush(); @in = fileSys.Open(file); firstBlock = DFSTestUtil.GetAllBlocks(@in)[0].GetBlock(); firstBlock.SetNumBytes(2L); newGS = firstBlock.GetGenerationStamp() + 1; TestWrite(firstBlock, BlockConstructionStage.PipelineSetupStreamingRecovery, newGS , "Recover a RBW replica", false); } finally { IOUtils.CloseStream(@in); IOUtils.CloseStream(@out); } } finally { cluster.Shutdown(); } }
public virtual void TestUpdateReplicaUnderRecovery() { MiniDFSCluster cluster = null; try { cluster = new MiniDFSCluster.Builder(conf).NumDataNodes(3).Build(); cluster.WaitActive(); string bpid = cluster.GetNamesystem().GetBlockPoolId(); //create a file DistributedFileSystem dfs = cluster.GetFileSystem(); string filestr = "/foo"; Path filepath = new Path(filestr); DFSTestUtil.CreateFile(dfs, filepath, 1024L, (short)3, 0L); //get block info LocatedBlock locatedblock = GetLastLocatedBlock(DFSClientAdapter.GetDFSClient(dfs ).GetNamenode(), filestr); DatanodeInfo[] datanodeinfo = locatedblock.GetLocations(); NUnit.Framework.Assert.IsTrue(datanodeinfo.Length > 0); //get DataNode and FSDataset objects DataNode datanode = cluster.GetDataNode(datanodeinfo[0].GetIpcPort()); NUnit.Framework.Assert.IsTrue(datanode != null); //initReplicaRecovery ExtendedBlock b = locatedblock.GetBlock(); long recoveryid = b.GetGenerationStamp() + 1; long newlength = b.GetNumBytes() - 1; FsDatasetSpi <object> fsdataset = DataNodeTestUtils.GetFSDataset(datanode); ReplicaRecoveryInfo rri = fsdataset.InitReplicaRecovery(new BlockRecoveryCommand.RecoveringBlock (b, null, recoveryid)); //check replica ReplicaInfo replica = FsDatasetTestUtil.FetchReplicaInfo(fsdataset, bpid, b.GetBlockId ()); NUnit.Framework.Assert.AreEqual(HdfsServerConstants.ReplicaState.Rur, replica.GetState ()); //check meta data before update FsDatasetImpl.CheckReplicaFiles(replica); { //case "THIS IS NOT SUPPOSED TO HAPPEN" //with (block length) != (stored replica's on disk length). //create a block with same id and gs but different length. ExtendedBlock tmp = new ExtendedBlock(b.GetBlockPoolId(), rri.GetBlockId(), rri.GetNumBytes () - 1, rri.GetGenerationStamp()); try { //update should fail fsdataset.UpdateReplicaUnderRecovery(tmp, recoveryid, tmp.GetBlockId(), newlength ); NUnit.Framework.Assert.Fail(); } catch (IOException ioe) { System.Console.Out.WriteLine("GOOD: getting " + ioe); } } //update string storageID = fsdataset.UpdateReplicaUnderRecovery(new ExtendedBlock(b.GetBlockPoolId (), rri), recoveryid, rri.GetBlockId(), newlength); NUnit.Framework.Assert.IsTrue(storageID != null); } finally { if (cluster != null) { cluster.Shutdown(); } } }
/// <summary>The following test first creates a file.</summary> /// <remarks> /// The following test first creates a file. /// It verifies the block information from a datanode. /// Then, it updates the block with new information and verifies again. /// </remarks> /// <param name="useDnHostname">whether DNs should connect to other DNs by hostname</param> /// <exception cref="System.Exception"/> private void CheckBlockMetaDataInfo(bool useDnHostname) { MiniDFSCluster cluster = null; conf.SetBoolean(DFSConfigKeys.DfsDatanodeUseDnHostname, useDnHostname); if (useDnHostname) { // Since the mini cluster only listens on the loopback we have to // ensure the hostname used to access DNs maps to the loopback. We // do this by telling the DN to advertise localhost as its hostname // instead of the default hostname. conf.Set(DFSConfigKeys.DfsDatanodeHostNameKey, "localhost"); } try { cluster = new MiniDFSCluster.Builder(conf).NumDataNodes(3).CheckDataNodeHostConfig (true).Build(); cluster.WaitActive(); //create a file DistributedFileSystem dfs = cluster.GetFileSystem(); string filestr = "/foo"; Path filepath = new Path(filestr); DFSTestUtil.CreateFile(dfs, filepath, 1024L, (short)3, 0L); NUnit.Framework.Assert.IsTrue(dfs.Exists(filepath)); //get block info LocatedBlock locatedblock = GetLastLocatedBlock(DFSClientAdapter.GetDFSClient(dfs ).GetNamenode(), filestr); DatanodeInfo[] datanodeinfo = locatedblock.GetLocations(); NUnit.Framework.Assert.IsTrue(datanodeinfo.Length > 0); //connect to a data node DataNode datanode = cluster.GetDataNode(datanodeinfo[0].GetIpcPort()); InterDatanodeProtocol idp = DataNodeTestUtils.CreateInterDatanodeProtocolProxy(datanode , datanodeinfo[0], conf, useDnHostname); // Stop the block scanners. datanode.GetBlockScanner().RemoveAllVolumeScanners(); //verify BlockMetaDataInfo ExtendedBlock b = locatedblock.GetBlock(); InterDatanodeProtocol.Log.Info("b=" + b + ", " + b.GetType()); CheckMetaInfo(b, datanode); long recoveryId = b.GetGenerationStamp() + 1; idp.InitReplicaRecovery(new BlockRecoveryCommand.RecoveringBlock(b, locatedblock. GetLocations(), recoveryId)); //verify updateBlock ExtendedBlock newblock = new ExtendedBlock(b.GetBlockPoolId(), b.GetBlockId(), b. GetNumBytes() / 2, b.GetGenerationStamp() + 1); idp.UpdateReplicaUnderRecovery(b, recoveryId, b.GetBlockId(), newblock.GetNumBytes ()); CheckMetaInfo(newblock, datanode); // Verify correct null response trying to init recovery for a missing block ExtendedBlock badBlock = new ExtendedBlock("fake-pool", b.GetBlockId(), 0, 0); NUnit.Framework.Assert.IsNull(idp.InitReplicaRecovery(new BlockRecoveryCommand.RecoveringBlock (badBlock, locatedblock.GetLocations(), recoveryId))); } finally { if (cluster != null) { cluster.Shutdown(); } } }
/// <exception cref="System.IO.IOException"/> internal static void CheckSuccess(DataTransferProtos.BlockOpResponseProto status, Peer peer, ExtendedBlock block, string file) { string logInfo = "for OP_READ_BLOCK" + ", self=" + peer.GetLocalAddressString() + ", remote=" + peer.GetRemoteAddressString() + ", for file " + file + ", for pool " + block.GetBlockPoolId() + " block " + block.GetBlockId() + "_" + block.GetGenerationStamp (); DataTransferProtoUtil.CheckBlockOpStatus(status, logInfo); }
/// <summary>Constructor</summary> /// <param name="block">Block that is being read</param> /// <param name="startOffset">starting offset to read from</param> /// <param name="length">length of data to read</param> /// <param name="corruptChecksumOk">if true, corrupt checksum is okay</param> /// <param name="verifyChecksum">verify checksum while reading the data</param> /// <param name="sendChecksum">send checksum to client.</param> /// <param name="datanode">datanode from which the block is being read</param> /// <param name="clientTraceFmt">format string used to print client trace logs</param> /// <exception cref="System.IO.IOException"/> internal BlockSender(ExtendedBlock block, long startOffset, long length, bool corruptChecksumOk , bool verifyChecksum, bool sendChecksum, DataNode datanode, string clientTraceFmt , CachingStrategy cachingStrategy) { // Cache-management related fields // 1MB try { this.block = block; this.corruptChecksumOk = corruptChecksumOk; this.verifyChecksum = verifyChecksum; this.clientTraceFmt = clientTraceFmt; /* * If the client asked for the cache to be dropped behind all reads, * we honor that. Otherwise, we use the DataNode defaults. * When using DataNode defaults, we use a heuristic where we only * drop the cache for large reads. */ if (cachingStrategy.GetDropBehind() == null) { this.dropCacheBehindAllReads = false; this.dropCacheBehindLargeReads = datanode.GetDnConf().dropCacheBehindReads; } else { this.dropCacheBehindAllReads = this.dropCacheBehindLargeReads = cachingStrategy.GetDropBehind (); } /* * Similarly, if readahead was explicitly requested, we always do it. * Otherwise, we read ahead based on the DataNode settings, and only * when the reads are large. */ if (cachingStrategy.GetReadahead() == null) { this.alwaysReadahead = false; this.readaheadLength = datanode.GetDnConf().readaheadLength; } else { this.alwaysReadahead = true; this.readaheadLength = cachingStrategy.GetReadahead(); } this.datanode = datanode; if (verifyChecksum) { // To simplify implementation, callers may not specify verification // without sending. Preconditions.CheckArgument(sendChecksum, "If verifying checksum, currently must also send it." ); } Replica replica; long replicaVisibleLength; lock (datanode.data) { replica = GetReplica(block, datanode); replicaVisibleLength = replica.GetVisibleLength(); } // if there is a write in progress ChunkChecksum chunkChecksum = null; if (replica is ReplicaBeingWritten) { ReplicaBeingWritten rbw = (ReplicaBeingWritten)replica; WaitForMinLength(rbw, startOffset + length); chunkChecksum = rbw.GetLastChecksumAndDataLen(); } if (replica.GetGenerationStamp() < block.GetGenerationStamp()) { throw new IOException("Replica gen stamp < block genstamp, block=" + block + ", replica=" + replica); } else { if (replica.GetGenerationStamp() > block.GetGenerationStamp()) { if (DataNode.Log.IsDebugEnabled()) { DataNode.Log.Debug("Bumping up the client provided" + " block's genstamp to latest " + replica.GetGenerationStamp() + " for block " + block); } block.SetGenerationStamp(replica.GetGenerationStamp()); } } if (replicaVisibleLength < 0) { throw new IOException("Replica is not readable, block=" + block + ", replica=" + replica); } if (DataNode.Log.IsDebugEnabled()) { DataNode.Log.Debug("block=" + block + ", replica=" + replica); } // transferToFully() fails on 32 bit platforms for block sizes >= 2GB, // use normal transfer in those cases this.transferToAllowed = datanode.GetDnConf().transferToAllowed&& (!is32Bit || length <= int.MaxValue); // Obtain a reference before reading data this.volumeRef = datanode.data.GetVolume(block).ObtainReference(); /* * (corruptChecksumOK, meta_file_exist): operation * True, True: will verify checksum * True, False: No verify, e.g., need to read data from a corrupted file * False, True: will verify checksum * False, False: throws IOException file not found */ DataChecksum csum = null; if (verifyChecksum || sendChecksum) { LengthInputStream metaIn = null; bool keepMetaInOpen = false; try { metaIn = datanode.data.GetMetaDataInputStream(block); if (!corruptChecksumOk || metaIn != null) { if (metaIn == null) { //need checksum but meta-data not found throw new FileNotFoundException("Meta-data not found for " + block); } // The meta file will contain only the header if the NULL checksum // type was used, or if the replica was written to transient storage. // Checksum verification is not performed for replicas on transient // storage. The header is important for determining the checksum // type later when lazy persistence copies the block to non-transient // storage and computes the checksum. if (metaIn.GetLength() > BlockMetadataHeader.GetHeaderSize()) { checksumIn = new DataInputStream(new BufferedInputStream(metaIn, HdfsConstants.IoFileBufferSize )); csum = BlockMetadataHeader.ReadDataChecksum(checksumIn, block); keepMetaInOpen = true; } } else { Log.Warn("Could not find metadata file for " + block); } } finally { if (!keepMetaInOpen) { IOUtils.CloseStream(metaIn); } } } if (csum == null) { // The number of bytes per checksum here determines the alignment // of reads: we always start reading at a checksum chunk boundary, // even if the checksum type is NULL. So, choosing too big of a value // would risk sending too much unnecessary data. 512 (1 disk sector) // is likely to result in minimal extra IO. csum = DataChecksum.NewDataChecksum(DataChecksum.Type.Null, 512); } /* * If chunkSize is very large, then the metadata file is mostly * corrupted. For now just truncate bytesPerchecksum to blockLength. */ int size = csum.GetBytesPerChecksum(); if (size > 10 * 1024 * 1024 && size > replicaVisibleLength) { csum = DataChecksum.NewDataChecksum(csum.GetChecksumType(), Math.Max((int)replicaVisibleLength , 10 * 1024 * 1024)); size = csum.GetBytesPerChecksum(); } chunkSize = size; checksum = csum; checksumSize = checksum.GetChecksumSize(); length = length < 0 ? replicaVisibleLength : length; // end is either last byte on disk or the length for which we have a // checksum long end = chunkChecksum != null?chunkChecksum.GetDataLength() : replica.GetBytesOnDisk (); if (startOffset < 0 || startOffset > end || (length + startOffset) > end) { string msg = " Offset " + startOffset + " and length " + length + " don't match block " + block + " ( blockLen " + end + " )"; Log.Warn(datanode.GetDNRegistrationForBP(block.GetBlockPoolId()) + ":sendBlock() : " + msg); throw new IOException(msg); } // Ensure read offset is position at the beginning of chunk offset = startOffset - (startOffset % chunkSize); if (length >= 0) { // Ensure endOffset points to end of chunk. long tmpLen = startOffset + length; if (tmpLen % chunkSize != 0) { tmpLen += (chunkSize - tmpLen % chunkSize); } if (tmpLen < end) { // will use on-disk checksum here since the end is a stable chunk end = tmpLen; } else { if (chunkChecksum != null) { // last chunk is changing. flag that we need to use in-memory checksum this.lastChunkChecksum = chunkChecksum; } } } endOffset = end; // seek to the right offsets if (offset > 0 && checksumIn != null) { long checksumSkip = (offset / chunkSize) * checksumSize; // note blockInStream is seeked when created below if (checksumSkip > 0) { // Should we use seek() for checksum file as well? IOUtils.SkipFully(checksumIn, checksumSkip); } } seqno = 0; if (DataNode.Log.IsDebugEnabled()) { DataNode.Log.Debug("replica=" + replica); } blockIn = datanode.data.GetBlockInputStream(block, offset); // seek to offset if (blockIn is FileInputStream) { blockInFd = ((FileInputStream)blockIn).GetFD(); } else { blockInFd = null; } } catch (IOException ioe) { IOUtils.CloseStream(this); IOUtils.CloseStream(blockIn); throw; } }