Exemple #1
0
        /// <exception cref="System.IO.IOException"/>
        private void ReadNextPacket()
        {
            //Read packet headers.
            packetReceiver.ReceiveNextPacket(@in);
            PacketHeader curHeader = packetReceiver.GetHeader();

            curDataSlice = packetReceiver.GetDataSlice();
            System.Diagnostics.Debug.Assert(curDataSlice.Capacity() == curHeader.GetDataLen()
                                            );
            if (Log.IsTraceEnabled())
            {
                Log.Trace("DFSClient readNextPacket got header " + curHeader);
            }
            // Sanity check the lengths
            if (!curHeader.SanityCheck(lastSeqNo))
            {
                throw new IOException("BlockReader: error in packet header " + curHeader);
            }
            if (curHeader.GetDataLen() > 0)
            {
                int chunks       = 1 + (curHeader.GetDataLen() - 1) / bytesPerChecksum;
                int checksumsLen = chunks * checksumSize;
                System.Diagnostics.Debug.Assert(packetReceiver.GetChecksumSlice().Capacity() == checksumsLen
                                                , "checksum slice capacity=" + packetReceiver.GetChecksumSlice().Capacity() + " checksumsLen="
                                                + checksumsLen);
                lastSeqNo = curHeader.GetSeqno();
                if (verifyChecksum && curDataSlice.Remaining() > 0)
                {
                    // N.B.: the checksum error offset reported here is actually
                    // relative to the start of the block, not the start of the file.
                    // This is slightly misleading, but preserves the behavior from
                    // the older BlockReader.
                    checksum.VerifyChunkedSums(curDataSlice, packetReceiver.GetChecksumSlice(), filename
                                               , curHeader.GetOffsetInBlock());
                }
                bytesNeededToFinish -= curHeader.GetDataLen();
            }
            // First packet will include some data prior to the first byte
            // the user requested. Skip it.
            if (curHeader.GetOffsetInBlock() < startOffset)
            {
                int newPos = (int)(startOffset - curHeader.GetOffsetInBlock());
                curDataSlice.Position(newPos);
            }
            // If we've now satisfied the whole client read, read one last packet
            // header, which should be empty
            if (bytesNeededToFinish <= 0)
            {
                ReadTrailingEmptyPacket();
                if (verifyChecksum)
                {
                    SendReadResult(DataTransferProtos.Status.ChecksumOk);
                }
                else
                {
                    SendReadResult(DataTransferProtos.Status.Success);
                }
            }
        }
 /// <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);
     }
 }