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 org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.hbase.testclassification.LargeTests;
24 import org.apache.hadoop.hbase.HColumnDescriptor;
25 import org.apache.hadoop.hbase.HConstants;
26 import org.apache.hadoop.hbase.HTableDescriptor;
27 import org.apache.hadoop.hbase.NamespaceDescriptor;
28 import org.apache.hadoop.hbase.TableName;
29 import org.apache.hadoop.hbase.client.Admin;
30 import org.apache.hadoop.hbase.client.Connection;
31 import org.apache.hadoop.hbase.client.ConnectionFactory;
32 import org.apache.hadoop.hbase.client.Get;
33 import org.apache.hadoop.hbase.client.Put;
34 import org.apache.hadoop.hbase.client.Result;
35 import org.apache.hadoop.hbase.client.ResultScanner;
36 import org.apache.hadoop.hbase.client.Scan;
37 import org.apache.hadoop.hbase.client.Table;
38 import org.apache.hadoop.hbase.util.Bytes;
39 import org.apache.hadoop.hbase.util.JVMClusterUtil;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.junit.experimental.categories.Category;
43
44 import static org.junit.Assert.assertArrayEquals;
45 import static org.junit.Assert.fail;
46
47 import java.util.ArrayList;
48 import java.util.List;
49
50 @Category(LargeTests.class)
51 public class TestReplicationDroppedTables extends TestReplicationBase {
52 private static final Log LOG = LogFactory.getLog(TestReplicationDroppedTables.class);
53
54
55
56
57 @Before
58 public void setUp() throws Exception {
59
60
61 for ( JVMClusterUtil.RegionServerThread r :
62 utility1.getHBaseCluster().getRegionServerThreads()) {
63 utility1.getHBaseAdmin().rollWALWriter(r.getRegionServer().getServerName());
64 }
65 int rowCount = utility1.countRows(tableName);
66 utility1.deleteTableData(tableName);
67
68
69
70
71
72 Scan scan = new Scan();
73 int lastCount = 0;
74 for (int i = 0; i < NB_RETRIES; i++) {
75 if (i==NB_RETRIES-1) {
76 fail("Waited too much time for truncate");
77 }
78 ResultScanner scanner = htable2.getScanner(scan);
79 Result[] res = scanner.next(rowCount);
80 scanner.close();
81 if (res.length != 0) {
82 if (res.length < lastCount) {
83 i--;
84 }
85 lastCount = res.length;
86 LOG.info("Still got " + res.length + " rows");
87 Thread.sleep(SLEEP_TIME);
88 } else {
89 break;
90 }
91 }
92 }
93
94 @Test(timeout = 600000)
95 public void testEditsStuckBehindDroppedTable() throws Exception {
96
97
98
99 testEditsBehindDroppedTable(false, "test_dropped");
100 }
101
102 @Test(timeout = 600000)
103 public void testEditsDroppedWithDroppedTable() throws Exception {
104
105
106 testEditsBehindDroppedTable(true, "test_dropped");
107 }
108
109 @Test(timeout = 600000)
110 public void testEditsDroppedWithDroppedTableNS() throws Exception {
111
112 Connection connection1 = ConnectionFactory.createConnection(conf1);
113 try (Admin admin1 = connection1.getAdmin()) {
114 admin1.createNamespace(NamespaceDescriptor.create("NS").build());
115 }
116 Connection connection2 = ConnectionFactory.createConnection(conf2);
117 try (Admin admin2 = connection2.getAdmin()) {
118 admin2.createNamespace(NamespaceDescriptor.create("NS").build());
119 }
120 testEditsBehindDroppedTable(true, "NS:test_dropped");
121 }
122
123 private void testEditsBehindDroppedTable(boolean allowProceeding, String tName) throws Exception {
124 conf1.setBoolean(HConstants.REPLICATION_DROP_ON_DELETED_TABLE_KEY, allowProceeding);
125 conf1.setInt(HConstants.REPLICATION_SOURCE_MAXTHREADS_KEY, 1);
126
127
128
129 utility1.shutdownMiniHBaseCluster();
130 utility1.startMiniHBaseCluster(1, 1);
131
132 TableName tablename = TableName.valueOf(tName);
133 byte[] familyname = Bytes.toBytes("fam");
134 byte[] row = Bytes.toBytes("row");
135
136 HTableDescriptor table = new HTableDescriptor(tablename);
137 HColumnDescriptor fam = new HColumnDescriptor(familyname);
138 fam.setScope(HConstants.REPLICATION_SCOPE_GLOBAL);
139 table.addFamily(fam);
140
141 Connection connection1 = ConnectionFactory.createConnection(conf1);
142 Connection connection2 = ConnectionFactory.createConnection(conf2);
143 try (Admin admin1 = connection1.getAdmin()) {
144 admin1.createTable(table);
145 }
146 try (Admin admin2 = connection2.getAdmin()) {
147 admin2.createTable(table);
148 }
149 utility1.waitUntilAllRegionsAssigned(tablename);
150 utility2.waitUntilAllRegionsAssigned(tablename);
151
152 Table lHtable1 = utility1.getConnection().getTable(tablename);
153
154
155 admin.disablePeer(PEER_ID);
156
157
158
159
160 byte[] rowkey = Bytes.toBytes(0+" put on table to be dropped");
161 Put put = new Put(rowkey);
162 put.addColumn(familyname, row, row);
163 lHtable1.put(put);
164
165 rowkey = Bytes.toBytes("normal put");
166 put = new Put(rowkey);
167 put.addColumn(famName, row, row);
168 htable1.put(put);
169
170 try (Admin admin1 = connection1.getAdmin()) {
171 admin1.disableTable(tablename);
172 admin1.deleteTable(tablename);
173 }
174 try (Admin admin2 = connection2.getAdmin()) {
175 admin2.disableTable(tablename);
176 admin2.deleteTable(tablename);
177 }
178
179 admin.enablePeer(PEER_ID);
180 if (allowProceeding) {
181
182 verifyReplicationProceeded(rowkey);
183 } else {
184 verifyReplicationStuck(rowkey);
185 }
186
187 conf1.setBoolean(HConstants.REPLICATION_DROP_ON_DELETED_TABLE_KEY, false);
188 }
189
190 @Test(timeout = 600000)
191 public void testEditsBehindDroppedTableTiming() throws Exception {
192 conf1.setBoolean(HConstants.REPLICATION_DROP_ON_DELETED_TABLE_KEY, true);
193 conf1.setInt(HConstants.REPLICATION_SOURCE_MAXTHREADS_KEY, 1);
194
195
196
197 utility1.shutdownMiniHBaseCluster();
198 utility1.startMiniHBaseCluster(1, 1);
199
200 TableName tablename = TableName.valueOf("testdroppedtimed");
201 byte[] familyname = Bytes.toBytes("fam");
202 byte[] row = Bytes.toBytes("row");
203
204 HTableDescriptor table = new HTableDescriptor(tablename);
205 HColumnDescriptor fam = new HColumnDescriptor(familyname);
206 fam.setScope(HConstants.REPLICATION_SCOPE_GLOBAL);
207 table.addFamily(fam);
208
209 Connection connection1 = ConnectionFactory.createConnection(conf1);
210 Connection connection2 = ConnectionFactory.createConnection(conf2);
211 try (Admin admin1 = connection1.getAdmin()) {
212 admin1.createTable(table);
213 }
214 try (Admin admin2 = connection2.getAdmin()) {
215 admin2.createTable(table);
216 }
217 utility1.waitUntilAllRegionsAssigned(tablename);
218 utility2.waitUntilAllRegionsAssigned(tablename);
219
220 Table lHtable1 = utility1.getConnection().getTable(tablename);
221
222
223 admin.disablePeer(PEER_ID);
224
225
226
227
228 byte[] rowkey = Bytes.toBytes(0+" put on table to be dropped");
229 Put put = new Put(rowkey);
230 put.addColumn(familyname, row, row);
231 lHtable1.put(put);
232
233 rowkey = Bytes.toBytes("normal put");
234 put = new Put(rowkey);
235 put.addColumn(famName, row, row);
236 htable1.put(put);
237
238 try (Admin admin2 = connection2.getAdmin()) {
239 admin2.disableTable(tablename);
240 admin2.deleteTable(tablename);
241 }
242
243 admin.enablePeer(PEER_ID);
244
245
246 try (Admin admin1 = connection1.getAdmin()) {
247
248 verifyReplicationStuck(rowkey);
249
250 admin1.disableTable(tablename);
251
252 verifyReplicationStuck(rowkey);
253
254 admin1.deleteTable(tablename);
255
256
257 verifyReplicationProceeded(rowkey);
258 }
259
260 conf1.setBoolean(HConstants.REPLICATION_DROP_ON_DELETED_TABLE_KEY, false);
261 }
262
263 private void verifyReplicationProceeded(byte[] rowkey) throws Exception {
264 Get get = new Get(rowkey);
265 for (int i = 0; i < NB_RETRIES; i++) {
266 if (i==NB_RETRIES-1) {
267 fail("Waited too much time for put replication");
268 }
269 Result res = htable2.get(get);
270 if (res.size() == 0) {
271 LOG.info("Row not available");
272 Thread.sleep(SLEEP_TIME);
273 } else {
274 assertArrayEquals(res.getRow(), rowkey);
275 break;
276 }
277 }
278 }
279
280 private void verifyReplicationStuck(byte[] rowkey) throws Exception {
281 Get get = new Get(rowkey);
282 for (int i = 0; i < NB_RETRIES; i++) {
283 Result res = htable2.get(get);
284 if (res.size() >= 1) {
285 fail("Edit should have been stuck behind dropped tables");
286 } else {
287 LOG.info("Row not replicated, let's wait a bit more...");
288 Thread.sleep(SLEEP_TIME);
289 }
290 }
291 }
292 }