001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.quotas; 019 020import static org.junit.jupiter.api.Assertions.assertTrue; 021import static org.junit.jupiter.api.Assertions.fail; 022 023import java.util.List; 024import java.util.Map; 025import java.util.concurrent.atomic.AtomicLong; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.HBaseTestingUtil; 028import org.apache.hadoop.hbase.MetaTableAccessor; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.Waiter; 031import org.apache.hadoop.hbase.client.Put; 032import org.apache.hadoop.hbase.client.RegionInfo; 033import org.apache.hadoop.hbase.master.HMaster; 034import org.apache.hadoop.hbase.testclassification.LargeTests; 035import org.apache.hadoop.hbase.util.Bytes; 036import org.junit.jupiter.api.AfterAll; 037import org.junit.jupiter.api.BeforeAll; 038import org.junit.jupiter.api.BeforeEach; 039import org.junit.jupiter.api.Tag; 040import org.junit.jupiter.api.Test; 041import org.junit.jupiter.api.TestInfo; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044 045@Tag(LargeTests.TAG) 046public class TestSpaceQuotaDropTable { 047 048 private static final Logger LOG = LoggerFactory.getLogger(TestSpaceQuotaDropTable.class); 049 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 050 051 private SpaceQuotaHelperForTests helper; 052 053 @BeforeAll 054 public static void setUp() throws Exception { 055 Configuration conf = TEST_UTIL.getConfiguration(); 056 SpaceQuotaHelperForTests.updateConfigForQuotas(conf); 057 TEST_UTIL.startMiniCluster(1); 058 } 059 060 @AfterAll 061 public static void tearDown() throws Exception { 062 TEST_UTIL.shutdownMiniCluster(); 063 } 064 065 @BeforeEach 066 public void removeAllQuotas(TestInfo testInfo) throws Exception { 067 helper = new SpaceQuotaHelperForTests(TEST_UTIL, () -> testInfo.getTestMethod().get().getName(), 068 new AtomicLong(0)); 069 helper.removeAllQuotas(); 070 } 071 072 @Test 073 public void testSetQuotaAndThenDropTableWithNoInserts() throws Exception { 074 setQuotaAndThenDropTable(SpaceViolationPolicy.NO_INSERTS); 075 } 076 077 @Test 078 public void testSetQuotaAndThenDropTableWithNoWrite() throws Exception { 079 setQuotaAndThenDropTable(SpaceViolationPolicy.NO_WRITES); 080 } 081 082 @Test 083 public void testSetQuotaAndThenDropTableWithNoWritesCompactions() throws Exception { 084 setQuotaAndThenDropTable(SpaceViolationPolicy.NO_WRITES_COMPACTIONS); 085 } 086 087 @Test 088 public void testSetQuotaAndThenDropTableWithDisable() throws Exception { 089 setQuotaAndThenDropTable(SpaceViolationPolicy.DISABLE); 090 } 091 092 @Test 093 public void testSetQuotaAndThenDropTableWithRegionReport() throws Exception { 094 final TableName tn = helper.createTable(); 095 helper.setQuotaLimit(tn, SpaceViolationPolicy.NO_INSERTS, 1L); 096 helper.writeData(tn, 2L); 097 098 final HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster(); 099 final MasterQuotaManager quotaManager = master.getMasterQuotaManager(); 100 101 // Make sure the master has report for the table. 102 Waiter.waitFor(TEST_UTIL.getConfiguration(), 30 * 1000, new Waiter.Predicate<Exception>() { 103 @Override 104 public boolean evaluate() throws Exception { 105 Map<RegionInfo, Long> regionSizes = quotaManager.snapshotRegionSizes(); 106 List<RegionInfo> tableRegions = 107 MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn); 108 return regionSizes.containsKey(tableRegions.get(0)); 109 } 110 }); 111 112 boolean hasRegionSize = false; 113 114 // region report should be present before dropping the table. 115 for (Map.Entry<RegionInfo, Long> entry : quotaManager.snapshotRegionSizes().entrySet()) { 116 if (entry.getKey().getTable().equals(tn)) { 117 hasRegionSize = true; 118 break; 119 } 120 } 121 122 // regionSize report for the given table should be present before dropping the table. 123 assertTrue(hasRegionSize); 124 125 // drop the table 126 TEST_UTIL.getAdmin().disableTable(tn); 127 TEST_UTIL.getAdmin().deleteTable(tn); 128 129 // check if deleted table region report still present in the map. 130 for (Map.Entry<RegionInfo, Long> entry : quotaManager.snapshotRegionSizes().entrySet()) { 131 if (entry.getKey().getTable().equals(tn)) { 132 fail("Dropped table regionSizes were not deleted during the drop command"); 133 } 134 } 135 } 136 137 private void setQuotaAndThenDropTable(SpaceViolationPolicy policy) throws Exception { 138 Put put = new Put(Bytes.toBytes("to_reject")); 139 put.addColumn(Bytes.toBytes(SpaceQuotaHelperForTests.F1), Bytes.toBytes("to"), 140 Bytes.toBytes("reject")); 141 142 // Do puts until we violate space policy 143 final TableName tn = helper.writeUntilViolationAndVerifyViolation(policy, put); 144 145 // Now, drop the table 146 TEST_UTIL.deleteTable(tn); 147 LOG.debug("Successfully deleted table ", tn); 148 149 // Now re-create the table 150 TEST_UTIL.createTable(tn, Bytes.toBytes(SpaceQuotaHelperForTests.F1)); 151 LOG.debug("Successfully re-created table ", tn); 152 153 // Put some rows now: should not violate as table/quota was dropped 154 helper.verifyNoViolation(tn, put); 155 } 156}