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.apache.hadoop.hbase.util.Bytes.toBytes;
20 import static org.junit.Assert.fail;
21 import static org.mockito.Matchers.any;
22 import static org.mockito.Mockito.doCallRealMethod;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
27
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Map.Entry;
35
36 import org.apache.hadoop.conf.Configuration;
37 import org.apache.hadoop.hbase.Cell;
38 import org.apache.hadoop.hbase.HBaseConfiguration;
39 import org.apache.hadoop.hbase.KeyValue;
40 import org.apache.hadoop.hbase.TableName;
41 import org.apache.hadoop.hbase.client.Connection;
42 import org.apache.hadoop.hbase.client.Result;
43 import org.apache.hadoop.hbase.client.ResultScanner;
44 import org.apache.hadoop.hbase.client.Scan;
45 import org.apache.hadoop.hbase.client.Table;
46 import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot.SpaceQuotaStatus;
47 import org.apache.hadoop.hbase.regionserver.RegionServerServices;
48 import org.apache.hadoop.hbase.testclassification.SmallTests;
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.junit.experimental.categories.Category;
52
53
54
55
56 @Category(SmallTests.class)
57 public class TestSpaceQuotaViolationPolicyRefresherChore {
58
59 private RegionServerSpaceQuotaManager manager;
60 private RegionServerServices rss;
61 private SpaceQuotaRefresherChore chore;
62 private Configuration conf;
63 private Connection conn;
64
65 @SuppressWarnings("unchecked")
66 @Before
67 public void setup() throws IOException {
68 conf = HBaseConfiguration.create();
69 rss = mock(RegionServerServices.class);
70 manager = mock(RegionServerSpaceQuotaManager.class);
71 conn = mock(Connection.class);
72 when(manager.getRegionServerServices()).thenReturn(rss);
73 when(rss.getConfiguration()).thenReturn(conf);
74
75
76 chore = mock(SpaceQuotaRefresherChore.class);
77 when(chore.getConnection()).thenReturn(conn);
78 when(chore.getManager()).thenReturn(manager);
79 doCallRealMethod().when(chore).chore();
80 when(chore.isInViolation(any(SpaceQuotaSnapshot.class))).thenCallRealMethod();
81 doCallRealMethod().when(chore).extractQuotaSnapshot(any(Result.class), any(Map.class));
82 }
83
84 @Test
85 public void testPoliciesAreEnforced() throws IOException {
86
87 final Map<TableName,SpaceQuotaSnapshot> policiesToEnforce = new HashMap<>();
88 policiesToEnforce.put(
89 TableName.valueOf("table1"),
90 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.DISABLE), 1024L, 512L));
91 policiesToEnforce.put(
92 TableName.valueOf("table2"),
93 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_INSERTS), 2048L, 512L));
94 policiesToEnforce.put(
95 TableName.valueOf("table3"),
96 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES), 4096L, 512L));
97 policiesToEnforce.put(
98 TableName.valueOf("table4"),
99 new SpaceQuotaSnapshot(
100 new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES_COMPACTIONS), 8192L, 512L));
101
102
103 when(manager.copyQuotaSnapshots()).thenReturn(
104 Collections.<TableName,SpaceQuotaSnapshot> emptyMap());
105
106 when(chore.fetchSnapshotsFromQuotaTable()).thenReturn(policiesToEnforce);
107
108 chore.chore();
109
110 for (Entry<TableName,SpaceQuotaSnapshot> entry : policiesToEnforce.entrySet()) {
111
112 verify(manager).enforceViolationPolicy(entry.getKey(), entry.getValue());
113
114 verify(manager, never()).disableViolationPolicyEnforcement(entry.getKey());
115 }
116 }
117
118 @Test
119 public void testOldPoliciesAreRemoved() throws IOException {
120 final Map<TableName,SpaceQuotaSnapshot> previousPolicies = new HashMap<>();
121 previousPolicies.put(
122 TableName.valueOf("table3"),
123 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES), 4096L, 512L));
124 previousPolicies.put(
125 TableName.valueOf("table4"),
126 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES), 8192L, 512L));
127
128 final Map<TableName,SpaceQuotaSnapshot> policiesToEnforce = new HashMap<>();
129 policiesToEnforce.put(
130 TableName.valueOf("table1"),
131 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.DISABLE), 1024L, 512L));
132 policiesToEnforce.put(
133 TableName.valueOf("table2"),
134 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_INSERTS), 2048L, 512L));
135 policiesToEnforce.put(
136 TableName.valueOf("table3"),
137 new SpaceQuotaSnapshot(SpaceQuotaStatus.notInViolation(), 256L, 512L));
138 policiesToEnforce.put(
139 TableName.valueOf("table4"),
140 new SpaceQuotaSnapshot(SpaceQuotaStatus.notInViolation(), 128L, 512L));
141
142
143 when(manager.copyQuotaSnapshots()).thenReturn(previousPolicies);
144
145 when(chore.fetchSnapshotsFromQuotaTable()).thenReturn(policiesToEnforce);
146
147 chore.chore();
148
149 verify(manager).enforceViolationPolicy(TableName.valueOf("table1"), policiesToEnforce.get(TableName.valueOf("table1")));
150 verify(manager).enforceViolationPolicy(TableName.valueOf("table2"), policiesToEnforce.get(TableName.valueOf("table2")));
151
152 verify(manager).disableViolationPolicyEnforcement(TableName.valueOf("table3"));
153 verify(manager).disableViolationPolicyEnforcement(TableName.valueOf("table4"));
154 }
155
156 @Test
157 public void testNewPolicyOverridesOld() throws IOException {
158 final Map<TableName,SpaceQuotaSnapshot> policiesToEnforce = new HashMap<>();
159 policiesToEnforce.put(
160 TableName.valueOf("table1"),
161 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.DISABLE), 1024L, 512L));
162 policiesToEnforce.put(
163 TableName.valueOf("table2"),
164 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES), 2048L, 512L));
165 policiesToEnforce.put(
166 TableName.valueOf("table3"),
167 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_INSERTS), 4096L, 512L));
168
169 final Map<TableName,SpaceQuotaSnapshot> previousPolicies = new HashMap<>();
170 previousPolicies.put(
171 TableName.valueOf("table1"),
172 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES), 8192L, 512L));
173
174
175 when(manager.getActivePoliciesAsMap()).thenReturn(previousPolicies);
176
177 when(chore.fetchSnapshotsFromQuotaTable()).thenReturn(policiesToEnforce);
178
179 chore.chore();
180
181 for (Entry<TableName,SpaceQuotaSnapshot> entry : policiesToEnforce.entrySet()) {
182 verify(manager).enforceViolationPolicy(entry.getKey(), entry.getValue());
183 }
184 verify(manager, never()).disableViolationPolicyEnforcement(TableName.valueOf("table1"));
185 }
186
187 @Test
188 public void testMissingAllColumns() throws IOException {
189 when(chore.fetchSnapshotsFromQuotaTable()).thenCallRealMethod();
190 ResultScanner scanner = mock(ResultScanner.class);
191 Table quotaTable = mock(Table.class);
192 when(conn.getTable(QuotaUtil.QUOTA_TABLE_NAME)).thenReturn(quotaTable);
193 when(quotaTable.getScanner(any(Scan.class))).thenReturn(scanner);
194
195 List<Result> results = new ArrayList<>();
196 results.add(Result.create(Collections.<Cell> emptyList()));
197 when(scanner.iterator()).thenReturn(results.iterator());
198 try {
199 chore.fetchSnapshotsFromQuotaTable();
200 fail("Expected an IOException, but did not receive one.");
201 } catch (IOException e) {
202
203
204 }
205 }
206
207 @Test
208 public void testMissingDesiredColumn() throws IOException {
209 when(chore.fetchSnapshotsFromQuotaTable()).thenCallRealMethod();
210 ResultScanner scanner = mock(ResultScanner.class);
211 Table quotaTable = mock(Table.class);
212 when(conn.getTable(QuotaUtil.QUOTA_TABLE_NAME)).thenReturn(quotaTable);
213 when(quotaTable.getScanner(any(Scan.class))).thenReturn(scanner);
214
215 List<Result> results = new ArrayList<>();
216
217 Cell c = new KeyValue(toBytes("t:inviolation"), toBytes("q"), toBytes("s"), new byte[0]);
218 results.add(Result.create(Collections.singletonList(c)));
219 when(scanner.iterator()).thenReturn(results.iterator());
220 try {
221 chore.fetchSnapshotsFromQuotaTable();
222 fail("Expected an IOException, but did not receive one.");
223 } catch (IOException e) {
224
225
226 }
227 }
228
229 @Test
230 public void testParsingError() throws IOException {
231 when(chore.fetchSnapshotsFromQuotaTable()).thenCallRealMethod();
232 ResultScanner scanner = mock(ResultScanner.class);
233 Table quotaTable = mock(Table.class);
234 when(conn.getTable(QuotaUtil.QUOTA_TABLE_NAME)).thenReturn(quotaTable);
235 when(quotaTable.getScanner(any(Scan.class))).thenReturn(scanner);
236
237 List<Result> results = new ArrayList<>();
238 Cell c = new KeyValue(toBytes("t:inviolation"), toBytes("u"), toBytes("v"), new byte[0]);
239 results.add(Result.create(Collections.singletonList(c)));
240 when(scanner.iterator()).thenReturn(results.iterator());
241 try {
242 chore.fetchSnapshotsFromQuotaTable();
243 fail("Expected an IOException, but did not receive one.");
244 } catch (IOException e) {
245
246
247 }
248 }
249 }