/// <exception cref="System.IO.IOException"/> private void ReadTrailingEmptyPacket() { if (Log.IsTraceEnabled()) { Log.Trace("Reading empty packet at end of read"); } packetReceiver.ReceiveNextPacket(@in); PacketHeader trailer = packetReceiver.GetHeader(); if (!trailer.IsLastPacketInBlock() || trailer.GetDataLen() != 0) { throw new IOException("Expected empty end-of-read packet! Header: " + trailer); } }
/// <exception cref="System.IO.IOException"/> private int ReadChunkImpl(long pos, byte[] buf, int offset, int len, byte[] checksumBuf ) { lock (this) { // Read one chunk. if (eos) { // Already hit EOF return(-1); } // Read one DATA_CHUNK. long chunkOffset = lastChunkOffset; if (lastChunkLen > 0) { chunkOffset += lastChunkLen; } // pos is relative to the start of the first chunk of the read. // chunkOffset is relative to the start of the block. // This makes sure that the read passed from FSInputChecker is the // for the same chunk we expect to be reading from the DN. if ((pos + firstChunkOffset) != chunkOffset) { throw new IOException("Mismatch in pos : " + pos + " + " + firstChunkOffset + " != " + chunkOffset); } // Read next packet if the previous packet has been read completely. if (dataLeft <= 0) { //Read packet headers. PacketHeader header = new PacketHeader(); header.ReadFields(@in); if (Log.IsDebugEnabled()) { Log.Debug("DFSClient readChunk got header " + header); } // Sanity check the lengths if (!header.SanityCheck(lastSeqNo)) { throw new IOException("BlockReader: error in packet header " + header); } lastSeqNo = header.GetSeqno(); dataLeft = header.GetDataLen(); AdjustChecksumBytes(header.GetDataLen()); if (header.GetDataLen() > 0) { IOUtils.ReadFully(@in, ((byte[])checksumBytes.Array()), 0, checksumBytes.Limit()); } } // Sanity checks System.Diagnostics.Debug.Assert(len >= bytesPerChecksum); System.Diagnostics.Debug.Assert(checksum != null); System.Diagnostics.Debug.Assert(checksumSize == 0 || (checksumBuf.Length % checksumSize == 0)); int checksumsToRead; int bytesToRead; if (checksumSize > 0) { // How many chunks left in our packet - this is a ceiling // since we may have a partial chunk at the end of the file int chunksLeft = (dataLeft - 1) / bytesPerChecksum + 1; // How many chunks we can fit in databuffer // - note this is a floor since we always read full chunks int chunksCanFit = Math.Min(len / bytesPerChecksum, checksumBuf.Length / checksumSize ); // How many chunks should we read checksumsToRead = Math.Min(chunksLeft, chunksCanFit); // How many bytes should we actually read bytesToRead = Math.Min(checksumsToRead * bytesPerChecksum, dataLeft); } else { // full chunks // in case we have a partial // no checksum bytesToRead = Math.Min(dataLeft, len); checksumsToRead = 0; } if (bytesToRead > 0) { // Assert we have enough space System.Diagnostics.Debug.Assert(bytesToRead <= len); System.Diagnostics.Debug.Assert(checksumBytes.Remaining() >= checksumSize * checksumsToRead ); System.Diagnostics.Debug.Assert(checksumBuf.Length >= checksumSize * checksumsToRead ); IOUtils.ReadFully(@in, buf, offset, bytesToRead); checksumBytes.Get(checksumBuf, 0, checksumSize * checksumsToRead); } dataLeft -= bytesToRead; System.Diagnostics.Debug.Assert(dataLeft >= 0); lastChunkOffset = chunkOffset; lastChunkLen = bytesToRead; // If there's no data left in the current packet after satisfying // this read, and we have satisfied the client read, we expect // an empty packet header from the DN to signify this. // Note that pos + bytesToRead may in fact be greater since the // DN finishes off the entire last chunk. if (dataLeft == 0 && pos + bytesToRead >= bytesNeededToFinish) { // Read header PacketHeader hdr = new PacketHeader(); hdr.ReadFields(@in); if (!hdr.IsLastPacketInBlock() || hdr.GetDataLen() != 0) { throw new IOException("Expected empty end-of-read packet! Header: " + hdr); } eos = true; } if (bytesToRead == 0) { return(-1); } return(bytesToRead); } }