-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-22012 Space Quota: DisableTableViolationPolicy will cause cycles of enable/disable table #572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ | |
| import java.util.Iterator; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
| import java.util.Optional; | ||
| import java.util.Set; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
|
|
||
|
|
@@ -694,23 +695,65 @@ public Map<RegionInfo, Long> snapshotRegionSizes() { | |
| return copy; | ||
| } | ||
|
|
||
| int pruneEntriesOlderThan(long timeToPruneBefore) { | ||
| int pruneEntriesOlderThan(long timeToPruneBefore, QuotaObserverChore quotaObserverChore) { | ||
| if (regionSizes == null) { | ||
| return 0; | ||
| } | ||
| int numEntriesRemoved = 0; | ||
| Iterator<Entry<RegionInfo,SizeSnapshotWithTimestamp>> iterator = | ||
| Iterator<Entry<RegionInfo, SizeSnapshotWithTimestamp>> iterator = | ||
| regionSizes.entrySet().iterator(); | ||
| while (iterator.hasNext()) { | ||
| long currentEntryTime = iterator.next().getValue().getTime(); | ||
| if (currentEntryTime < timeToPruneBefore) { | ||
| RegionInfo regionInfo = iterator.next().getKey(); | ||
| long currentEntryTime = regionSizes.get(regionInfo).getTime(); | ||
| // do not prune the entries if table is in violation and | ||
| // violation policy is disable to avoid cycle of enable/disable. | ||
| // Please refer HBASE-22012 for more details. | ||
| // prune entries older than time. | ||
| if (currentEntryTime < timeToPruneBefore && !isInViolationAndPolicyDisable( | ||
| regionInfo.getTable(), quotaObserverChore)) { | ||
| iterator.remove(); | ||
| numEntriesRemoved++; | ||
| } | ||
| } | ||
| return numEntriesRemoved; | ||
| } | ||
|
|
||
| /** | ||
| * Method to check if a table is in violation and policy set on table is DISABLE. | ||
| * | ||
| * @param tableName tableName to check. | ||
| * @param quotaObserverChore QuotaObserverChore instance | ||
| * @return returns true if table is in violation and policy is disable else false. | ||
| */ | ||
| private boolean isInViolationAndPolicyDisable(TableName tableName, | ||
| QuotaObserverChore quotaObserverChore) { | ||
| boolean isInViolationAtTable = false; | ||
| boolean isInViolationAtNamespace = false; | ||
| SpaceViolationPolicy policy = null; | ||
| // Get Current Snapshot for the given table | ||
| SpaceQuotaSnapshot tableQuotaSnapshot = quotaObserverChore.getTableQuotaSnapshot(tableName); | ||
| SpaceQuotaSnapshot namespaceQuotaSnapshot = | ||
| quotaObserverChore.getNamespaceQuotaSnapshot(tableName.getNamespaceAsString()); | ||
| if (tableQuotaSnapshot != null) { | ||
| // check if table in violation | ||
| isInViolationAtTable = tableQuotaSnapshot.getQuotaStatus().isInViolation(); | ||
| Optional<SpaceViolationPolicy> tablePolicy = tableQuotaSnapshot.getQuotaStatus().getPolicy(); | ||
| if (tablePolicy.isPresent()) { | ||
| policy = tablePolicy.get(); | ||
| } | ||
| } else if (namespaceQuotaSnapshot != null) { | ||
| // check namespace in violation | ||
| isInViolationAtNamespace = namespaceQuotaSnapshot.getQuotaStatus().isInViolation(); | ||
| Optional<SpaceViolationPolicy> namespacePolicy = | ||
| tableQuotaSnapshot.getQuotaStatus().getPolicy(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the NPE from findbugs. Should be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| if (namespacePolicy.isPresent()) { | ||
| policy = namespacePolicy.get(); | ||
| } | ||
| } | ||
| return (policy == SpaceViolationPolicy.DISABLE) && (isInViolationAtTable | ||
| || isInViolationAtNamespace); | ||
| } | ||
|
|
||
| public void processFileArchivals(FileArchiveNotificationRequest request, Connection conn, | ||
| Configuration conf, FileSystem fs) throws IOException { | ||
| final HashMultimap<TableName,Entry<String,Long>> archivedFilesByTable = HashMultimap.create(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,24 +19,31 @@ | |
| import static org.junit.Assert.assertTrue; | ||
| import static org.junit.Assert.fail; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.concurrent.atomic.AtomicLong; | ||
|
|
||
| import org.apache.hadoop.conf.Configuration; | ||
| import org.apache.hadoop.hbase.DoNotRetryIOException; | ||
| import org.apache.hadoop.hbase.HBaseClassTestRule; | ||
| import org.apache.hadoop.hbase.HBaseTestingUtility; | ||
| import org.apache.hadoop.hbase.MetaTableAccessor; | ||
| import org.apache.hadoop.hbase.TableName; | ||
| import org.apache.hadoop.hbase.Waiter; | ||
| import org.apache.hadoop.hbase.client.Admin; | ||
| import org.apache.hadoop.hbase.client.Append; | ||
| import org.apache.hadoop.hbase.client.Delete; | ||
| import org.apache.hadoop.hbase.client.Increment; | ||
| import org.apache.hadoop.hbase.client.Put; | ||
| import org.apache.hadoop.hbase.client.RegionInfo; | ||
| import org.apache.hadoop.hbase.client.Table; | ||
| import org.apache.hadoop.hbase.master.HMaster; | ||
| import org.apache.hadoop.hbase.security.AccessDeniedException; | ||
| import org.apache.hadoop.hbase.testclassification.LargeTests; | ||
| import org.apache.hadoop.hbase.util.Bytes; | ||
| import org.apache.hadoop.util.StringUtils; | ||
| import org.junit.AfterClass; | ||
| import org.junit.Assert; | ||
| import org.junit.Before; | ||
| import org.junit.BeforeClass; | ||
| import org.junit.ClassRule; | ||
|
|
@@ -221,4 +228,32 @@ public void testTableQuotaOverridesNamespaceQuota() throws Exception { | |
| Bytes.toBytes("reject")); | ||
| helper.verifyViolation(policy, tn, p); | ||
| } | ||
|
|
||
| @Test | ||
| public void testDisablePolicyQuotaAndViolate() throws Exception { | ||
| TableName tableName = helper.createTable(); | ||
| helper.setQuotaLimit(tableName, SpaceViolationPolicy.DISABLE, 1L); | ||
| helper.writeData(tableName, SpaceQuotaHelperForTests.ONE_MEGABYTE * 2L); | ||
| TEST_UTIL.getConfiguration() | ||
| .setLong("hbase.master.quotas.region.report.retention.millis", 100); | ||
|
|
||
| HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster(); | ||
| MasterQuotaManager quotaManager = master.getMasterQuotaManager(); | ||
|
|
||
| // Make sure the master has report for the table. | ||
| Waiter.waitFor(TEST_UTIL.getConfiguration(), 30 * 1000, new Waiter.Predicate<Exception>() { | ||
| @Override | ||
| public boolean evaluate() throws Exception { | ||
| Map<RegionInfo, Long> regionSizes = quotaManager.snapshotRegionSizes(); | ||
| List<RegionInfo> tableRegions = | ||
| MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tableName); | ||
| return regionSizes.containsKey(tableRegions.get(0)); | ||
| } | ||
| }); | ||
|
|
||
| // Check if disabled table region report present in the map after retention period expired. | ||
| // It should be present after retention period expired. | ||
| Assert.assertTrue(quotaManager.snapshotRegionSizes().keySet().stream() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you pull the lambda out of the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| .filter(k -> k.getTable().equals(tableName)).count() > 0); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.