@Override
  public synchronized int read(byte buf[], int off, int len) throws IOException {
    dfsClient.checkOpen();
    if (closed) {
      dfsClient.incReadExpCntToStats();

      throw new IOException("Stream closed");
    }
    DFSClient.dfsInputStreamfailures.set(0);
    long start = System.currentTimeMillis();
    
    if (pos < getFileLength() || (pos == getFileLength() && len == 0)) {
      int retries = 2;
      while (retries > 0) {
        try {
          // If position equals or is larger than the end position of the
          // block, we try to seek to the next block, unless:
          // 1. user tries to read 0 bytes (usually by available() call), AND
          // 2. there is at least a known block for the file (blockEnd != -1), AND
          // 3. pos is the end of the file, AND
          // 4. the end of the block is the end of the file
          //    (the current block is the known last block of the file)
          // For this case, we want to stay in the current block, as in the case
          // that it is the last block (which is almost always true given
          // len == 0), the current block is the under-construction block whose size
          // you want to update.
          //
          if (len == 0) { // called by available()
            if (blockEnd == -1 // No current block selected
                || pos == getFileLength()) { // at the end of the file
              currentNode = blockSeekTo(pos, false);
              if (currentNode == null) {
                // In this case, user wants to know available information of
                // the file, but the file doesn't have any block created yet (it
                // is a 0 size file). Simply 0 should be returned.
                return 0;
              }
            } else {
              throw new IOException(
                  "Try to read 0 bytes while current position is not the end of the file");
            }
          } else if (pos > blockEnd
              || (this.isCurrentBlockUnderConstruction && blockReader != null
                  && blockReader.eos && blockReader.available() == 0)) {
            currentNode = blockSeekTo(pos, true);
          }
          
          int realLen = (int) Math.min((long) len, (blockEnd - pos + 1L));
          int result = readBuffer(buf, off, realLen);

          if (result >= 0) {
            pos += result;
          } else if (len != 0){
            // got a EOS from reader though we expect more data on it.
            throw new IOException("Unexpected EOS from the reader");
          }
          if (dfsClient.stats != null && result != -1) {
            dfsClient.stats.incrementBytesRead(result);
          }
          long timeval = System.currentTimeMillis() - start;
          dfsClient.metrics.incReadTime(timeval);
          dfsClient.metrics.incReadSize(result);
          dfsClient.metrics.incReadOps();
          return (result >= 0) ? result : 0;
        } catch (InterruptedIOException iie) {
          throw iie;
        } catch (ChecksumException ce) {
          dfsClient.incReadExpCntToStats();

          throw ce;
        } catch (IOException e) {
          dfsClient.incReadExpCntToStats();

          if (retries == 1) {
            DFSClient.LOG.warn("DFS Read: " + StringUtils.stringifyException(e));
          }
          blockEnd = -1;
          if (currentNode != null) { addToDeadNodes(currentNode); }
          if (--retries == 0) {
            if (len != 0) {
              throw e;
            } else {
              // When called by available(). No need to fail the query. In that case
              // available() value might not be updated, but it's OK.
              return 0;
            }
          }
        }
      }
    }
    return -1;
  }
@ Override public synchronized int read ( byte buf [ ] , int off , int len ) throws IOException { dfsClient . checkOpen ( ) ; if ( closed ) { dfsClient . incReadExpCntToStats ( ) ; throw new IOException ( "Stream closed" ) ; } DFSClient . dfsInputStreamfailures . set ( 0 ) ; long start = System . currentTimeMillis ( ) ; if ( pos < getFileLength ( ) || ( pos == getFileLength ( ) && len == 0 ) ) { int retries = 2 ; while ( retries > 0 ) { try { if ( len == 0 ) { if ( blockEnd == - 1 || pos == getFileLength ( ) ) { currentNode = blockSeekTo ( pos , false ) ; if ( currentNode == null ) { return 0 ; } } else { throw new IOException ( "Try to read 0 bytes while current position is not the end of the file" ) ; } } else if ( pos > blockEnd || ( this . isCurrentBlockUnderConstruction && blockReader != null && blockReader . eos && blockReader . available ( ) == 0 ) ) { currentNode = blockSeekTo ( pos , true ) ; } int realLen = ( int ) Math . min ( ( long ) len , ( blockEnd - pos + 1L ) ) ; int result = readBuffer ( buf , off , realLen ) ; if ( result >= 0 ) { pos += result ; } else if ( len != 0 ) { throw new IOException ( "Unexpected EOS from the reader" ) ; } if ( dfsClient . stats != null && result != - 1 ) { dfsClient . stats . incrementBytesRead ( result ) ; } long timeval = System . currentTimeMillis ( ) - start ; dfsClient . metrics . incReadTime ( timeval ) ; dfsClient . metrics . incReadSize ( result ) ; dfsClient . metrics . incReadOps ( ) ; return ( result >= 0 ) ? result : 0 ; } catch ( InterruptedIOException iie ) { throw iie ; } catch ( ChecksumException ce ) { dfsClient . incReadExpCntToStats ( ) ; throw ce ; } catch ( IOException e ) { dfsClient . incReadExpCntToStats ( ) ; if ( retries == 1 ) { DFSClient . LOG . warn ( "DFS Read: " + StringUtils . stringifyException ( e ) ) ; } blockEnd = - 1 ; if ( currentNode != null ) { addToDeadNodes ( currentNode ) ; } if ( -- retries == 0 ) { if ( len != 0 ) { throw e ; } else { return 0 ; } } } } } return - 1 ; }
Read the entire buffer.