001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.regionserver;
019
020import java.io.FileNotFoundException;
021import java.io.IOException;
022import java.util.concurrent.atomic.AtomicInteger;
023import java.util.regex.Matcher;
024import java.util.regex.Pattern;
025import org.apache.hadoop.conf.Configurable;
026import org.apache.hadoop.conf.Configuration;
027import org.apache.hadoop.fs.FileStatus;
028import org.apache.hadoop.fs.FileSystem;
029import org.apache.hadoop.fs.Path;
030import org.apache.hadoop.hbase.HDFSBlocksDistribution;
031import org.apache.hadoop.hbase.io.FSDataInputStreamWrapper;
032import org.apache.hadoop.hbase.io.HFileLink;
033import org.apache.hadoop.hbase.io.HalfStoreFileReader;
034import org.apache.hadoop.hbase.io.Reference;
035import org.apache.hadoop.hbase.io.hfile.CacheConfig;
036import org.apache.hadoop.hbase.io.hfile.HFileInfo;
037import org.apache.hadoop.hbase.io.hfile.ReaderContext;
038import org.apache.hadoop.hbase.io.hfile.ReaderContext.ReaderType;
039import org.apache.hadoop.hbase.io.hfile.ReaderContextBuilder;
040import org.apache.hadoop.hbase.mob.MobUtils;
041import org.apache.hadoop.hbase.util.FSUtils;
042import org.apache.hadoop.hbase.util.Pair;
043import org.apache.yetus.audience.InterfaceAudience;
044import org.slf4j.Logger;
045import org.slf4j.LoggerFactory;
046
047/**
048 * Describe a StoreFile (hfile, reference, link)
049 */
050@InterfaceAudience.Private
051public class StoreFileInfo implements Configurable {
052  private static final Logger LOG = LoggerFactory.getLogger(StoreFileInfo.class);
053
054  /**
055   * A non-capture group, for hfiles, so that this can be embedded. HFiles are uuid ([0-9a-z]+).
056   * Bulk loaded hfiles has (_SeqId_[0-9]+_) has suffix. The mob del file has (_del) as suffix.
057   */
058  public static final String HFILE_NAME_REGEX = "[0-9a-f]+(?:(?:_SeqId_[0-9]+_)|(?:_del))?";
059
060  /** Regex that will work for hfiles */
061  private static final Pattern HFILE_NAME_PATTERN = Pattern.compile("^(" + HFILE_NAME_REGEX + ")");
062
063  /**
064   * Regex that will work for straight reference names ({@code <hfile>.<parentEncRegion>}) and
065   * hfilelink reference names ({@code
066   *
067  <table>
068   * =<region>-<hfile>.<parentEncRegion>}) If reference, then the regex has more than just one
069   * group. Group 1, hfile/hfilelink pattern, is this file's id. Group 2 '(.+)' is the reference's
070   * parent region name.
071   */
072  private static final Pattern REF_NAME_PATTERN =
073    Pattern.compile(String.format("^(%s|%s)\\.(.+)$", HFILE_NAME_REGEX, HFileLink.LINK_NAME_REGEX));
074
075  public static final String STORE_FILE_READER_NO_READAHEAD = "hbase.store.reader.no-readahead";
076  public static final boolean DEFAULT_STORE_FILE_READER_NO_READAHEAD = false;
077
078  // Configuration
079  private Configuration conf;
080
081  // FileSystem handle
082  private final FileSystem fs;
083
084  // HDFS blocks distribution information
085  private HDFSBlocksDistribution hdfsBlocksDistribution = null;
086
087  private HFileInfo hfileInfo;
088
089  // If this storefile references another, this is the reference instance.
090  private final Reference reference;
091
092  // If this storefile is a link to another, this is the link instance.
093  private final HFileLink link;
094
095  private final Path initialPath;
096
097  private RegionCoprocessorHost coprocessorHost;
098
099  // timestamp on when the file was created, is 0 and ignored for reference or link files
100  private long createdTimestamp;
101
102  private long size;
103
104  private final boolean primaryReplica;
105
106  private final boolean noReadahead;
107
108  // Counter that is incremented every time a scanner is created on the
109  // store file. It is decremented when the scan on the store file is
110  // done.
111  final AtomicInteger refCount = new AtomicInteger(0);
112
113  /**
114   * Create a Store File Info
115   * @param conf           the {@link Configuration} to use
116   * @param fs             The current file system to use.
117   * @param initialPath    The {@link Path} of the file
118   * @param primaryReplica true if this is a store file for primary replica, otherwise false.
119   */
120  public StoreFileInfo(final Configuration conf, final FileSystem fs, final Path initialPath,
121    final boolean primaryReplica) throws IOException {
122    this(conf, fs, null, initialPath, primaryReplica);
123  }
124
125  private StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus,
126    final Path initialPath, final boolean primaryReplica) throws IOException {
127    assert fs != null;
128    assert initialPath != null;
129    assert conf != null;
130
131    this.fs = fs;
132    this.conf = conf;
133    this.initialPath = fs.makeQualified(initialPath);
134    this.primaryReplica = primaryReplica;
135    this.noReadahead =
136      this.conf.getBoolean(STORE_FILE_READER_NO_READAHEAD, DEFAULT_STORE_FILE_READER_NO_READAHEAD);
137    Path p = initialPath;
138    if (HFileLink.isHFileLink(p)) {
139      // HFileLink
140      this.reference = null;
141      this.link = HFileLink.buildFromHFileLinkPattern(conf, p);
142      LOG.trace("{} is a link", p);
143    } else if (isReference(p)) {
144      this.reference = Reference.read(fs, p);
145      Path referencePath = getReferredToFile(p);
146      if (HFileLink.isHFileLink(referencePath)) {
147        // HFileLink Reference
148        this.link = HFileLink.buildFromHFileLinkPattern(conf, referencePath);
149      } else {
150        // Reference
151        this.link = null;
152      }
153      LOG.trace("{} is a {} reference to {}", p, reference.getFileRegion(), referencePath);
154    } else if (isHFile(p) || isMobFile(p) || isMobRefFile(p)) {
155      // HFile
156      if (fileStatus != null) {
157        this.createdTimestamp = fileStatus.getModificationTime();
158        this.size = fileStatus.getLen();
159      } else {
160        FileStatus fStatus = fs.getFileStatus(initialPath);
161        this.createdTimestamp = fStatus.getModificationTime();
162        this.size = fStatus.getLen();
163      }
164      this.reference = null;
165      this.link = null;
166    } else {
167      throw new IOException("path=" + p + " doesn't look like a valid StoreFile");
168    }
169  }
170
171  /**
172   * Create a Store File Info
173   * @param conf       the {@link Configuration} to use
174   * @param fs         The current file system to use.
175   * @param fileStatus The {@link FileStatus} of the file
176   */
177  public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus)
178    throws IOException {
179    this(conf, fs, fileStatus, fileStatus.getPath(), true);
180  }
181
182  /**
183   * Create a Store File Info from an HFileLink
184   * @param conf       The {@link Configuration} to use
185   * @param fs         The current file system to use
186   * @param fileStatus The {@link FileStatus} of the file
187   */
188  public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus,
189    final HFileLink link) {
190    this(conf, fs, fileStatus, null, link);
191  }
192
193  /**
194   * Create a Store File Info from an HFileLink
195   * @param conf       The {@link Configuration} to use
196   * @param fs         The current file system to use
197   * @param fileStatus The {@link FileStatus} of the file
198   * @param reference  The reference instance
199   */
200  public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus,
201    final Reference reference) {
202    this(conf, fs, fileStatus, reference, null);
203  }
204
205  /**
206   * Create a Store File Info from an HFileLink and a Reference
207   * @param conf       The {@link Configuration} to use
208   * @param fs         The current file system to use
209   * @param fileStatus The {@link FileStatus} of the file
210   * @param reference  The reference instance
211   * @param link       The link instance
212   */
213  public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus,
214    final Reference reference, final HFileLink link) {
215    this.fs = fs;
216    this.conf = conf;
217    this.primaryReplica = false;
218    this.initialPath = (fileStatus == null) ? null : fileStatus.getPath();
219    this.createdTimestamp = (fileStatus == null) ? 0 : fileStatus.getModificationTime();
220    this.reference = reference;
221    this.link = link;
222    this.noReadahead =
223      this.conf.getBoolean(STORE_FILE_READER_NO_READAHEAD, DEFAULT_STORE_FILE_READER_NO_READAHEAD);
224  }
225
226  @Override
227  public Configuration getConf() {
228    return conf;
229  }
230
231  @Override
232  public void setConf(Configuration conf) {
233    this.conf = conf;
234  }
235
236  /**
237   * Size of the Hfile n
238   */
239  public long getSize() {
240    return size;
241  }
242
243  /**
244   * Sets the region coprocessor env. n
245   */
246  public void setRegionCoprocessorHost(RegionCoprocessorHost coprocessorHost) {
247    this.coprocessorHost = coprocessorHost;
248  }
249
250  /**
251   * @return the Reference object associated to this StoreFileInfo. null if the StoreFile is not a
252   *         reference.
253   */
254  public Reference getReference() {
255    return this.reference;
256  }
257
258  /** Returns True if the store file is a Reference */
259  public boolean isReference() {
260    return this.reference != null;
261  }
262
263  /** Returns True if the store file is a top Reference */
264  public boolean isTopReference() {
265    return this.reference != null && Reference.isTopFileRegion(this.reference.getFileRegion());
266  }
267
268  /** Returns True if the store file is a link */
269  public boolean isLink() {
270    return this.link != null && this.reference == null;
271  }
272
273  /** Returns the HDFS block distribution */
274  public HDFSBlocksDistribution getHDFSBlockDistribution() {
275    return this.hdfsBlocksDistribution;
276  }
277
278  StoreFileReader createReader(ReaderContext context, CacheConfig cacheConf) throws IOException {
279    StoreFileReader reader = null;
280    if (this.reference != null) {
281      reader = new HalfStoreFileReader(context, hfileInfo, cacheConf, reference, refCount, conf);
282    } else {
283      reader = new StoreFileReader(context, hfileInfo, cacheConf, refCount, conf);
284    }
285    return reader;
286  }
287
288  ReaderContext createReaderContext(boolean doDropBehind, long readahead, ReaderType type)
289    throws IOException {
290    FSDataInputStreamWrapper in;
291    FileStatus status;
292    if (this.link != null) {
293      // HFileLink
294      in = new FSDataInputStreamWrapper(fs, this.link, doDropBehind, readahead);
295      status = this.link.getFileStatus(fs);
296    } else if (this.reference != null) {
297      // HFile Reference
298      Path referencePath = getReferredToFile(this.getPath());
299      try {
300        in = new FSDataInputStreamWrapper(fs, referencePath, doDropBehind, readahead);
301      } catch (FileNotFoundException fnfe) {
302        // Intercept the exception so can insert more info about the Reference; otherwise
303        // exception just complains about some random file -- operator doesn't realize it
304        // other end of a Reference
305        FileNotFoundException newFnfe = new FileNotFoundException(toString());
306        newFnfe.initCause(fnfe);
307        throw newFnfe;
308      }
309      status = fs.getFileStatus(referencePath);
310    } else {
311      in = new FSDataInputStreamWrapper(fs, this.getPath(), doDropBehind, readahead);
312      status = fs.getFileStatus(initialPath);
313    }
314    long length = status.getLen();
315    ReaderContextBuilder contextBuilder =
316      new ReaderContextBuilder().withInputStreamWrapper(in).withFileSize(length)
317        .withPrimaryReplicaReader(this.primaryReplica).withReaderType(type).withFileSystem(fs);
318    if (this.reference != null) {
319      contextBuilder.withFilePath(this.getPath());
320    } else {
321      contextBuilder.withFilePath(status.getPath());
322    }
323    return contextBuilder.build();
324  }
325
326  /**
327   * Compute the HDFS Block Distribution for this StoreFile
328   */
329  public HDFSBlocksDistribution computeHDFSBlocksDistribution(final FileSystem fs)
330    throws IOException {
331    // guard against the case where we get the FileStatus from link, but by the time we
332    // call compute the file is moved again
333    if (this.link != null) {
334      FileNotFoundException exToThrow = null;
335      for (int i = 0; i < this.link.getLocations().length; i++) {
336        try {
337          return computeHDFSBlocksDistributionInternal(fs);
338        } catch (FileNotFoundException ex) {
339          // try the other location
340          exToThrow = ex;
341        }
342      }
343      throw exToThrow;
344    } else {
345      return computeHDFSBlocksDistributionInternal(fs);
346    }
347  }
348
349  private HDFSBlocksDistribution computeHDFSBlocksDistributionInternal(final FileSystem fs)
350    throws IOException {
351    FileStatus status = getReferencedFileStatus(fs);
352    if (this.reference != null) {
353      return computeRefFileHDFSBlockDistribution(fs, reference, status);
354    } else {
355      return FSUtils.computeHDFSBlocksDistribution(fs, status, 0, status.getLen());
356    }
357  }
358
359  /**
360   * Get the {@link FileStatus} of the file referenced by this StoreFileInfo
361   * @param fs The current file system to use.
362   * @return The {@link FileStatus} of the file referenced by this StoreFileInfo
363   */
364  public FileStatus getReferencedFileStatus(final FileSystem fs) throws IOException {
365    FileStatus status;
366    if (this.reference != null) {
367      if (this.link != null) {
368        FileNotFoundException exToThrow = null;
369        for (int i = 0; i < this.link.getLocations().length; i++) {
370          // HFileLink Reference
371          try {
372            return link.getFileStatus(fs);
373          } catch (FileNotFoundException ex) {
374            // try the other location
375            exToThrow = ex;
376          }
377        }
378        throw exToThrow;
379      } else {
380        // HFile Reference
381        Path referencePath = getReferredToFile(this.getPath());
382        status = fs.getFileStatus(referencePath);
383      }
384    } else {
385      if (this.link != null) {
386        FileNotFoundException exToThrow = null;
387        for (int i = 0; i < this.link.getLocations().length; i++) {
388          // HFileLink
389          try {
390            return link.getFileStatus(fs);
391          } catch (FileNotFoundException ex) {
392            // try the other location
393            exToThrow = ex;
394          }
395        }
396        throw exToThrow;
397      } else {
398        status = fs.getFileStatus(initialPath);
399      }
400    }
401    return status;
402  }
403
404  /** Returns The {@link Path} of the file */
405  public Path getPath() {
406    return initialPath;
407  }
408
409  /** Returns The {@link FileStatus} of the file */
410  public FileStatus getFileStatus() throws IOException {
411    return getReferencedFileStatus(fs);
412  }
413
414  /** Returns Get the modification time of the file. */
415  public long getModificationTime() throws IOException {
416    return getFileStatus().getModificationTime();
417  }
418
419  @Override
420  public String toString() {
421    return this.getPath()
422      + (isReference() ? "->" + getReferredToFile(this.getPath()) + "-" + reference : "");
423  }
424
425  /**
426   * @param path Path to check.
427   * @return True if the path has format of a HFile.
428   */
429  public static boolean isHFile(final Path path) {
430    return isHFile(path.getName());
431  }
432
433  public static boolean isHFile(final String fileName) {
434    Matcher m = HFILE_NAME_PATTERN.matcher(fileName);
435    return m.matches() && m.groupCount() > 0;
436  }
437
438  /**
439   * Checks if the file is a MOB file
440   * @param path path to a file
441   * @return true, if - yes, false otherwise
442   */
443  public static boolean isMobFile(final Path path) {
444    String fileName = path.getName();
445    String[] parts = fileName.split(MobUtils.SEP);
446    if (parts.length != 2) {
447      return false;
448    }
449    Matcher m = HFILE_NAME_PATTERN.matcher(parts[0]);
450    Matcher mm = HFILE_NAME_PATTERN.matcher(parts[1]);
451    return m.matches() && mm.matches();
452  }
453
454  /**
455   * Checks if the file is a MOB reference file, created by snapshot
456   * @param path path to a file
457   * @return true, if - yes, false otherwise
458   */
459  public static boolean isMobRefFile(final Path path) {
460    String fileName = path.getName();
461    int lastIndex = fileName.lastIndexOf(MobUtils.SEP);
462    if (lastIndex < 0) {
463      return false;
464    }
465    String[] parts = new String[2];
466    parts[0] = fileName.substring(0, lastIndex);
467    parts[1] = fileName.substring(lastIndex + 1);
468    String name = parts[0] + "." + parts[1];
469    Matcher m = REF_NAME_PATTERN.matcher(name);
470    return m.matches() && m.groupCount() > 1;
471  }
472
473  /**
474   * @param path Path to check.
475   * @return True if the path has format of a HStoreFile reference.
476   */
477  public static boolean isReference(final Path path) {
478    return isReference(path.getName());
479  }
480
481  /**
482   * @param name file name to check.
483   * @return True if the path has format of a HStoreFile reference.
484   */
485  public static boolean isReference(final String name) {
486    Matcher m = REF_NAME_PATTERN.matcher(name);
487    return m.matches() && m.groupCount() > 1;
488  }
489
490  /** Returns timestamp when this file was created (as returned by filesystem) */
491  public long getCreatedTimestamp() {
492    return createdTimestamp;
493  }
494
495  /*
496   * Return path to the file referred to by a Reference. Presumes a directory hierarchy of
497   * <code>${hbase.rootdir}/data/${namespace}/tablename/regionname/familyname</code>.
498   * @param p Path to a Reference file.
499   * @return Calculated path to parent region file.
500   * @throws IllegalArgumentException when path regex fails to match.
501   */
502  public static Path getReferredToFile(final Path p) {
503    Matcher m = REF_NAME_PATTERN.matcher(p.getName());
504    if (m == null || !m.matches()) {
505      LOG.warn("Failed match of store file name {}", p.toString());
506      throw new IllegalArgumentException("Failed match of store file name " + p.toString());
507    }
508
509    // Other region name is suffix on the passed Reference file name
510    String otherRegion = m.group(2);
511    // Tabledir is up two directories from where Reference was written.
512    Path tableDir = p.getParent().getParent().getParent();
513    String nameStrippedOfSuffix = m.group(1);
514    LOG.trace("reference {} to region={} hfile={}", p, otherRegion, nameStrippedOfSuffix);
515
516    // Build up new path with the referenced region in place of our current
517    // region in the reference path. Also strip regionname suffix from name.
518    return new Path(new Path(new Path(tableDir, otherRegion), p.getParent().getName()),
519      nameStrippedOfSuffix);
520  }
521
522  /*
523   * Return region and file name referred to by a Reference.
524   * @param referenceFile HFile name which is a Reference.
525   * @return Calculated referenced region and file name.
526   * @throws IllegalArgumentException when referenceFile regex fails to match.
527   */
528  public static Pair<String, String> getReferredToRegionAndFile(final String referenceFile) {
529    Matcher m = REF_NAME_PATTERN.matcher(referenceFile);
530    if (m == null || !m.matches()) {
531      LOG.warn("Failed match of store file name {}", referenceFile);
532      throw new IllegalArgumentException("Failed match of store file name " + referenceFile);
533    }
534    String referencedRegion = m.group(2);
535    String referencedFile = m.group(1);
536    LOG.trace("reference {} to region={} file={}", referenceFile, referencedRegion, referencedFile);
537    return new Pair<>(referencedRegion, referencedFile);
538  }
539
540  /**
541   * Validate the store file name.
542   * @param fileName name of the file to validate
543   * @return <tt>true</tt> if the file could be a valid store file, <tt>false</tt> otherwise
544   */
545  public static boolean validateStoreFileName(final String fileName) {
546    if (HFileLink.isHFileLink(fileName) || isReference(fileName)) {
547      return true;
548    }
549    return !fileName.contains("-");
550  }
551
552  /**
553   * Return if the specified file is a valid store file or not.
554   * @param fileStatus The {@link FileStatus} of the file
555   * @return <tt>true</tt> if the file is valid
556   */
557  public static boolean isValid(final FileStatus fileStatus) throws IOException {
558    final Path p = fileStatus.getPath();
559
560    if (fileStatus.isDirectory()) {
561      return false;
562    }
563
564    // Check for empty hfile. Should never be the case but can happen
565    // after data loss in hdfs for whatever reason (upgrade, etc.): HBASE-646
566    // NOTE: that the HFileLink is just a name, so it's an empty file.
567    if (!HFileLink.isHFileLink(p) && fileStatus.getLen() <= 0) {
568      LOG.warn("Skipping {} because it is empty. HBASE-646 DATA LOSS?", p);
569      return false;
570    }
571
572    return validateStoreFileName(p.getName());
573  }
574
575  /**
576   * helper function to compute HDFS blocks distribution of a given reference file.For reference
577   * file, we don't compute the exact value. We use some estimate instead given it might be good
578   * enough. we assume bottom part takes the first half of reference file, top part takes the second
579   * half of the reference file. This is just estimate, given midkey ofregion != midkey of HFile,
580   * also the number and size of keys vary. If this estimate isn't good enough, we can improve it
581   * later.
582   * @param fs        The FileSystem
583   * @param reference The reference
584   * @param status    The reference FileStatus
585   * @return HDFS blocks distribution
586   */
587  private static HDFSBlocksDistribution computeRefFileHDFSBlockDistribution(final FileSystem fs,
588    final Reference reference, final FileStatus status) throws IOException {
589    if (status == null) {
590      return null;
591    }
592
593    long start = 0;
594    long length = 0;
595
596    if (Reference.isTopFileRegion(reference.getFileRegion())) {
597      start = status.getLen() / 2;
598      length = status.getLen() - status.getLen() / 2;
599    } else {
600      start = 0;
601      length = status.getLen() / 2;
602    }
603    return FSUtils.computeHDFSBlocksDistribution(fs, status, start, length);
604  }
605
606  @Override
607  public boolean equals(Object that) {
608    if (this == that) {
609      return true;
610    }
611    if (that == null) {
612      return false;
613    }
614
615    if (!(that instanceof StoreFileInfo)) {
616      return false;
617    }
618
619    StoreFileInfo o = (StoreFileInfo) that;
620    if (initialPath != null && o.initialPath == null) {
621      return false;
622    }
623    if (initialPath == null && o.initialPath != null) {
624      return false;
625    }
626    if (initialPath != o.initialPath && initialPath != null && !initialPath.equals(o.initialPath)) {
627      return false;
628    }
629    if (reference != null && o.reference == null) {
630      return false;
631    }
632    if (reference == null && o.reference != null) {
633      return false;
634    }
635    if (reference != o.reference && reference != null && !reference.equals(o.reference)) {
636      return false;
637    }
638
639    if (link != null && o.link == null) {
640      return false;
641    }
642    if (link == null && o.link != null) {
643      return false;
644    }
645    if (link != o.link && link != null && !link.equals(o.link)) {
646      return false;
647    }
648
649    return true;
650  }
651
652  @Override
653  public int hashCode() {
654    int hash = 17;
655    hash = hash * 31 + ((reference == null) ? 0 : reference.hashCode());
656    hash = hash * 31 + ((initialPath == null) ? 0 : initialPath.hashCode());
657    hash = hash * 31 + ((link == null) ? 0 : link.hashCode());
658    return hash;
659  }
660
661  /**
662   * Return the active file name that contains the real data.
663   * <p>
664   * For referenced hfile, we will return the name of the reference file as it will be used to
665   * construct the StoreFileReader. And for linked hfile, we will return the name of the file being
666   * linked.
667   */
668  public String getActiveFileName() {
669    if (reference != null || link == null) {
670      return initialPath.getName();
671    } else {
672      return HFileLink.getReferencedHFileName(initialPath.getName());
673    }
674  }
675
676  FileSystem getFileSystem() {
677    return this.fs;
678  }
679
680  boolean isNoReadahead() {
681    return this.noReadahead;
682  }
683
684  HFileInfo getHFileInfo() {
685    return hfileInfo;
686  }
687
688  void initHDFSBlocksDistribution() throws IOException {
689    hdfsBlocksDistribution = computeHDFSBlocksDistribution(fs);
690  }
691
692  StoreFileReader preStoreFileReaderOpen(ReaderContext context, CacheConfig cacheConf)
693    throws IOException {
694    StoreFileReader reader = null;
695    if (this.coprocessorHost != null) {
696      reader = this.coprocessorHost.preStoreFileReaderOpen(fs, this.getPath(),
697        context.getInputStreamWrapper(), context.getFileSize(), cacheConf, reference);
698    }
699    return reader;
700  }
701
702  StoreFileReader postStoreFileReaderOpen(ReaderContext context, CacheConfig cacheConf,
703    StoreFileReader reader) throws IOException {
704    StoreFileReader res = reader;
705    if (this.coprocessorHost != null) {
706      res = this.coprocessorHost.postStoreFileReaderOpen(fs, this.getPath(),
707        context.getInputStreamWrapper(), context.getFileSize(), cacheConf, reference, reader);
708    }
709    return res;
710  }
711
712  public void initHFileInfo(ReaderContext context) throws IOException {
713    this.hfileInfo = new HFileInfo(context, conf);
714  }
715
716}