private List < LocatedBlock > getBlockRange ( final long offset , final long length ) throws IOException { List < LocatedBlock > blockRange = new ArrayList < LocatedBlock > ( ) ; // Zero length. Not sure this ever happens in practice. if ( length == 0 ) return blockRange ; // A defensive measure to ensure that we never loop here eternally. // With a 256 M block size, 10000 blocks will correspond to 2.5 TB. // No one should read this much data at once in practice. int maxLoops = 10000 ; // Copy locatedBlocks to a local data structure. This ensures that // a concurrent invocation of openInfo() works OK, the reason being // that openInfo may completely replace locatedBlocks. DFSLocatedBlocks locatedBlocks = this . locatedBlocks ; if ( locatedBlocks == null ) { // Make this an IO exception because this is input/output code error. throw new IOException ( "locatedBlocks is null" ) ; } locatedBlocks . blockLocationInfoExpiresIfNeeded ( ) ; long remaining = length ; long curOff = offset ; while ( remaining > 0 ) { // a defensive check to bail out of this loop at all costs if ( -- maxLoops < 0 ) { String msg = "Failed to getBlockRange at offset " + offset + ", length=" + length + ", curOff=" + curOff + ", remaining=" + remaining + ". Aborting..." ; DFSClient . LOG . warn ( msg ) ; throw new IOException ( msg ) ; } LocatedBlock blk = locatedBlocks . getBlockContainingOffset ( curOff ) ; if ( blk == null ) { LocatedBlocks newBlocks ; newBlocks = getLocatedBlocks ( src , curOff , remaining ) ; if ( newBlocks == null ) { throw new IOException ( "Could not get block locations for curOff=" + curOff + ", remaining=" + remaining + " (offset=" + offset + ")" ) ; } locatedBlocks . insertRange ( newBlocks . getLocatedBlocks ( ) ) ; continue ; } blockRange . add ( blk ) ; long bytesRead = blk . getStartOffset ( ) + blk . getBlockSize ( ) - curOff ; remaining -= bytesRead ; curOff += bytesRead ; } DFSClient . checkBlockRange ( blockRange , offset , length ) ; return blockRange ; }
Get blocks in the specified range . The locations of all blocks overlapping with the given segment of the file are retrieved . Fetch them from the namenode if not cached .