code: private LocatedBlock getBlockAt(long offset, boolean updatePosition,
        boolean throwWhenNotFound)
        throws IOException {
      assert (locatedBlocks != null) : "locatedBlocks is null";
      // search cached blocks first
      locatedBlocks.blockLocationInfoExpiresIfNeeded();
      LocatedBlock blk = locatedBlocks.getBlockContainingOffset(offset);
      if (blk == null) { // block is not cached
        // fetch more blocks
        LocatedBlocks newBlocks;
        newBlocks = getLocatedBlocks(src, offset, prefetchSize);
        if (newBlocks == null) {
          if (!throwWhenNotFound) {
            return null;
          }
          throw new IOException("Could not find target position " + offset);
        }
        locatedBlocks.insertRange(newBlocks.getLocatedBlocks());
        locatedBlocks.setFileLength(newBlocks.getFileLength());
      }
      blk = locatedBlocks.getBlockContainingOffset(offset);
      if (blk == null) {
        if (!throwWhenNotFound) {
          return null;
        }
        throw new IOException("Failed to determine location for block at "
            + "offset=" + offset);
      }
      if (updatePosition) {
        // update current position
        this.pos = offset;
        this.blockEnd = blk.getStartOffset() + blk.getBlockSize() - 1;
        this.currentBlock = blk.getBlock();
        isCurrentBlockUnderConstruction = locatedBlocks
            .isUnderConstructionBlock(this.currentBlock);
      }
      return blk;
  
    }
docs: Get block at the specified position. Fetch it from the namenode if not
  cached.
  
  If updatePosition is true, it is required that the the method is
  called inside the synchronized block, since the current block information
  will be updated.
  
  @param offset
  @param updatePosition
  @param throwWhenNoFound
  when no block found for the offset return null instead of
  throwing an exception
  @return located block
  @throws IOException