From 078cbdea493ea9d67683fdfec8c241d450282d21 Mon Sep 17 00:00:00 2001 From: Michael Stack Date: Wed, 12 Sep 2012 05:47:32 +0000 Subject: [PATCH] HBASE-5997 Fix concerns raised in HBASE-5922 related to HalfStoreFileReader git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1383788 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop/hbase/io/HalfStoreFileReader.java | 27 +++++++++++++++++-- .../hadoop/hbase/regionserver/HStore.java | 3 ++- .../hbase/io/TestHalfStoreFileReader.java | 3 +++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java index bc73d9c45ec..29f2cc8c00c 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java @@ -53,6 +53,10 @@ public class HalfStoreFileReader extends StoreFile.Reader { // This is the key we split around. Its the first possible entry on a row: // i.e. empty column and a timestamp of LATEST_TIMESTAMP. protected final byte [] splitkey; + + private byte[] firstKey = null; + + private boolean firstKeySeeked = false; /** * @param fs @@ -142,8 +146,11 @@ public class HalfStoreFileReader extends StoreFile.Reader { public boolean seekBefore(byte [] key, int offset, int length) throws IOException { if (top) { - if (getComparator().compare(key, offset, length, splitkey, 0, - splitkey.length) < 0) { + byte[] fk = getFirstKey(); + // This will be null when the file is empty in which we can not seekBefore to any key + if (fk == null) return false; + if (getComparator().compare(key, offset, length, fk, 0, + fk.length) <= 0) { return false; } } else { @@ -272,4 +279,20 @@ public class HalfStoreFileReader extends StoreFile.Reader { // Returns null to indicate file is not splitable. return null; } + + @Override + public byte[] getFirstKey() { + if (!firstKeySeeked) { + HFileScanner scanner = getScanner(true, true, false); + try { + if (scanner.seekTo()) { + this.firstKey = Bytes.toBytes(scanner.getKey()); + } + firstKeySeeked = true; + } catch (IOException e) { + LOG.warn("Failed seekTo first KV in the file", e); + } + } + return this.firstKey; + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HStore.java index b8bb95a25c3..31dcc6fc5a1 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HStore.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HStore.java @@ -1698,6 +1698,7 @@ public class HStore extends SchemaConfigured implements Store { } // TODO: Cache these keys rather than make each time? byte [] fk = r.getFirstKey(); + if (fk == null) return; KeyValue firstKV = KeyValue.createKeyValueFromKey(fk, 0, fk.length); byte [] lk = r.getLastKey(); KeyValue lastKV = KeyValue.createKeyValueFromKey(lk, 0, lk.length); @@ -1711,7 +1712,7 @@ public class HStore extends SchemaConfigured implements Store { firstOnRow = new KeyValue(lastKV.getRow(), HConstants.LATEST_TIMESTAMP); } // Get a scanner that caches blocks and that uses pread. - HFileScanner scanner = r.getHFileReader().getScanner(true, true, false); + HFileScanner scanner = r.getScanner(true, true, false); // Seek scanner. If can't seek it, return. if (!seekToScanner(scanner, firstOnRow, firstKV)) return; // If we found candidate on firstOnRow, just return. THIS WILL NEVER HAPPEN! diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/TestHalfStoreFileReader.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/TestHalfStoreFileReader.java index 36889ee041f..d655a6be48f 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/TestHalfStoreFileReader.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/TestHalfStoreFileReader.java @@ -194,6 +194,9 @@ public class TestHalfStoreFileReader { foundKeyValue = doTestOfSeekBefore(p, fs, bottom, items.get(1), cacheConf); assertEquals(items.get(0), foundKeyValue); + // Try to seek before the splitKey in the top file + foundKeyValue = doTestOfSeekBefore(p, fs, top, midKV, cacheConf); + assertNull(foundKeyValue); } private KeyValue doTestOfSeekBefore(Path p, FileSystem fs, Reference bottom, KeyValue seekBefore,