diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreFileInfo.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreFileInfo.java index 5eaab23fc6cf..94324b3ff1f3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreFileInfo.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreFileInfo.java @@ -52,6 +52,8 @@ public class StoreFileInfo { private static final Logger LOG = LoggerFactory.getLogger(StoreFileInfo.class); + private FileStatus localStatus = null; + /** * A non-capture group, for hfiles, so that this can be embedded. HFiles are uuid ([0-9a-z]+). * Bulk loaded hfiles has (_SeqId_[0-9]+_) has suffix. The mob del file has (_del) as suffix. @@ -155,13 +157,12 @@ private StoreFileInfo(final Configuration conf, final FileSystem fs, final FileS } else if (isHFile(p) || isMobFile(p) || isMobRefFile(p)) { // HFile if (fileStatus != null) { - this.createdTimestamp = fileStatus.getModificationTime(); - this.size = fileStatus.getLen(); + this.localStatus = fileStatus; } else { - FileStatus fStatus = fs.getFileStatus(initialPath); - this.createdTimestamp = fStatus.getModificationTime(); - this.size = fStatus.getLen(); + this.localStatus = loadAndCacheFileStatus(fs); } + this.createdTimestamp = localStatus.getModificationTime(); + this.size = localStatus.getLen(); this.reference = null; this.link = null; } else { @@ -169,6 +170,48 @@ private StoreFileInfo(final Configuration conf, final FileSystem fs, final FileS } } + private FileStatus loadAndCacheFileStatus(final FileSystem fs) throws IOException { + FileStatus status = null; + if (this.reference != null) { + if (this.link != null) { + for (int i = 0; i < this.link.getLocations().length; i++) { + // HFileLink Reference + try { + status = link.getFileStatus(fs); + } catch (FileNotFoundException ex) { + // try the other location + throw ex; + } + } + } else { + try{ + // HFile Reference + Path referencePath = getReferredToFile(this.getPath()); + status = fs.getFileStatus(referencePath); + } catch (FileNotFoundException ex) { + FileNotFoundException newFnfe = new FileNotFoundException(toString()); + newFnfe.initCause(ex); + throw newFnfe; + } + } + } else { + if (this.link != null) { + for (int i = 0; i < this.link.getLocations().length; i++) { + // HFileLink + try { + status = link.getFileStatus(fs); + } catch (FileNotFoundException ex) { + // try the other location + throw ex; + } + } + } else { + status = fs.getFileStatus(initialPath); + } + } + return status; + } + /** * Create a Store File Info * @param conf the {@link Configuration} to use @@ -187,7 +230,7 @@ public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileSt * @param fileStatus The {@link FileStatus} of the file */ public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus, - final HFileLink link) { + final HFileLink link) throws IOException { this(conf, fs, fileStatus, null, link); } @@ -199,7 +242,7 @@ public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileSt * @param reference The reference instance */ public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus, - final Reference reference) { + final Reference reference) throws IOException { this(conf, fs, fileStatus, reference, null); } @@ -212,14 +255,15 @@ public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileSt * @param link The link instance */ public StoreFileInfo(final Configuration conf, final FileSystem fs, final FileStatus fileStatus, - final Reference reference, final HFileLink link) { + final Reference reference, final HFileLink link) throws IOException { this.fs = fs; this.conf = conf; this.primaryReplica = false; - this.initialPath = (fileStatus == null) ? null : fileStatus.getPath(); - this.createdTimestamp = (fileStatus == null) ? 0 : fileStatus.getModificationTime(); this.reference = reference; this.link = link; + this.initialPath = (fileStatus == null) ? null : fileStatus.getPath(); + this.createdTimestamp = (fileStatus == null) ? 0 : fileStatus.getModificationTime(); + this.localStatus = (fileStatus == null) ? loadAndCacheFileStatus(fs) : fileStatus; this.noReadahead = this.conf.getBoolean(STORE_FILE_READER_NO_READAHEAD, DEFAULT_STORE_FILE_READER_NO_READAHEAD); } @@ -286,7 +330,6 @@ ReaderContext createReaderContext(boolean doDropBehind, long readahead, ReaderTy if (this.link != null) { // HFileLink in = new FSDataInputStreamWrapper(fs, this.link, doDropBehind, readahead); - status = this.link.getFileStatus(fs); } else if (this.reference != null) { // HFile Reference Path referencePath = getReferredToFile(this.getPath()); @@ -300,11 +343,10 @@ ReaderContext createReaderContext(boolean doDropBehind, long readahead, ReaderTy newFnfe.initCause(fnfe); throw newFnfe; } - status = fs.getFileStatus(referencePath); } else { in = new FSDataInputStreamWrapper(fs, this.getPath(), doDropBehind, readahead); - status = fs.getFileStatus(initialPath); } + status = getFileStatus(); long length = status.getLen(); ReaderContextBuilder contextBuilder = new ReaderContextBuilder().withInputStreamWrapper(in).withFileSize(length) @@ -356,43 +398,10 @@ private HDFSBlocksDistribution computeHDFSBlocksDistributionInternal(final FileS * @return The {@link FileStatus} of the file referenced by this StoreFileInfo */ public FileStatus getReferencedFileStatus(final FileSystem fs) throws IOException { - FileStatus status; - if (this.reference != null) { - if (this.link != null) { - FileNotFoundException exToThrow = null; - for (int i = 0; i < this.link.getLocations().length; i++) { - // HFileLink Reference - try { - return link.getFileStatus(fs); - } catch (FileNotFoundException ex) { - // try the other location - exToThrow = ex; - } - } - throw exToThrow; - } else { - // HFile Reference - Path referencePath = getReferredToFile(this.getPath()); - status = fs.getFileStatus(referencePath); - } - } else { - if (this.link != null) { - FileNotFoundException exToThrow = null; - for (int i = 0; i < this.link.getLocations().length; i++) { - // HFileLink - try { - return link.getFileStatus(fs); - } catch (FileNotFoundException ex) { - // try the other location - exToThrow = ex; - } - } - throw exToThrow; - } else { - status = fs.getFileStatus(initialPath); - } + if(null == this.localStatus) { + return loadAndCacheFileStatus(fs); } - return status; + return this.localStatus; } /** @return The {@link Path} of the file */ diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFileInfo.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFileInfo.java index ea2d473cbb3f..ac37e8239c25 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFileInfo.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFileInfo.java @@ -25,6 +25,7 @@ import java.io.IOException; import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseTestingUtility; @@ -90,9 +91,9 @@ public void testEqualsWithLink() throws IOException { new Path(mob, "f1"), new Path(archive, "f1")); StoreFileInfo info1 = new StoreFileInfo(TEST_UTIL.getConfiguration(), - TEST_UTIL.getTestFileSystem(), null, link1); + TEST_UTIL.getTestFileSystem(), new FileStatus(), link1); StoreFileInfo info2 = new StoreFileInfo(TEST_UTIL.getConfiguration(), - TEST_UTIL.getTestFileSystem(), null, link2); + TEST_UTIL.getTestFileSystem(), new FileStatus(), link2); assertEquals(info1, info2); assertEquals(info1.hashCode(), info2.hashCode()); @@ -104,8 +105,8 @@ public void testOpenErrorMessageHFileLink() throws IOException, IllegalStateExce // Try to open nonsense hfilelink. Make sure exception is from HFileLink. Path p = new Path("/hbase/test/0123/cf/testtb=4567-abcd"); try (FileSystem fs = FileSystem.get(TEST_UTIL.getConfiguration())) { - StoreFileInfo sfi = new StoreFileInfo(TEST_UTIL.getConfiguration(), fs, p, true); try { + StoreFileInfo sfi = new StoreFileInfo(TEST_UTIL.getConfiguration(), fs, p, true); ReaderContext context = sfi.createReaderContext(false, 1000, ReaderType.PREAD); sfi.createReader(context, null); throw new IllegalStateException(); @@ -124,8 +125,8 @@ public void testOpenErrorMessageReference() throws IOException { fs.mkdirs(p.getParent()); Reference r = Reference.createBottomReference(HConstants.EMPTY_START_ROW); r.write(fs, p); - StoreFileInfo sfi = new StoreFileInfo(TEST_UTIL.getConfiguration(), fs, p, true); try { + StoreFileInfo sfi = new StoreFileInfo(TEST_UTIL.getConfiguration(), fs, p, true); ReaderContext context = sfi.createReaderContext(false, 1000, ReaderType.PREAD); sfi.createReader(context, null); throw new IllegalStateException();