1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.hadoop.hbase.quotas;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.when;
24
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Map;
31 import java.util.Set;
32
33 import org.apache.hadoop.conf.Configuration;
34 import org.apache.hadoop.hbase.HBaseConfiguration;
35 import org.apache.hadoop.hbase.HRegionInfo;
36 import org.apache.hadoop.hbase.TableName;
37 import org.apache.hadoop.hbase.client.Admin;
38 import org.apache.hadoop.hbase.client.Connection;
39 import org.apache.hadoop.hbase.quotas.QuotaObserverChore.TablesWithQuotas;
40 import org.apache.hadoop.hbase.testclassification.SmallTests;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.experimental.categories.Category;
44
45 import com.google.common.collect.Multimap;
46
47
48
49
50 @Category(SmallTests.class)
51 public class TestTablesWithQuotas {
52 private Connection conn;
53 private Configuration conf;
54
55 @Before
56 public void setup() throws Exception {
57 conn = mock(Connection.class);
58 conf = HBaseConfiguration.create();
59 }
60
61 @Test
62 public void testImmutableGetters() {
63 Set<TableName> tablesWithTableQuotas = new HashSet<>();
64 Set<TableName> tablesWithNamespaceQuotas = new HashSet<>();
65 final TablesWithQuotas tables = new TablesWithQuotas(conn, conf);
66 for (int i = 0; i < 5; i++) {
67 TableName tn = TableName.valueOf("tn" + i);
68 tablesWithTableQuotas.add(tn);
69 tables.addTableQuotaTable(tn);
70 }
71 for (int i = 0; i < 3; i++) {
72 TableName tn = TableName.valueOf("tn_ns" + i);
73 tablesWithNamespaceQuotas.add(tn);
74 tables.addNamespaceQuotaTable(tn);
75 }
76 Set<TableName> actualTableQuotaTables = tables.getTableQuotaTables();
77 Set<TableName> actualNamespaceQuotaTables = tables.getNamespaceQuotaTables();
78 assertEquals(tablesWithTableQuotas, actualTableQuotaTables);
79 assertEquals(tablesWithNamespaceQuotas, actualNamespaceQuotaTables);
80 try {
81 actualTableQuotaTables.add(null);
82 fail("Should not be able to add an element");
83 } catch (UnsupportedOperationException e) {
84
85 }
86 try {
87 actualNamespaceQuotaTables.add(null);
88 fail("Should not be able to add an element");
89 } catch (UnsupportedOperationException e) {
90
91 }
92 }
93
94 @Test
95 public void testInsufficientlyReportedTableFiltering() throws Exception {
96 final Map<TableName,Integer> reportedRegions = new HashMap<>();
97 final Map<TableName,Integer> actualRegions = new HashMap<>();
98 final Configuration conf = HBaseConfiguration.create();
99 conf.setDouble(QuotaObserverChore.QUOTA_OBSERVER_CHORE_REPORT_PERCENT_KEY, 0.95);
100
101 TableName tooFewRegionsTable = TableName.valueOf("tn1");
102 TableName sufficientRegionsTable = TableName.valueOf("tn2");
103 TableName tooFewRegionsNamespaceTable = TableName.valueOf("ns1", "tn2");
104 TableName sufficientRegionsNamespaceTable = TableName.valueOf("ns1", "tn2");
105 final TablesWithQuotas tables = new TablesWithQuotas(conn, conf) {
106 @Override
107 Configuration getConfiguration() {
108 return conf;
109 }
110
111 @Override
112 int getNumRegions(TableName tableName) {
113 return actualRegions.get(tableName);
114 }
115
116 @Override
117 int getNumReportedRegions(TableName table, QuotaSnapshotStore<TableName> tableStore) {
118 return reportedRegions.get(table);
119 }
120 };
121 tables.addTableQuotaTable(tooFewRegionsTable);
122 tables.addTableQuotaTable(sufficientRegionsTable);
123 tables.addNamespaceQuotaTable(tooFewRegionsNamespaceTable);
124 tables.addNamespaceQuotaTable(sufficientRegionsNamespaceTable);
125
126 reportedRegions.put(tooFewRegionsTable, 5);
127 actualRegions.put(tooFewRegionsTable, 10);
128 reportedRegions.put(sufficientRegionsTable, 19);
129 actualRegions.put(sufficientRegionsTable, 20);
130 reportedRegions.put(tooFewRegionsNamespaceTable, 9);
131 actualRegions.put(tooFewRegionsNamespaceTable, 10);
132 reportedRegions.put(sufficientRegionsNamespaceTable, 98);
133 actualRegions.put(sufficientRegionsNamespaceTable, 100);
134
135
136 tables.filterInsufficientlyReportedTables(null);
137 Set<TableName> filteredTablesWithTableQuotas = tables.getTableQuotaTables();
138 assertEquals(Collections.singleton(sufficientRegionsTable), filteredTablesWithTableQuotas);
139 Set<TableName> filteredTablesWithNamespaceQutoas = tables.getNamespaceQuotaTables();
140 assertEquals(Collections.singleton(sufficientRegionsNamespaceTable), filteredTablesWithNamespaceQutoas);
141 }
142
143 @Test
144 public void testGetTablesByNamespace() {
145 final TablesWithQuotas tables = new TablesWithQuotas(conn, conf);
146 tables.addTableQuotaTable(TableName.valueOf("ignored1"));
147 tables.addTableQuotaTable(TableName.valueOf("ignored2"));
148 tables.addNamespaceQuotaTable(TableName.valueOf("ns1", "t1"));
149 tables.addNamespaceQuotaTable(TableName.valueOf("ns1", "t2"));
150 tables.addNamespaceQuotaTable(TableName.valueOf("ns1", "t3"));
151 tables.addNamespaceQuotaTable(TableName.valueOf("ns2", "t1"));
152 tables.addNamespaceQuotaTable(TableName.valueOf("ns2", "t2"));
153
154 Multimap<String,TableName> tablesByNamespace = tables.getTablesByNamespace();
155 Collection<TableName> tablesInNs = tablesByNamespace.get("ns1");
156 assertEquals(3, tablesInNs.size());
157 assertTrue("Unexpected results for ns1: " + tablesInNs,
158 tablesInNs.containsAll(Arrays.asList(
159 TableName.valueOf("ns1", "t1"),
160 TableName.valueOf("ns1", "t2"),
161 TableName.valueOf("ns1", "t3"))));
162 tablesInNs = tablesByNamespace.get("ns2");
163 assertEquals(2, tablesInNs.size());
164 assertTrue("Unexpected results for ns2: " + tablesInNs,
165 tablesInNs.containsAll(Arrays.asList(
166 TableName.valueOf("ns2", "t1"),
167 TableName.valueOf("ns2", "t2"))));
168 }
169
170 @Test
171 public void testFilteringMissingTables() throws Exception {
172 final TableName missingTable = TableName.valueOf("doesNotExist");
173
174 Admin admin = mock(Admin.class);
175 when(conn.getAdmin()).thenReturn(admin);
176 when(admin.getTableRegions(missingTable)).thenReturn(null);
177
178 QuotaObserverChore chore = mock(QuotaObserverChore.class);
179 Map<HRegionInfo,Long> regionUsage = new HashMap<>();
180 TableQuotaSnapshotStore store = new TableQuotaSnapshotStore(conn, chore, regionUsage);
181
182
183
184 final TablesWithQuotas tables = new TablesWithQuotas(conn, conf) {
185 @Override
186 int getNumReportedRegions(TableName table, QuotaSnapshotStore<TableName> tableStore) {
187 throw new RuntimeException("Should should not reach here");
188 }
189 };
190 tables.addTableQuotaTable(missingTable);
191
192 tables.filterInsufficientlyReportedTables(store);
193
194 final Set<TableName> tablesWithQuotas = tables.getTableQuotaTables();
195 assertTrue(
196 "Expected to find no tables, but found " + tablesWithQuotas, tablesWithQuotas.isEmpty());
197 }
198 }