View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.hadoop.hbase.quotas;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertTrue;
21  
22  import java.io.IOException;
23  import java.util.Set;
24  import java.util.concurrent.atomic.AtomicLong;
25  
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.HColumnDescriptor;
29  import org.apache.hadoop.hbase.HTableDescriptor;
30  import org.apache.hadoop.hbase.NamespaceDescriptor;
31  import org.apache.hadoop.hbase.TableName;
32  import org.apache.hadoop.hbase.client.Admin;
33  import org.apache.hadoop.hbase.client.Connection;
34  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
35  import org.apache.hadoop.hbase.master.HMaster;
36  import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
37  import org.apache.hadoop.hbase.testclassification.MediumTests;
38  import org.junit.AfterClass;
39  import org.junit.Before;
40  import org.junit.BeforeClass;
41  import org.junit.Rule;
42  import org.junit.Test;
43  import org.junit.experimental.categories.Category;
44  import org.junit.rules.TestName;
45  
46  /**
47   * Test class for {@link MasterSpaceQuotaObserver}.
48   */
49  @Category(MediumTests.class)
50  public class TestMasterSpaceQuotaObserver {
51    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
52    private static SpaceQuotaHelperForTests helper;
53  
54    @Rule
55    public TestName testName = new TestName();
56  
57    @BeforeClass
58    public static void setUp() throws Exception {
59      Configuration conf = TEST_UTIL.getConfiguration();
60      conf.setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
61      TEST_UTIL.startMiniCluster(1);
62    }
63  
64    @AfterClass
65    public static void tearDown() throws Exception {
66      TEST_UTIL.shutdownMiniCluster();
67    }
68  
69    @Before
70    public void removeAllQuotas() throws Exception {
71      if (helper == null) {
72        helper = new SpaceQuotaHelperForTests(TEST_UTIL, testName, new AtomicLong());
73      }
74      final Connection conn = TEST_UTIL.getConnection();
75      // Wait for the quota table to be created
76      if (!conn.getAdmin().tableExists(QuotaUtil.QUOTA_TABLE_NAME)) {
77        helper.waitForQuotaTable(conn);
78      } else {
79        // Or, clean up any quotas from previous test runs.
80        helper.removeAllQuotas(conn);
81        assertEquals(0, helper.listNumDefinedQuotas(conn));
82      }
83    }
84  
85    @Test
86    public void testTableQuotaRemoved() throws Exception {
87      final Connection conn = TEST_UTIL.getConnection();
88      final Admin admin = conn.getAdmin();
89      final TableName tn = TableName.valueOf(testName.getMethodName());
90      // Drop the table if it somehow exists
91      if (admin.tableExists(tn)) {
92        admin.disableTable(tn);
93        admin.deleteTable(tn);
94      }
95  
96      // Create a table
97      HTableDescriptor tableDesc = new HTableDescriptor(tn);
98      tableDesc.addFamily(new HColumnDescriptor("F1"));
99      admin.createTable(tableDesc);
100     assertEquals(0, getNumSpaceQuotas());
101 
102     // Set a quota
103     QuotaSettings settings = QuotaSettingsFactory.limitTableSpace(
104         tn, 1024L, SpaceViolationPolicy.NO_INSERTS);
105     admin.setQuota(settings);
106     assertEquals(1, getNumSpaceQuotas());
107 
108     // Delete the table and observe the quota being automatically deleted as well
109     admin.disableTable(tn);
110     admin.deleteTable(tn);
111     assertEquals(0, getNumSpaceQuotas());
112   }
113 
114   @Test
115   public void testNamespaceQuotaRemoved() throws Exception {
116     final Connection conn = TEST_UTIL.getConnection();
117     final Admin admin = conn.getAdmin();
118     final String ns = testName.getMethodName();
119     // Drop the ns if it somehow exists
120     if (namespaceExists(ns)) {
121       admin.deleteNamespace(ns);
122     }
123 
124     // Create the ns
125     NamespaceDescriptor desc = NamespaceDescriptor.create(ns).build();
126     admin.createNamespace(desc);
127     assertEquals(0, getNumSpaceQuotas());
128 
129     // Set a quota
130     QuotaSettings settings = QuotaSettingsFactory.limitNamespaceSpace(
131         ns, 1024L, SpaceViolationPolicy.NO_INSERTS);
132     admin.setQuota(settings);
133     assertEquals(1, getNumSpaceQuotas());
134 
135     // Delete the table and observe the quota being automatically deleted as well
136     admin.deleteNamespace(ns);
137     assertEquals(0, getNumSpaceQuotas());
138   }
139 
140   @Test
141   public void testObserverAddedByDefault() throws Exception {
142     final HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
143     final MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost();
144     Set<String> coprocessorNames = cpHost.getCoprocessors();
145     assertTrue(
146         "Did not find MasterSpaceQuotaObserver in list of CPs: " + coprocessorNames,
147         coprocessorNames.contains(MasterSpaceQuotaObserver.class.getSimpleName()));
148   }
149 
150   public boolean namespaceExists(String ns) throws IOException {
151     NamespaceDescriptor[] descs = TEST_UTIL.getHBaseAdmin().listNamespaceDescriptors();
152     for (NamespaceDescriptor desc : descs) {
153       if (ns.equals(desc.getName())) {
154         return true;
155       }
156     }
157     return false;
158   }
159 
160   public int getNumSpaceQuotas() throws Exception {
161     QuotaRetriever scanner = QuotaRetriever.open(TEST_UTIL.getConfiguration());
162     int numSpaceQuotas = 0;
163     for (QuotaSettings quotaSettings : scanner) {
164       if (quotaSettings.getQuotaType() == QuotaType.SPACE) {
165         numSpaceQuotas++;
166       }
167     }
168     return numSpaceQuotas;
169   }
170 }