@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "SF_SWITCH_FALLTHROUGH",
      justification = "Intentional")
  public static Reader createReader(ReaderContext context, HFileInfo fileInfo,
    CacheConfig cacheConf, Configuration conf) throws IOException {
    try {
      if (context.getReaderType() == ReaderType.STREAM) {
        // stream reader will share trailer with pread reader, see HFileStreamReader#copyFields
        return new HFileStreamReader(context, fileInfo, cacheConf, conf);
      }
      FixedFileTrailer trailer = fileInfo.getTrailer();
      switch (trailer.getMajorVersion()) {
        case 2:
          LOG.debug("Opening HFile v2 with v3 reader");
          // Fall through. FindBugs: SF_SWITCH_FALLTHROUGH
        case 3:
          return new HFilePreadReader(context, fileInfo, cacheConf, conf);
        default:
          throw new IllegalArgumentException("Invalid HFile version " + trailer.getMajorVersion());
      }
    } catch (Throwable t) {
      IOUtils.closeQuietly(context.getInputStreamWrapper(),
        e -> LOG.warn("failed to close input stream wrapper", e));
      throw new CorruptHFileException(
        "Problem reading HFile Trailer from file " + context.getFilePath(), t);
    } finally {
      context.getInputStreamWrapper().unbuffer();
    }
  }
Method returns the reader given the specified arguments. TODO This is a bad abstraction. See
HBASE-6635.
@param context   Reader context info
@param fileInfo  HFile info
@param cacheConf Cache configuation values, cannot be null.
@param conf      Configuration
@return an appropriate instance of HFileReader
@throws IOException If file is invalid, will throw CorruptHFileException flavored IOException
hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFile.java