You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ap...@apache.org on 2017/06/07 00:13:42 UTC
[1/4] hbase git commit: HBASE-18066: Get with closest_row_before on
hbase:meta can return empty Cell during region merge/split
Repository: hbase
Updated Branches:
refs/heads/branch-1 ea3075e7f -> 9c1efc9f9
refs/heads/branch-1.1 70789c733 -> b9ff18e94
refs/heads/branch-1.2 b9d8f3b85 -> 04bbdc835
refs/heads/branch-1.3 041f14341 -> 5812e41bc
HBASE-18066: Get with closest_row_before on hbase:meta can return empty Cell during region merge/split
Signed-off-by: Andrew Purtell <ap...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/5812e41b
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/5812e41b
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/5812e41b
Branch: refs/heads/branch-1.3
Commit: 5812e41bca63463798c2f9beaeb30377291a4419
Parents: 041f143
Author: huzheng <op...@gmail.com>
Authored: Wed May 24 16:46:06 2017 +0800
Committer: Andrew Purtell <ap...@apache.org>
Committed: Tue Jun 6 14:16:49 2017 -0700
----------------------------------------------------------------------
.../hadoop/hbase/regionserver/HRegion.java | 36 +++-
.../TestFromClientGetWithClosestRowBefore.java | 164 +++++++++++++++++++
2 files changed, 191 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/5812e41b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
index a603910..61d532b 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
@@ -117,6 +117,7 @@ import org.apache.hadoop.hbase.filter.ByteArrayComparable;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.FilterWrapper;
import org.apache.hadoop.hbase.filter.IncompatibleFilterException;
+import org.apache.hadoop.hbase.filter.PrefixFilter;
import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.io.hfile.BlockCache;
@@ -2602,15 +2603,13 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
startRegionOperation(Operation.GET);
this.readRequestsCount.increment();
try {
- Store store = getStore(family);
- // get the closest key. (HStore.getRowKeyAtOrBefore can return null)
- Cell key = store.getRowKeyAtOrBefore(row);
Result result = null;
- if (key != null) {
- Get get = new Get(CellUtil.cloneRow(key));
- get.addFamily(family);
- result = get(get);
- }
+ Get get = new Get(row);
+ get.addFamily(family);
+ get.setClosestRowBefore(true);
+ result = get(get);
+ // for compatibility
+ result = result.isEmpty() ? null : result;
if (coprocessorHost != null) {
coprocessorHost.postGetClosestRowBefore(row, family, result);
}
@@ -7010,6 +7009,20 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
return get(get, withCoprocessor, HConstants.NO_NONCE, HConstants.NO_NONCE);
}
+ private Scan buildScanForGetWithClosestRowBefore(Get get) throws IOException {
+ Scan scan = new Scan().setStartRow(get.getRow())
+ .addFamily(get.getFamilyMap().keySet().iterator().next()).setReversed(true)
+ .setStopRow(HConstants.EMPTY_END_ROW);
+ if (this.getRegionInfo().isMetaRegion()) {
+ int delimiterIdx =
+ KeyValue.getDelimiter(get.getRow(), 0, get.getRow().length, HConstants.DELIMITER);
+ if (delimiterIdx >= 0) {
+ scan.setFilter(new PrefixFilter(Bytes.copy(get.getRow(), 0, delimiterIdx + 1)));
+ }
+ }
+ return scan;
+ }
+
@Override
public List<Cell> get(Get get, boolean withCoprocessor, long nonceGroup, long nonce)
throws IOException {
@@ -7022,7 +7035,12 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
}
}
long before = EnvironmentEdgeManager.currentTime();
- Scan scan = new Scan(get);
+ Scan scan;
+ if (get.isClosestRowBefore()) {
+ scan = buildScanForGetWithClosestRowBefore(get);
+ } else {
+ scan = new Scan(get);
+ }
RegionScanner scanner = null;
try {
http://git-wip-us.apache.org/repos/asf/hbase/blob/5812e41b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
new file mode 100644
index 0000000..781977c
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.IOException;
+import java.util.Random;
+
+@Category({ MediumTests.class })
+public class TestFromClientGetWithClosestRowBefore {
+
+ private static final Logger LOG = Logger.getLogger(TestFromClientGetWithClosestRowBefore.class);
+ private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
+ private static Configuration CONF;
+ private static final TableName TEST_TABLE = TableName.valueOf("test_table");
+ private static final byte[] COLUMN_FAMILY = Bytes.toBytes("f1");
+ private static final Random RANDOM = new Random();
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ CONF = UTIL.getConfiguration();
+ UTIL.startMiniCluster();
+ }
+
+ @AfterClass
+ public static void teardown() throws Exception {
+ UTIL.shutdownMiniCluster();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
+ HColumnDescriptor hcd = new HColumnDescriptor(COLUMN_FAMILY);
+ htd.addFamily(hcd);
+
+ UTIL.getHBaseAdmin().createTable(htd);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ for (HTableDescriptor htd : UTIL.getHBaseAdmin().listTables()) {
+ UTIL.deleteTable(htd.getTableName());
+ }
+ }
+
+ @Test
+ public void testGetWithClosestRowBeforeWhenSplitRegion() throws Exception {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(100);
+ UTIL.getHBaseAdmin().split(TEST_TABLE);
+ } catch (Exception e) {
+ LOG.error("split region failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = 0; i < 1000; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, data);
+ table.put(put);
+ }
+ }
+ try (Table table = conn.getTable(TableName.META_TABLE_NAME)) {
+ t.start();
+ for (int i = 0; i < 10000; i++) {
+ Get get = new Get(Bytes.toBytes(TEST_TABLE + ",,:")).addFamily(Bytes.toBytes("info"))
+ .setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testClosestRowIsLatestPutRow() throws IOException {
+ final int[] initialRowkeys = new int[] { 1, 1000 };
+
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ // a huge value to slow down transaction committing.
+ byte[] value = new byte[512 * 1024];
+ for (int i = 0; i < value.length; i++) {
+ value[i] = (byte) RANDOM.nextInt(256);
+ }
+
+ // Put rowKey= 2,3,4,...,(initialRowkeys[1]-1) into table, let the rowkey returned by a
+ // Get with closestRowBefore to be exactly the latest put rowkey.
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = initialRowkeys[0] + 1; i < initialRowkeys[1]; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, value);
+ table.put(put);
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Put huge value into table failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+
+ // Put the boundary into table firstly.
+ for (int i = 0; i < initialRowkeys.length; i++) {
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[i]));
+ Put put = new Put(rowKey).addColumn(COLUMN_FAMILY, null, rowKey);
+ table.put(put);
+ }
+
+ t.start();
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[1] - 1));
+ for (int i = 0; i < 1000; i++) {
+ Get get = new Get(rowKey).addFamily(COLUMN_FAMILY).setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+}
[4/4] hbase git commit: HBASE-18066: Get with closest_row_before on
hbase:meta can return empty Cell during region merge/split
Posted by ap...@apache.org.
HBASE-18066: Get with closest_row_before on hbase:meta can return empty Cell during region merge/split
Signed-off-by: Andrew Purtell <ap...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/9c1efc9f
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/9c1efc9f
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/9c1efc9f
Branch: refs/heads/branch-1
Commit: 9c1efc9f9d11d6b59b54052da4a77f981102931b
Parents: ea3075e
Author: huzheng <op...@gmail.com>
Authored: Tue May 23 16:05:16 2017 +0800
Committer: Andrew Purtell <ap...@apache.org>
Committed: Tue Jun 6 17:13:16 2017 -0700
----------------------------------------------------------------------
.../hadoop/hbase/regionserver/HRegion.java | 36 +++-
.../TestFromClientGetWithClosestRowBefore.java | 164 +++++++++++++++++++
2 files changed, 191 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/9c1efc9f/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
index cea7c6f..fc737a9 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
@@ -136,6 +136,7 @@ import org.apache.hadoop.hbase.filter.ByteArrayComparable;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.FilterWrapper;
import org.apache.hadoop.hbase.filter.IncompatibleFilterException;
+import org.apache.hadoop.hbase.filter.PrefixFilter;
import org.apache.hadoop.hbase.io.HFileLink;
import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.io.TimeRange;
@@ -2726,15 +2727,13 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
startRegionOperation(Operation.GET);
this.readRequestsCount.increment();
try {
- Store store = getStore(family);
- // get the closest key. (HStore.getRowKeyAtOrBefore can return null)
- Cell key = store.getRowKeyAtOrBefore(row);
Result result = null;
- if (key != null) {
- Get get = new Get(CellUtil.cloneRow(key));
- get.addFamily(family);
- result = get(get);
- }
+ Get get = new Get(row);
+ get.addFamily(family);
+ get.setClosestRowBefore(true);
+ result = get(get);
+ // for compatibility
+ result = result.isEmpty() ? null : result;
if (coprocessorHost != null) {
coprocessorHost.postGetClosestRowBefore(row, family, result);
}
@@ -7224,6 +7223,20 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
return get(get, withCoprocessor, HConstants.NO_NONCE, HConstants.NO_NONCE);
}
+ private Scan buildScanForGetWithClosestRowBefore(Get get) throws IOException {
+ Scan scan = new Scan().withStartRow(get.getRow())
+ .addFamily(get.getFamilyMap().keySet().iterator().next()).setReversed(true)
+ .withStopRow(HConstants.EMPTY_END_ROW, false).setLimit(1);
+ if (this.getRegionInfo().isMetaRegion()) {
+ int delimiterIdx =
+ KeyValue.getDelimiter(get.getRow(), 0, get.getRow().length, HConstants.DELIMITER);
+ if (delimiterIdx >= 0) {
+ scan.setFilter(new PrefixFilter(Bytes.copy(get.getRow(), 0, delimiterIdx + 1)));
+ }
+ }
+ return scan;
+ }
+
@Override
public List<Cell> get(Get get, boolean withCoprocessor, long nonceGroup, long nonce)
throws IOException {
@@ -7236,7 +7249,12 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
}
}
long before = EnvironmentEdgeManager.currentTime();
- Scan scan = new Scan(get);
+ Scan scan;
+ if (get.isClosestRowBefore()) {
+ scan = buildScanForGetWithClosestRowBefore(get);
+ } else {
+ scan = new Scan(get);
+ }
RegionScanner scanner = null;
try {
http://git-wip-us.apache.org/repos/asf/hbase/blob/9c1efc9f/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
new file mode 100644
index 0000000..781977c
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.IOException;
+import java.util.Random;
+
+@Category({ MediumTests.class })
+public class TestFromClientGetWithClosestRowBefore {
+
+ private static final Logger LOG = Logger.getLogger(TestFromClientGetWithClosestRowBefore.class);
+ private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
+ private static Configuration CONF;
+ private static final TableName TEST_TABLE = TableName.valueOf("test_table");
+ private static final byte[] COLUMN_FAMILY = Bytes.toBytes("f1");
+ private static final Random RANDOM = new Random();
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ CONF = UTIL.getConfiguration();
+ UTIL.startMiniCluster();
+ }
+
+ @AfterClass
+ public static void teardown() throws Exception {
+ UTIL.shutdownMiniCluster();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
+ HColumnDescriptor hcd = new HColumnDescriptor(COLUMN_FAMILY);
+ htd.addFamily(hcd);
+
+ UTIL.getHBaseAdmin().createTable(htd);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ for (HTableDescriptor htd : UTIL.getHBaseAdmin().listTables()) {
+ UTIL.deleteTable(htd.getTableName());
+ }
+ }
+
+ @Test
+ public void testGetWithClosestRowBeforeWhenSplitRegion() throws Exception {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(100);
+ UTIL.getHBaseAdmin().split(TEST_TABLE);
+ } catch (Exception e) {
+ LOG.error("split region failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = 0; i < 1000; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, data);
+ table.put(put);
+ }
+ }
+ try (Table table = conn.getTable(TableName.META_TABLE_NAME)) {
+ t.start();
+ for (int i = 0; i < 10000; i++) {
+ Get get = new Get(Bytes.toBytes(TEST_TABLE + ",,:")).addFamily(Bytes.toBytes("info"))
+ .setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testClosestRowIsLatestPutRow() throws IOException {
+ final int[] initialRowkeys = new int[] { 1, 1000 };
+
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ // a huge value to slow down transaction committing.
+ byte[] value = new byte[512 * 1024];
+ for (int i = 0; i < value.length; i++) {
+ value[i] = (byte) RANDOM.nextInt(256);
+ }
+
+ // Put rowKey= 2,3,4,...,(initialRowkeys[1]-1) into table, let the rowkey returned by a
+ // Get with closestRowBefore to be exactly the latest put rowkey.
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = initialRowkeys[0] + 1; i < initialRowkeys[1]; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, value);
+ table.put(put);
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Put huge value into table failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+
+ // Put the boundary into table firstly.
+ for (int i = 0; i < initialRowkeys.length; i++) {
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[i]));
+ Put put = new Put(rowKey).addColumn(COLUMN_FAMILY, null, rowKey);
+ table.put(put);
+ }
+
+ t.start();
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[1] - 1));
+ for (int i = 0; i < 1000; i++) {
+ Get get = new Get(rowKey).addFamily(COLUMN_FAMILY).setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+}
[2/4] hbase git commit: HBASE-18066: Get with closest_row_before on
hbase:meta can return empty Cell during region merge/split
Posted by ap...@apache.org.
HBASE-18066: Get with closest_row_before on hbase:meta can return empty Cell during region merge/split
Signed-off-by: Andrew Purtell <ap...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/04bbdc83
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/04bbdc83
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/04bbdc83
Branch: refs/heads/branch-1.2
Commit: 04bbdc835c6a875576290eca1a5a1ad1d6f7577c
Parents: b9d8f3b
Author: huzheng <op...@gmail.com>
Authored: Wed May 24 16:46:06 2017 +0800
Committer: Andrew Purtell <ap...@apache.org>
Committed: Tue Jun 6 15:50:41 2017 -0700
----------------------------------------------------------------------
.../hadoop/hbase/regionserver/HRegion.java | 36 +++-
.../TestFromClientGetWithClosestRowBefore.java | 164 +++++++++++++++++++
2 files changed, 191 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/04bbdc83/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
index 7006dbc..d0d457f 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
@@ -117,6 +117,7 @@ import org.apache.hadoop.hbase.filter.ByteArrayComparable;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.FilterWrapper;
import org.apache.hadoop.hbase.filter.IncompatibleFilterException;
+import org.apache.hadoop.hbase.filter.PrefixFilter;
import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.io.hfile.BlockCache;
@@ -2518,15 +2519,13 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
startRegionOperation(Operation.GET);
this.readRequestsCount.increment();
try {
- Store store = getStore(family);
- // get the closest key. (HStore.getRowKeyAtOrBefore can return null)
- Cell key = store.getRowKeyAtOrBefore(row);
Result result = null;
- if (key != null) {
- Get get = new Get(CellUtil.cloneRow(key));
- get.addFamily(family);
- result = get(get);
- }
+ Get get = new Get(row);
+ get.addFamily(family);
+ get.setClosestRowBefore(true);
+ result = get(get);
+ // for compatibility
+ result = result.isEmpty() ? null : result;
if (coprocessorHost != null) {
coprocessorHost.postGetClosestRowBefore(row, family, result);
}
@@ -6811,6 +6810,20 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
return Result.create(results, get.isCheckExistenceOnly() ? !results.isEmpty() : null, stale);
}
+ private Scan buildScanForGetWithClosestRowBefore(Get get) throws IOException {
+ Scan scan = new Scan().setStartRow(get.getRow())
+ .addFamily(get.getFamilyMap().keySet().iterator().next()).setReversed(true)
+ .setStopRow(HConstants.EMPTY_END_ROW);
+ if (this.getRegionInfo().isMetaRegion()) {
+ int delimiterIdx =
+ KeyValue.getDelimiter(get.getRow(), 0, get.getRow().length, HConstants.DELIMITER);
+ if (delimiterIdx >= 0) {
+ scan.setFilter(new PrefixFilter(Bytes.copy(get.getRow(), 0, delimiterIdx + 1)));
+ }
+ }
+ return scan;
+ }
+
@Override
public List<Cell> get(Get get, boolean withCoprocessor) throws IOException {
@@ -6823,7 +6836,12 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
}
}
- Scan scan = new Scan(get);
+ Scan scan;
+ if (get.isClosestRowBefore()) {
+ scan = buildScanForGetWithClosestRowBefore(get);
+ } else {
+ scan = new Scan(get);
+ }
RegionScanner scanner = null;
try {
http://git-wip-us.apache.org/repos/asf/hbase/blob/04bbdc83/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
new file mode 100644
index 0000000..781977c
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.IOException;
+import java.util.Random;
+
+@Category({ MediumTests.class })
+public class TestFromClientGetWithClosestRowBefore {
+
+ private static final Logger LOG = Logger.getLogger(TestFromClientGetWithClosestRowBefore.class);
+ private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
+ private static Configuration CONF;
+ private static final TableName TEST_TABLE = TableName.valueOf("test_table");
+ private static final byte[] COLUMN_FAMILY = Bytes.toBytes("f1");
+ private static final Random RANDOM = new Random();
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ CONF = UTIL.getConfiguration();
+ UTIL.startMiniCluster();
+ }
+
+ @AfterClass
+ public static void teardown() throws Exception {
+ UTIL.shutdownMiniCluster();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
+ HColumnDescriptor hcd = new HColumnDescriptor(COLUMN_FAMILY);
+ htd.addFamily(hcd);
+
+ UTIL.getHBaseAdmin().createTable(htd);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ for (HTableDescriptor htd : UTIL.getHBaseAdmin().listTables()) {
+ UTIL.deleteTable(htd.getTableName());
+ }
+ }
+
+ @Test
+ public void testGetWithClosestRowBeforeWhenSplitRegion() throws Exception {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(100);
+ UTIL.getHBaseAdmin().split(TEST_TABLE);
+ } catch (Exception e) {
+ LOG.error("split region failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = 0; i < 1000; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, data);
+ table.put(put);
+ }
+ }
+ try (Table table = conn.getTable(TableName.META_TABLE_NAME)) {
+ t.start();
+ for (int i = 0; i < 10000; i++) {
+ Get get = new Get(Bytes.toBytes(TEST_TABLE + ",,:")).addFamily(Bytes.toBytes("info"))
+ .setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testClosestRowIsLatestPutRow() throws IOException {
+ final int[] initialRowkeys = new int[] { 1, 1000 };
+
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ // a huge value to slow down transaction committing.
+ byte[] value = new byte[512 * 1024];
+ for (int i = 0; i < value.length; i++) {
+ value[i] = (byte) RANDOM.nextInt(256);
+ }
+
+ // Put rowKey= 2,3,4,...,(initialRowkeys[1]-1) into table, let the rowkey returned by a
+ // Get with closestRowBefore to be exactly the latest put rowkey.
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = initialRowkeys[0] + 1; i < initialRowkeys[1]; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, value);
+ table.put(put);
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Put huge value into table failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+
+ // Put the boundary into table firstly.
+ for (int i = 0; i < initialRowkeys.length; i++) {
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[i]));
+ Put put = new Put(rowKey).addColumn(COLUMN_FAMILY, null, rowKey);
+ table.put(put);
+ }
+
+ t.start();
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[1] - 1));
+ for (int i = 0; i < 1000; i++) {
+ Get get = new Get(rowKey).addFamily(COLUMN_FAMILY).setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+}
[3/4] hbase git commit: HBASE-18066: Get with closest_row_before on
hbase:meta can return empty Cell during region merge/split
Posted by ap...@apache.org.
HBASE-18066: Get with closest_row_before on hbase:meta can return empty Cell during region merge/split
Signed-off-by: Andrew Purtell <ap...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/b9ff18e9
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/b9ff18e9
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/b9ff18e9
Branch: refs/heads/branch-1.1
Commit: b9ff18e94e614ec83afaf0216783b7a27dec9a62
Parents: 70789c7
Author: huzheng <op...@gmail.com>
Authored: Wed May 24 16:46:06 2017 +0800
Committer: Andrew Purtell <ap...@apache.org>
Committed: Tue Jun 6 16:00:01 2017 -0700
----------------------------------------------------------------------
.../hadoop/hbase/regionserver/HRegion.java | 36 +++-
.../TestFromClientGetWithClosestRowBefore.java | 164 +++++++++++++++++++
2 files changed, 191 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/b9ff18e9/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
index 3263873..ccb6a5c 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
@@ -118,6 +118,7 @@ import org.apache.hadoop.hbase.filter.ByteArrayComparable;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.FilterWrapper;
import org.apache.hadoop.hbase.filter.IncompatibleFilterException;
+import org.apache.hadoop.hbase.filter.PrefixFilter;
import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.io.hfile.BlockCache;
@@ -2493,15 +2494,13 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
startRegionOperation(Operation.GET);
this.readRequestsCount.increment();
try {
- Store store = getStore(family);
- // get the closest key. (HStore.getRowKeyAtOrBefore can return null)
- Cell key = store.getRowKeyAtOrBefore(row);
Result result = null;
- if (key != null) {
- Get get = new Get(CellUtil.cloneRow(key));
- get.addFamily(family);
- result = get(get);
- }
+ Get get = new Get(row);
+ get.addFamily(family);
+ get.setClosestRowBefore(true);
+ result = get(get);
+ // for compatibility
+ result = result.isEmpty() ? null : result;
if (coprocessorHost != null) {
coprocessorHost.postGetClosestRowBefore(row, family, result);
}
@@ -6582,6 +6581,20 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
return Result.create(results, get.isCheckExistenceOnly() ? !results.isEmpty() : null, stale);
}
+ private Scan buildScanForGetWithClosestRowBefore(Get get) throws IOException {
+ Scan scan = new Scan().setStartRow(get.getRow())
+ .addFamily(get.getFamilyMap().keySet().iterator().next()).setReversed(true)
+ .setStopRow(HConstants.EMPTY_END_ROW);
+ if (this.getRegionInfo().isMetaRegion()) {
+ int delimiterIdx =
+ KeyValue.getDelimiter(get.getRow(), 0, get.getRow().length, HConstants.DELIMITER);
+ if (delimiterIdx >= 0) {
+ scan.setFilter(new PrefixFilter(Bytes.copy(get.getRow(), 0, delimiterIdx + 1)));
+ }
+ }
+ return scan;
+ }
+
@Override
public List<Cell> get(Get get, boolean withCoprocessor) throws IOException {
@@ -6594,7 +6607,12 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
}
}
- Scan scan = new Scan(get);
+ Scan scan;
+ if (get.isClosestRowBefore()) {
+ scan = buildScanForGetWithClosestRowBefore(get);
+ } else {
+ scan = new Scan(get);
+ }
RegionScanner scanner = null;
try {
http://git-wip-us.apache.org/repos/asf/hbase/blob/b9ff18e9/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
new file mode 100644
index 0000000..781977c
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFromClientGetWithClosestRowBefore.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.IOException;
+import java.util.Random;
+
+@Category({ MediumTests.class })
+public class TestFromClientGetWithClosestRowBefore {
+
+ private static final Logger LOG = Logger.getLogger(TestFromClientGetWithClosestRowBefore.class);
+ private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
+ private static Configuration CONF;
+ private static final TableName TEST_TABLE = TableName.valueOf("test_table");
+ private static final byte[] COLUMN_FAMILY = Bytes.toBytes("f1");
+ private static final Random RANDOM = new Random();
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ CONF = UTIL.getConfiguration();
+ UTIL.startMiniCluster();
+ }
+
+ @AfterClass
+ public static void teardown() throws Exception {
+ UTIL.shutdownMiniCluster();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
+ HColumnDescriptor hcd = new HColumnDescriptor(COLUMN_FAMILY);
+ htd.addFamily(hcd);
+
+ UTIL.getHBaseAdmin().createTable(htd);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ for (HTableDescriptor htd : UTIL.getHBaseAdmin().listTables()) {
+ UTIL.deleteTable(htd.getTableName());
+ }
+ }
+
+ @Test
+ public void testGetWithClosestRowBeforeWhenSplitRegion() throws Exception {
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(100);
+ UTIL.getHBaseAdmin().split(TEST_TABLE);
+ } catch (Exception e) {
+ LOG.error("split region failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = 0; i < 1000; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, data);
+ table.put(put);
+ }
+ }
+ try (Table table = conn.getTable(TableName.META_TABLE_NAME)) {
+ t.start();
+ for (int i = 0; i < 10000; i++) {
+ Get get = new Get(Bytes.toBytes(TEST_TABLE + ",,:")).addFamily(Bytes.toBytes("info"))
+ .setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testClosestRowIsLatestPutRow() throws IOException {
+ final int[] initialRowkeys = new int[] { 1, 1000 };
+
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ // a huge value to slow down transaction committing.
+ byte[] value = new byte[512 * 1024];
+ for (int i = 0; i < value.length; i++) {
+ value[i] = (byte) RANDOM.nextInt(256);
+ }
+
+ // Put rowKey= 2,3,4,...,(initialRowkeys[1]-1) into table, let the rowkey returned by a
+ // Get with closestRowBefore to be exactly the latest put rowkey.
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+ for (int i = initialRowkeys[0] + 1; i < initialRowkeys[1]; i++) {
+ byte[] data = Bytes.toBytes(String.format("%026d", i));
+ Put put = new Put(data).addColumn(COLUMN_FAMILY, null, value);
+ table.put(put);
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Put huge value into table failed: ", e);
+ }
+ }
+ };
+
+ try (Connection conn = ConnectionFactory.createConnection(CONF)) {
+ try (Table table = conn.getTable(TEST_TABLE)) {
+
+ // Put the boundary into table firstly.
+ for (int i = 0; i < initialRowkeys.length; i++) {
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[i]));
+ Put put = new Put(rowKey).addColumn(COLUMN_FAMILY, null, rowKey);
+ table.put(put);
+ }
+
+ t.start();
+ byte[] rowKey = Bytes.toBytes(String.format("%026d", initialRowkeys[1] - 1));
+ for (int i = 0; i < 1000; i++) {
+ Get get = new Get(rowKey).addFamily(COLUMN_FAMILY).setClosestRowBefore(true);
+ Result result = table.get(get);
+ if (Result.getTotalSizeOfCells(result) == 0) {
+ Assert.fail("Get with closestRowBefore return NONE result.");
+ }
+ }
+ }
+ }
+ }
+}