1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.zookeeper;
21
22
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertTrue;
25
26 import java.io.IOException;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.*;
32 import org.apache.hadoop.hbase.zookeeper.ZKTable.TableState;
33 import org.apache.zookeeper.KeeperException;
34 import org.apache.zookeeper.data.Stat;
35 import org.junit.AfterClass;
36 import org.junit.BeforeClass;
37 import org.junit.Test;
38 import org.junit.experimental.categories.Category;
39 import org.mockito.Mockito;
40
41 @Category(MediumTests.class)
42 public class TestZKTable {
43 private static final Log LOG = LogFactory.getLog(TestZKTable.class);
44 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
45
46 @BeforeClass
47 public static void setUpBeforeClass() throws Exception {
48 TEST_UTIL.startMiniZKCluster();
49 }
50
51 @AfterClass
52 public static void tearDownAfterClass() throws Exception {
53 TEST_UTIL.shutdownMiniZKCluster();
54 }
55
56 Abortable abortable = new Abortable() {
57 @Override
58 public void abort(String why, Throwable e) {
59 LOG.info(why, e);
60 }
61
62 @Override
63 public boolean isAborted() {
64 return false;
65 }
66 };
67
68 @Test
69 public void testTableStates()
70 throws ZooKeeperConnectionException, IOException, KeeperException {
71 final String name = "testDisabled";
72
73 ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
74 name, abortable, true);
75 ZKTable zkt = new ZKTable(zkw);
76 assertFalse(zkt.isEnabledTable(name));
77 assertFalse(zkt.isDisablingTable(name));
78 assertFalse(zkt.isDisabledTable(name));
79 assertFalse(zkt.isEnablingTable(name));
80 assertFalse(zkt.isDisablingOrDisabledTable(name));
81 assertFalse(zkt.isDisabledOrEnablingTable(name));
82 assertFalse(zkt.isTablePresent(name));
83 zkt.setDisablingTable(name);
84 assertTrue(zkt.isDisablingTable(name));
85 assertTrue(zkt.isDisablingOrDisabledTable(name));
86 assertFalse(zkt.getDisabledTables().contains(name));
87 assertTrue(zkt.isTablePresent(name));
88 zkt.setDisabledTable(name);
89 assertTrue(zkt.isDisabledTable(name));
90 assertTrue(zkt.isDisablingOrDisabledTable(name));
91 assertFalse(zkt.isDisablingTable(name));
92 assertTrue(zkt.getDisabledTables().contains(name));
93 assertTrue(zkt.isTablePresent(name));
94 zkt.setEnablingTable(name);
95 assertTrue(zkt.isEnablingTable(name));
96 assertTrue(zkt.isDisabledOrEnablingTable(name));
97 assertFalse(zkt.isDisabledTable(name));
98 assertFalse(zkt.getDisabledTables().contains(name));
99 assertTrue(zkt.isTablePresent(name));
100 zkt.setEnabledTable(name);
101 assertTrue(zkt.isEnabledTable(name));
102 assertFalse(zkt.isEnablingTable(name));
103 assertTrue(zkt.isTablePresent(name));
104 zkt.setDeletedTable(name);
105 assertFalse(zkt.isEnabledTable(name));
106 assertFalse(zkt.isDisablingTable(name));
107 assertFalse(zkt.isDisabledTable(name));
108 assertFalse(zkt.isEnablingTable(name));
109 assertFalse(zkt.isDisablingOrDisabledTable(name));
110 assertFalse(zkt.isDisabledOrEnablingTable(name));
111 assertFalse(zkt.isTablePresent(name));
112 }
113
114 private void runTest9294CompatibilityTest(String tableName, Configuration conf)
115 throws Exception {
116 ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
117 tableName, abortable, true);
118 ZKTable zkt = new ZKTable(zkw);
119 zkt.setEnabledTable(tableName);
120
121 assertTrue(
122 ZKTableReadOnly.getTableState(zkw, zkw.masterTableZNode, tableName) == TableState.ENABLED);
123
124 assertTrue(ZKTableReadOnly.getTableState(zkw, zkw.masterTableZNode92, tableName) == null);
125 }
126
127
128
129
130 @Test
131 public void test9294Compatibility() throws Exception {
132
133 String tableName = "test9294Compatibility";
134 runTest9294CompatibilityTest(tableName, TEST_UTIL.getConfiguration());
135
136
137 tableName = "test9294CompatibilityWithMulti";
138 Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
139 conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, true);
140 runTest9294CompatibilityTest(tableName, conf);
141 }
142
143
144
145
146 class ThrowingRecoverableZookeeper extends RecoverableZooKeeper {
147 private ZooKeeperWatcher zkw;
148 private int throwExceptionInNumOperations;
149
150 public ThrowingRecoverableZookeeper(ZooKeeperWatcher zkw) throws Exception {
151 super(ZKConfig.getZKQuorumServersString(TEST_UTIL.getConfiguration()),
152 HConstants.DEFAULT_ZK_SESSION_TIMEOUT, zkw, 3, 1000);
153 this.zkw = zkw;
154 this.throwExceptionInNumOperations = 0;
155 }
156
157 public void setThrowExceptionInNumOperations(int throwExceptionInNumOperations) {
158 this.throwExceptionInNumOperations = throwExceptionInNumOperations;
159 }
160
161 private void checkThrowKeeperException() throws KeeperException {
162 if (throwExceptionInNumOperations == 1) {
163 throwExceptionInNumOperations = 0;
164 throw new KeeperException.DataInconsistencyException();
165 }
166 if(throwExceptionInNumOperations > 0) throwExceptionInNumOperations--;
167 }
168
169 public Stat setData(String path, byte[] data, int version)
170 throws KeeperException, InterruptedException {
171 checkThrowKeeperException();
172 return zkw.getRecoverableZooKeeper().setData(path, data, version);
173 }
174
175 public void delete(String path, int version)
176 throws InterruptedException, KeeperException {
177 checkThrowKeeperException();
178 zkw.getRecoverableZooKeeper().delete(path, version);
179 }
180 }
181
182
183
184
185
186
187
188 @Test
189 public void testDisableTableRetry() throws Exception {
190 final String tableName = "testDisableTableRetry";
191
192 Configuration conf = TEST_UTIL.getConfiguration();
193
194 conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
195 ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
196 tableName, abortable, true);
197 ThrowingRecoverableZookeeper throwing = new ThrowingRecoverableZookeeper(zkw);
198 ZooKeeperWatcher spyZookeeperWatcher = Mockito.spy(zkw);
199 Mockito.doReturn(throwing).when(spyZookeeperWatcher).getRecoverableZooKeeper();
200
201 ZKTable zkt = new ZKTable(spyZookeeperWatcher);
202 zkt.setEnabledTable(tableName);
203 assertTrue(zkt.isEnabledOrDisablingTable(tableName));
204 boolean caughtExpectedException = false;
205 try {
206
207 throwing.setThrowExceptionInNumOperations(2);
208 zkt.setDisabledTable(tableName);
209 } catch (KeeperException ke) {
210 caughtExpectedException = true;
211 }
212 assertTrue(caughtExpectedException);
213 assertFalse(zkt.isDisabledTable(tableName));
214
215 zkt.setDisabledTable(tableName);
216
217 assertTrue(zkt.isDisabledTable(tableName));
218
219 assertTrue(ZKTableReadOnly.isDisabledTable(zkw, tableName));
220 }
221
222
223
224
225 @Test
226 public void testEnableTableRetry() throws Exception {
227 final String tableName = "testEnableTableRetry";
228
229 Configuration conf = TEST_UTIL.getConfiguration();
230
231 conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
232 ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
233 tableName, abortable, true);
234 ThrowingRecoverableZookeeper throwing = new ThrowingRecoverableZookeeper(zkw);
235 ZooKeeperWatcher spyZookeeperWatcher = Mockito.spy(zkw);
236 Mockito.doReturn(throwing).when(spyZookeeperWatcher).getRecoverableZooKeeper();
237
238 ZKTable zkt = new ZKTable(spyZookeeperWatcher);
239 zkt.setDisabledTable(tableName);
240 assertTrue(zkt.isDisabledTable(tableName));
241 boolean caughtExpectedException = false;
242 try {
243
244 throwing.throwExceptionInNumOperations = 2;
245 zkt.setEnabledTable(tableName);
246 } catch (KeeperException ke) {
247 caughtExpectedException = true;
248 }
249 assertTrue(caughtExpectedException);
250 assertFalse(zkt.isEnabledTable(tableName));
251
252 zkt.setEnabledTable(tableName);
253
254 assertTrue(zkt.isEnabledTable(tableName));
255
256 assertTrue(ZKTableReadOnly.isEnabledTable(zkw, tableName));
257 }
258
259
260
261
262 @Test
263 public void testDeleteTableRetry() throws Exception {
264 final String tableName = "testEnableTableRetry";
265
266 Configuration conf = TEST_UTIL.getConfiguration();
267
268 conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
269 ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
270 tableName, abortable, true);
271 ThrowingRecoverableZookeeper throwing = new ThrowingRecoverableZookeeper(zkw);
272 ZooKeeperWatcher spyZookeeperWatcher = Mockito.spy(zkw);
273 Mockito.doReturn(throwing).when(spyZookeeperWatcher).getRecoverableZooKeeper();
274
275 ZKTable zkt = new ZKTable(spyZookeeperWatcher);
276 zkt.setDisabledTable(tableName);
277 assertTrue(zkt.isDisabledTable(tableName));
278 boolean caughtExpectedException = false;
279 try {
280
281 throwing.setThrowExceptionInNumOperations(2);
282 zkt.setDeletedTable(tableName);
283 } catch (KeeperException ke) {
284 caughtExpectedException = true;
285 }
286 assertTrue(caughtExpectedException);
287 assertTrue(zkt.isTablePresent(tableName));
288
289 zkt.setDeletedTable(tableName);
290
291 assertFalse(zkt.isTablePresent(tableName));
292
293 assertFalse(ZKTableReadOnly.getDisabledTables(zkw).contains(tableName));
294 }
295
296 @org.junit.Rule
297 public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
298 new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
299 }