From 0a0d9310c3f61f1c971d993d7027bc5475d76920 Mon Sep 17 00:00:00 2001 From: ramkrishna Date: Fri, 1 Mar 2013 16:37:57 +0000 Subject: [PATCH] HBASE-7928 Scanning .META. with startRow and/or stopRow is not giving proper results (Ram) git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1451643 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/hadoop/hbase/client/HTable.java | 21 ++++++++++++ .../org/apache/hadoop/hbase/HConstants.java | 2 ++ .../apache/hadoop/hbase/client/TestAdmin.java | 32 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java index bbf5e78ce9f..d75483e83de 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java @@ -529,9 +529,30 @@ public class HTable implements HTableInterface { if (scan.getCaching() <= 0) { scan.setCaching(getScannerCaching()); } + if (Bytes.equals(this.getTableName(), HConstants.META_TABLE_NAME)) { + changeStartAndStopRowIfMeta(scan); + } + return new ClientScanner(getConfiguration(), scan, getTableName(), this.connection); } + private void changeStartAndStopRowIfMeta(final Scan scan) { + if (scan.getStartRow() != null && scan.getStartRow().length != 0 + && !isValidMetaTableRow(scan.getStartRow())) { + scan.setStartRow(Bytes.add(scan.getStartRow(), HConstants.META_ROW_DELIMITER_BYTES, + Bytes.toBytes(HConstants.ZEROES))); + } + if (scan.getStopRow() != null && scan.getStopRow().length != 0 + && !isValidMetaTableRow(scan.getStopRow())) { + scan.setStopRow(Bytes.add(scan.getStopRow(), HConstants.META_ROW_DELIMITER_BYTES, + Bytes.toBytes(HConstants.NINES))); + } + } + + private boolean isValidMetaTableRow(byte[] metaRow) { + return (com.google.common.primitives.Bytes + .indexOf(metaRow, HConstants.META_ROW_DELIMITER_BYTES) != -1); + } /** * {@inheritDoc} diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java index 44d968aeeb7..21a445fd6f7 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java @@ -358,6 +358,8 @@ public final class HConstants { /** delimiter used between portions of a region name */ public static final int META_ROW_DELIMITER = ','; + + public static final byte[] META_ROW_DELIMITER_BYTES = Bytes.toBytes(",,"); /** The catalog family as a string*/ public static final String CATALOG_FAMILY_STR = "info"; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java index 7909f9833b3..2a902ee3428 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java @@ -536,6 +536,38 @@ public class TestAdmin { assertTrue(regionList.size() == min || regionList.size() == max); } } + + @Test + public void testHBASE7928() throws Exception { + final byte[] tableName = Bytes.toBytes("a"); + final byte[] tableName1 = Bytes.toBytes("b"); + final byte[] tableName2 = Bytes.toBytes("c"); + try { + + TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close(); + + TEST_UTIL.createTable(tableName1, HConstants.CATALOG_FAMILY).close(); + + TEST_UTIL.createTable(tableName2, HConstants.CATALOG_FAMILY).close(); + while (!admin.isTableAvailable(tableName2)) { + Thread.sleep(1); + } + Scan s = new Scan(); + s.setStartRow(Bytes.toBytes("a1")); + s.setStopRow(Bytes.toBytes("b1")); + HTable table = new HTable(admin.getConfiguration(), HConstants.META_TABLE_NAME); + ResultScanner scanner = table.getScanner(s); + Result[] result = scanner.next(5); + assertEquals("Only one row should be selected", 1, result.length); + } finally { + admin.disableTable(tableName); + admin.deleteTable(tableName); + admin.disableTable(tableName1); + admin.deleteTable(tableName1); + admin.disableTable(tableName2); + admin.deleteTable(tableName2); + } + } @Test public void testCreateTableWithRegions() throws IOException, InterruptedException {