1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.replication;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNull;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.fs.Path;
33 import org.apache.hadoop.hbase.ServerName;
34 import org.apache.hadoop.hbase.util.Pair;
35 import org.apache.hadoop.hbase.zookeeper.ZKConfig;
36 import org.apache.zookeeper.KeeperException;
37 import org.junit.Before;
38 import org.junit.Test;
39
40
41
42
43
44 public abstract class TestReplicationStateBasic {
45
46 protected ReplicationQueues rq1;
47 protected ReplicationQueues rq2;
48 protected ReplicationQueues rq3;
49 protected ReplicationQueuesClient rqc;
50 protected String server1 = ServerName.valueOf("hostname1.example.org", 1234, -1L).toString();
51 protected String server2 = ServerName.valueOf("hostname2.example.org", 1234, -1L).toString();
52 protected String server3 = ServerName.valueOf("hostname3.example.org", 1234, -1L).toString();
53 protected ReplicationPeers rp;
54 protected static final String ID_ONE = "1";
55 protected static final String ID_TWO = "2";
56 protected static String KEY_ONE;
57 protected static String KEY_TWO;
58
59
60 protected String OUR_KEY;
61
62 protected static int zkTimeoutCount;
63 protected static final int ZK_MAX_COUNT = 300;
64 protected static final int ZK_SLEEP_INTERVAL = 100;
65
66 private static final Log LOG = LogFactory.getLog(TestReplicationStateBasic.class);
67
68 @Before
69 public void setUp() {
70 zkTimeoutCount = 0;
71 }
72
73 @Test
74 public void testReplicationQueuesClient() throws ReplicationException, KeeperException {
75 rqc.init();
76
77 assertEquals(0, rqc.getListOfReplicators().size());
78 assertNull(rqc.getLogsInQueue(server1, "qId1"));
79 assertNull(rqc.getAllQueues(server1));
80
81
82
83
84
85 rq1.init(server1);
86 rq2.init(server2);
87 rq1.addLog("qId1", "trash");
88 rq1.removeLog("qId1", "trash");
89 rq1.addLog("qId2", "filename1");
90 rq1.addLog("qId3", "filename2");
91 rq1.addLog("qId3", "filename3");
92 rq2.addLog("trash", "trash");
93 rq2.removeQueue("trash");
94
95 List<String> reps = rqc.getListOfReplicators();
96 assertEquals(2, reps.size());
97 assertTrue(server1, reps.contains(server1));
98 assertTrue(server2, reps.contains(server2));
99
100 assertNull(rqc.getLogsInQueue("bogus", "bogus"));
101 assertNull(rqc.getLogsInQueue(server1, "bogus"));
102 assertEquals(0, rqc.getLogsInQueue(server1, "qId1").size());
103 assertEquals(1, rqc.getLogsInQueue(server1, "qId2").size());
104 assertEquals("filename1", rqc.getLogsInQueue(server1, "qId2").get(0));
105
106 assertNull(rqc.getAllQueues("bogus"));
107 assertEquals(0, rqc.getAllQueues(server2).size());
108 List<String> list = rqc.getAllQueues(server1);
109 assertEquals(3, list.size());
110 assertTrue(list.contains("qId2"));
111 assertTrue(list.contains("qId3"));
112 }
113
114 @Test
115 public void testReplicationQueues() throws ReplicationException {
116 rq1.init(server1);
117 rq2.init(server2);
118 rq3.init(server3);
119
120 rp.init();
121
122
123 assertEquals(3, rq1.getListOfReplicators().size());
124 rq1.removeQueue("bogus");
125 rq1.removeAllQueues();
126 assertNull(rq1.getAllQueues());
127 assertEquals(0, rq1.getLogPosition("bogus", "bogus"));
128 assertNull(rq1.getLogsInQueue("bogus"));
129 assertNull(rq1.getUnClaimedQueueIds(ServerName.valueOf("bogus", 1234, -1L).toString()));
130
131 rq1.setLogPosition("bogus", "bogus", 5L);
132
133 populateQueues();
134
135 assertEquals(3, rq1.getListOfReplicators().size());
136 assertEquals(0, rq2.getLogsInQueue("qId1").size());
137 assertEquals(5, rq3.getLogsInQueue("qId5").size());
138 assertEquals(0, rq3.getLogPosition("qId1", "filename0"));
139 rq3.setLogPosition("qId5", "filename4", 354L);
140 assertEquals(354L, rq3.getLogPosition("qId5", "filename4"));
141
142 assertEquals(5, rq3.getLogsInQueue("qId5").size());
143 assertEquals(0, rq2.getLogsInQueue("qId1").size());
144 assertEquals(0, rq1.getAllQueues().size());
145 assertEquals(1, rq2.getAllQueues().size());
146 assertEquals(5, rq3.getAllQueues().size());
147
148 assertEquals(0, rq3.getUnClaimedQueueIds(server1).size());
149 rq3.removeReplicatorIfQueueIsEmpty(server1);
150 assertEquals(2, rq3.getListOfReplicators().size());
151
152 List<String> queues = rq2.getUnClaimedQueueIds(server3);
153 assertEquals(5, queues.size());
154 for(String queue: queues) {
155 rq2.claimQueue(server3, queue);
156 }
157 rq2.removeReplicatorIfQueueIsEmpty(server3);
158 assertEquals(1, rq2.getListOfReplicators().size());
159
160
161 assertNull(rq2.getUnClaimedQueueIds(server2));
162 rq2.removeReplicatorIfQueueIsEmpty(server2);
163
164 assertEquals(6, rq2.getAllQueues().size());
165
166 rq2.removeAllQueues();
167
168 assertEquals(0, rq2.getListOfReplicators().size());
169 }
170
171 @Test
172 public void testLogRemovalWithNoZnode() throws ReplicationException {
173 rq1.init(server1);
174 Exception expectedException = null;
175 try {
176 rq1.removeLog("bogus", "bogus");
177 } catch (ReplicationException e) {
178 expectedException = e;
179 }
180
181 assertTrue(expectedException instanceof ReplicationSourceWithoutPeerException);
182 }
183
184 @Test
185 public void testInvalidClusterKeys() throws ReplicationException, KeeperException {
186 rp.init();
187
188 try {
189 rp.addPeer(ID_ONE,
190 new ReplicationPeerConfig().setClusterKey("hostname1.example.org:1234:hbase"));
191 fail("Should throw an IllegalArgumentException because "
192 + "zookeeper.znode.parent is missing leading '/'.");
193 } catch (IllegalArgumentException e) {
194
195 }
196
197 try {
198 rp.addPeer(ID_ONE,
199 new ReplicationPeerConfig().setClusterKey("hostname1.example.org:1234:/"));
200 fail("Should throw an IllegalArgumentException because zookeeper.znode.parent is missing.");
201 } catch (IllegalArgumentException e) {
202
203 }
204
205 try {
206 rp.addPeer(ID_ONE,
207 new ReplicationPeerConfig().setClusterKey("hostname1.example.org::/hbase"));
208 fail("Should throw an IllegalArgumentException because "
209 + "hbase.zookeeper.property.clientPort is missing.");
210 } catch (IllegalArgumentException e) {
211
212 }
213 }
214
215 @Test
216 public void testHfileRefsReplicationQueues() throws ReplicationException, KeeperException {
217 rp.init();
218 rq1.init(server1);
219 rqc.init();
220
221 List<Pair<Path, Path>> files1 = new ArrayList<>(3);
222 files1.add(new Pair<Path, Path>(null, new Path("file_1")));
223 files1.add(new Pair<Path, Path>(null, new Path("file_2")));
224 files1.add(new Pair<Path, Path>(null, new Path("file_3")));
225 assertNull(rqc.getReplicableHFiles(ID_ONE));
226 assertEquals(0, rqc.getAllPeersFromHFileRefsQueue().size());
227 rp.addPeer(ID_ONE, new ReplicationPeerConfig().setClusterKey(KEY_ONE));
228 rq1.addPeerToHFileRefs(ID_ONE);
229 rq1.addHFileRefs(ID_ONE, files1);
230 assertEquals(1, rqc.getAllPeersFromHFileRefsQueue().size());
231 assertEquals(3, rqc.getReplicableHFiles(ID_ONE).size());
232 List<String> hfiles2 = new ArrayList<>();
233 for (Pair<Path, Path> p : files1) {
234 hfiles2.add(p.getSecond().getName());
235 }
236 String removedString = hfiles2.remove(0);
237 rq1.removeHFileRefs(ID_ONE, hfiles2);
238 assertEquals(1, rqc.getReplicableHFiles(ID_ONE).size());
239 hfiles2 = new ArrayList<>(1);
240 hfiles2.add(removedString);
241 rq1.removeHFileRefs(ID_ONE, hfiles2);
242 assertEquals(0, rqc.getReplicableHFiles(ID_ONE).size());
243 rp.removePeer(ID_ONE);
244 }
245
246 @Test
247 public void testRemovePeerForHFileRefs() throws ReplicationException, KeeperException {
248 rq1.init(server1);
249 rqc.init();
250
251 rp.init();
252 rp.addPeer(ID_ONE, new ReplicationPeerConfig().setClusterKey(KEY_ONE));
253 rp.addPeer(ID_TWO, new ReplicationPeerConfig().setClusterKey(KEY_TWO));
254
255 List<Pair<Path, Path>> files1 = new ArrayList<>(3);
256 files1.add(new Pair<Path, Path>(null, new Path("file_1")));
257 files1.add(new Pair<Path, Path>(null, new Path("file_2")));
258 files1.add(new Pair<Path, Path>(null, new Path("file_3")));
259 rq1.addPeerToHFileRefs(ID_ONE);
260 rq1.addHFileRefs(ID_ONE, files1);
261 rq1.addPeerToHFileRefs(ID_TWO);
262 rq1.addHFileRefs(ID_TWO, files1);
263 assertEquals(2, rqc.getAllPeersFromHFileRefsQueue().size());
264 assertEquals(3, rqc.getReplicableHFiles(ID_ONE).size());
265 assertEquals(3, rqc.getReplicableHFiles(ID_TWO).size());
266
267 rp.removePeer(ID_ONE);
268 rq1.removePeerFromHFileRefs(ID_ONE);
269 assertEquals(1, rqc.getAllPeersFromHFileRefsQueue().size());
270 assertNull(rqc.getReplicableHFiles(ID_ONE));
271 assertEquals(3, rqc.getReplicableHFiles(ID_TWO).size());
272
273 rp.removePeer(ID_TWO);
274 rq1.removePeerFromHFileRefs(ID_TWO);
275 assertEquals(0, rqc.getAllPeersFromHFileRefsQueue().size());
276 assertNull(rqc.getReplicableHFiles(ID_TWO));
277 }
278
279 @Test
280 public void testReplicationPeers() throws Exception {
281 rp.init();
282
283
284 try {
285 rp.removePeer("bogus");
286 fail("Should have thrown an IllegalArgumentException when passed a bogus peerId");
287 } catch (IllegalArgumentException e) {
288 }
289 try {
290 rp.enablePeer("bogus");
291 fail("Should have thrown an IllegalArgumentException when passed a bogus peerId");
292 } catch (IllegalArgumentException e) {
293 }
294 try {
295 rp.disablePeer("bogus");
296 fail("Should have thrown an IllegalArgumentException when passed a bogus peerId");
297 } catch (IllegalArgumentException e) {
298 }
299 try {
300 rp.getStatusOfPeer("bogus");
301 fail("Should have thrown an IllegalArgumentException when passed a bogus peerId");
302 } catch (IllegalArgumentException e) {
303 }
304 assertFalse(rp.peerAdded("bogus"));
305 rp.peerRemoved("bogus");
306
307 assertNull(rp.getPeerConf("bogus"));
308 assertNumberOfPeers(0);
309
310
311 rp.addPeer(ID_ONE, new ReplicationPeerConfig().setClusterKey(KEY_ONE));
312 assertNumberOfPeers(1);
313 rp.addPeer(ID_TWO, new ReplicationPeerConfig().setClusterKey(KEY_TWO));
314 assertNumberOfPeers(2);
315
316
317 try {
318 rp.getStatusOfPeer(ID_ONE);
319 fail("There are no connected peers, should have thrown an IllegalArgumentException");
320 } catch (IllegalArgumentException e) {
321 }
322 assertEquals(KEY_ONE, ZKConfig.getZooKeeperClusterKey(rp.getPeerConf(ID_ONE).getSecond()));
323 rp.removePeer(ID_ONE);
324 rp.peerRemoved(ID_ONE);
325 assertNumberOfPeers(1);
326
327
328 rp.addPeer(ID_ONE, new ReplicationPeerConfig().setClusterKey(KEY_ONE));
329 rp.peerAdded(ID_ONE);
330 assertNumberOfPeers(2);
331 assertTrue(rp.getStatusOfPeer(ID_ONE));
332 rp.disablePeer(ID_ONE);
333 assertConnectedPeerStatus(false, ID_ONE);
334 rp.enablePeer(ID_ONE);
335 assertConnectedPeerStatus(true, ID_ONE);
336
337
338 rp.peerRemoved(ID_ONE);
339 assertNumberOfPeers(2);
340 try {
341 rp.getStatusOfPeer(ID_ONE);
342 fail("There are no connected peers, should have thrown an IllegalArgumentException");
343 } catch (IllegalArgumentException e) {
344 }
345 }
346
347 protected void assertConnectedPeerStatus(boolean status, String peerId) throws Exception {
348
349 if (status != rp.getStatusOfPeerFromBackingStore(peerId)) {
350 fail("ConnectedPeerStatus was " + !status + " but expected " + status + " in ZK");
351 }
352 while (true) {
353 if (status == rp.getStatusOfPeer(peerId)) {
354 return;
355 }
356 if (zkTimeoutCount < ZK_MAX_COUNT) {
357 LOG.debug("ConnectedPeerStatus was " + !status + " but expected " + status
358 + ", sleeping and trying again.");
359 Thread.sleep(ZK_SLEEP_INTERVAL);
360 } else {
361 fail("Timed out waiting for ConnectedPeerStatus to be " + status);
362 }
363 }
364 }
365
366 protected void assertNumberOfPeers(int total) {
367 assertEquals(total, rp.getAllPeerConfigs().size());
368 assertEquals(total, rp.getAllPeerIds().size());
369 assertEquals(total, rp.getAllPeerIds().size());
370 }
371
372
373
374
375
376 protected void populateQueues() throws ReplicationException {
377 rq1.addLog("trash", "trash");
378 rq1.removeQueue("trash");
379
380 rq2.addLog("qId1", "trash");
381 rq2.removeLog("qId1", "trash");
382
383 for (int i = 1; i < 6; i++) {
384 for (int j = 0; j < i; j++) {
385 rq3.addLog("qId" + i, "filename" + j);
386 }
387
388 rp.addPeer("qId" + i, new ReplicationPeerConfig().setClusterKey("localhost:2818:/bogus" + i));
389 }
390 }
391 }
392