You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by el...@apache.org on 2020/07/22 01:43:23 UTC
[hbase] branch master updated: HBASE-22146 Removing a
namespace-level space quota does not remove policies against contained
tables
This is an automated email from the ASF dual-hosted git repository.
elserj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/master by this push:
new 8191fbd HBASE-22146 Removing a namespace-level space quota does not remove policies against contained tables
8191fbd is described below
commit 8191fbdd7d4030dab05532e285206c8189cd37c7
Author: surbhi <su...@gmail.com>
AuthorDate: Fri Jun 19 16:21:22 2020 -0700
HBASE-22146 Removing a namespace-level space quota does not remove policies against contained tables
Closes #1935
Signed-off-by: Josh Elser <el...@apache.org>
---
.../apache/hadoop/hbase/quotas/QuotaTableUtil.java | 28 ++++++++++
.../org/apache/hadoop/hbase/quotas/QuotaUtil.java | 8 +++
.../hbase/quotas/SpaceQuotaHelperForTests.java | 64 +++++++++++++++++++++-
.../hadoop/hbase/quotas/TestSpaceQuotaRemoval.java | 58 ++++++++++++++++++++
4 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java
index 4f14911..624b475 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java
@@ -629,6 +629,34 @@ public class QuotaTableUtil {
}
/**
+ * Remove table usage snapshots (u:p columns) for the namespace passed
+ * @param connection connection to re-use
+ * @param namespace the namespace to fetch the list of table usage snapshots
+ */
+ static void deleteTableUsageSnapshotsForNamespace(Connection connection, String namespace)
+ throws IOException {
+ Scan s = new Scan();
+ //Get rows for all tables in namespace
+ s.setRowPrefixFilter(Bytes.add(QUOTA_TABLE_ROW_KEY_PREFIX, Bytes.toBytes(namespace + TableName.NAMESPACE_DELIM)));
+ //Scan for table usage column (u:p) in quota table
+ s.addColumn(QUOTA_FAMILY_USAGE,QUOTA_QUALIFIER_POLICY);
+ //Scan for table quota column (q:s) if table has a space quota defined
+ s.addColumn(QUOTA_FAMILY_INFO,QUOTA_QUALIFIER_SETTINGS);
+ try (Table quotaTable = connection.getTable(QUOTA_TABLE_NAME);
+ ResultScanner rs = quotaTable.getScanner(s)) {
+ for (Result r : rs) {
+ byte[] data = r.getValue(QUOTA_FAMILY_INFO, QUOTA_QUALIFIER_SETTINGS);
+ //if table does not have a table space quota defined, delete table usage column (u:p)
+ if (data == null) {
+ Delete delete = new Delete(r.getRow());
+ delete.addColumns(QUOTA_FAMILY_USAGE,QUOTA_QUALIFIER_POLICY);
+ quotaTable.delete(delete);
+ }
+ }
+ }
+ }
+
+ /**
* Fetches the computed size of all snapshots against tables in a namespace for space quotas.
*/
static long getNamespaceSnapshotSize(
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java
index e6acc4b..1d816d6 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java
@@ -266,6 +266,14 @@ public class QuotaUtil extends QuotaTableUtil {
if (qualifier != null) {
delete.addColumns(QUOTA_FAMILY_INFO, qualifier);
}
+ if (isNamespaceRowKey(rowKey)) {
+ String ns = getNamespaceFromRowKey(rowKey);
+ Quotas namespaceQuota = getNamespaceQuota(connection,ns);
+ if (namespaceQuota != null && namespaceQuota.hasSpace()) {
+ // When deleting namespace space quota, also delete table usage(u:p) snapshots
+ deleteTableUsageSnapshotsForNamespace(connection, ns);
+ }
+ }
doDelete(connection, delete);
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/SpaceQuotaHelperForTests.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/SpaceQuotaHelperForTests.java
index d522c0c..296d38f 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/SpaceQuotaHelperForTests.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/SpaceQuotaHelperForTests.java
@@ -158,6 +158,28 @@ public class SpaceQuotaHelperForTests {
return tn;
}
+
+ TableName writeUntilViolationAndVerifyViolationInNamespace(
+ String ns, SpaceViolationPolicy policyToViolate, Mutation m) throws Exception {
+ final TableName tn = writeUntilViolationInNamespace(ns, policyToViolate);
+ verifyViolation(policyToViolate, tn, m);
+ return tn;
+ }
+
+ TableName writeUntilViolationInNamespace(String ns, SpaceViolationPolicy policyToViolate) throws Exception {
+ TableName tn = createTableWithRegions(ns,10);
+
+ setQuotaLimit(ns, policyToViolate, 4L);
+
+ // Write more data than should be allowed and flush it to disk
+ writeData(tn, 5L * SpaceQuotaHelperForTests.ONE_MEGABYTE);
+
+ // This should be sufficient time for the chores to run and see the change.
+ Thread.sleep(5000);
+
+ return tn;
+ }
+
/**
* Verifies that the given policy on the given table has been violated
*/
@@ -261,6 +283,19 @@ public class SpaceQuotaHelperForTests {
}
/**
+ * Verifies that table usage snapshot exists for the table
+ */
+ void verifyTableUsageSnapshotForSpaceQuotaExist(TableName tn) throws Exception {
+ boolean sawUsageSnapshot = false;
+ try (Table quotaTable = testUtil.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) {
+ Scan s = QuotaTableUtil.makeQuotaSnapshotScanForTable(tn);
+ ResultScanner rs = quotaTable.getScanner(s);
+ sawUsageSnapshot = (rs.next() != null);
+ }
+ assertTrue("Expected to succeed in getting table usage snapshots for space quota", sawUsageSnapshot);
+ }
+
+ /**
* Sets the given quota (policy & limit) on the passed table.
*/
void setQuotaLimit(final TableName tn, SpaceViolationPolicy policy, long sizeInMBs)
@@ -272,6 +307,17 @@ public class SpaceQuotaHelperForTests {
}
/**
+ * Sets the given quota (policy & limit) on the passed namespace.
+ */
+ void setQuotaLimit(String ns, SpaceViolationPolicy policy, long sizeInMBs)
+ throws Exception {
+ final long sizeLimit = sizeInMBs * SpaceQuotaHelperForTests.ONE_MEGABYTE;
+ QuotaSettings settings = QuotaSettingsFactory.limitNamespaceSpace(ns, sizeLimit, policy);
+ testUtil.getAdmin().setQuota(settings);
+ LOG.debug("Quota limit set for namespace = {}, limit = {}", ns, sizeLimit);
+ }
+
+ /**
* Removes the space quota from the given table
*/
void removeQuotaFromtable(final TableName tn) throws Exception {
@@ -281,6 +327,16 @@ public class SpaceQuotaHelperForTests {
}
/**
+ * Removes the space quota from the given namespace
+ */
+ void removeQuotaFromNamespace(String ns) throws Exception {
+ QuotaSettings removeQuota = QuotaSettingsFactory.removeNamespaceSpaceLimit(ns);
+ Admin admin = testUtil.getAdmin();
+ admin.setQuota(removeQuota);
+ LOG.debug("Space quota settings removed from the namespace ", ns);
+ }
+
+ /**
* Removes all quotas defined in the HBase quota table.
*/
void removeAllQuotas() throws Exception {
@@ -411,7 +467,13 @@ public class SpaceQuotaHelperForTests {
}
NamespaceDescriptor createNamespace() throws Exception {
- NamespaceDescriptor nd = NamespaceDescriptor.create("ns" + counter.getAndIncrement()).build();
+ return createNamespace(null);
+ }
+
+ NamespaceDescriptor createNamespace(String namespace) throws Exception {
+ if (namespace == null || namespace.trim().isEmpty())
+ namespace = "ns" + counter.getAndIncrement();
+ NamespaceDescriptor nd = NamespaceDescriptor.create(namespace).build();
testUtil.getAdmin().createNamespace(nd);
return nd;
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestSpaceQuotaRemoval.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestSpaceQuotaRemoval.java
index ba89990..3ed6c71 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestSpaceQuotaRemoval.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestSpaceQuotaRemoval.java
@@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicLong;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.testclassification.LargeTests;
@@ -139,6 +140,63 @@ public class TestSpaceQuotaRemoval {
helper.verifyNoViolation(tn, put);
}
+ @Test
+ public void testDeleteTableUsageSnapshotsForNamespace() throws Exception {
+ Put put = new Put(Bytes.toBytes("to_reject"));
+ put.addColumn(Bytes.toBytes(SpaceQuotaHelperForTests.F1), Bytes.toBytes("to"),
+ Bytes.toBytes("reject"));
+
+ SpaceViolationPolicy policy = SpaceViolationPolicy.NO_INSERTS;
+
+ //Create a namespace
+ String ns1 = "nsnew";
+ NamespaceDescriptor nsd = helper.createNamespace(ns1);
+
+ //Create 2nd namespace with name similar to ns1
+ String ns2 = ns1 + "test";
+ NamespaceDescriptor nsd2 = helper.createNamespace(ns2);
+
+ // Do puts until we violate space policy on table tn1 in namesapce ns1
+ final TableName tn1 = helper.writeUntilViolationAndVerifyViolationInNamespace(ns1, policy, put);
+
+ // Do puts until we violate space policy on table tn2 in namespace ns2
+ final TableName tn2 = helper.writeUntilViolationAndVerifyViolationInNamespace(ns2, policy, put);
+
+ // Now, remove the quota from namespace ns1 which will remove table usage snapshots for ns1
+ helper.removeQuotaFromNamespace(ns1);
+
+ // Verify that table usage snapshot for table tn2 in namespace ns2 exist
+ helper.verifyTableUsageSnapshotForSpaceQuotaExist(tn2);
+
+ // Put a new row on tn2: should violate as space quota exists on namespace ns2
+ helper.verifyViolation(policy, tn2, put);
+
+ // Put a new row on tn1: should not violate as quota settings removed from namespace ns1
+ helper.verifyNoViolation(tn1, put);
+ }
+
+ @Test
+ public void testSetNamespaceSizeQuotaAndThenRemove() throws Exception {
+ Put put = new Put(Bytes.toBytes("to_reject"));
+ put.addColumn(Bytes.toBytes(SpaceQuotaHelperForTests.F1), Bytes.toBytes("to"),
+ Bytes.toBytes("reject"));
+
+ SpaceViolationPolicy policy = SpaceViolationPolicy.NO_INSERTS;
+
+ //Create namespace
+ NamespaceDescriptor nsd = helper.createNamespace();
+ String ns = nsd.getName();
+
+ // Do puts until we violate space policy on table tn1
+ final TableName tn1 = helper.writeUntilViolationAndVerifyViolationInNamespace(ns, policy, put);
+
+ // Now, remove the quota from namespace
+ helper.removeQuotaFromNamespace(ns);
+
+ // Put a new row now on tn1: should not violate as quota settings removed from namespace
+ helper.verifyNoViolation(tn1, put);
+ }
+
private void setQuotaAndThenRemoveInOneAmongTwoTables(SpaceViolationPolicy policy)
throws Exception {
Put put = new Put(Bytes.toBytes("to_reject"));