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.client;
21
22 import static org.junit.Assert.*;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Set;
30
31 import junit.framework.Assert;
32 import junit.framework.AssertionFailedError;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.conf.Configuration;
37 import org.apache.hadoop.fs.FileSystem;
38 import org.apache.hadoop.fs.FileUtil;
39 import org.apache.hadoop.fs.FsShell;
40 import org.apache.hadoop.fs.Path;
41 import org.apache.hadoop.hbase.HBaseTestingUtility;
42 import org.apache.hadoop.hbase.HColumnDescriptor;
43 import org.apache.hadoop.hbase.HConstants;
44 import org.apache.hadoop.hbase.HRegionInfo;
45 import org.apache.hadoop.hbase.HTableDescriptor;
46 import org.apache.hadoop.hbase.catalog.CatalogTracker;
47 import org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD;
48 import org.apache.hadoop.hbase.catalog.MetaReader;
49 import org.apache.hadoop.hbase.migration.HRegionInfo090x;
50 import org.apache.hadoop.hbase.util.Bytes;
51 import org.apache.hadoop.hbase.util.Writables;
52 import org.junit.AfterClass;
53 import org.junit.BeforeClass;
54 import org.junit.Test;
55
56
57
58
59
60 public class TestMetaMigrationRemovingHTD {
61 static final Log LOG = LogFactory.getLog(TestMetaMigrationRemovingHTD.class);
62 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
63 private final static String TESTTABLE = "TestTable";
64 private final static int ROWCOUNT = 100;
65
66 @BeforeClass
67 public static void setUpBeforeClass() throws Exception {
68
69
70
71 TEST_UTIL.startMiniZKCluster();
72 TEST_UTIL.startMiniDFSCluster(1);
73 Path testdir = TEST_UTIL.getDataTestDir("TestMetaMigrationRemovingHTD");
74
75 File untar = untar(new File(testdir.toString()));
76
77 Configuration conf = TEST_UTIL.getConfiguration();
78 FsShell shell = new FsShell(conf);
79 FileSystem fs = FileSystem.get(conf);
80
81 Path homedir = fs.getHomeDirectory();
82 doFsCommand(shell,
83 new String [] {"-put", untar.toURI().toString(), homedir.toString()});
84
85 doFsCommand(shell, new String [] {"-lsr", "/"});
86 TEST_UTIL.startMiniHBaseCluster(1, 1);
87
88
89
90 HTable t = new HTable(TEST_UTIL.getConfiguration(), TESTTABLE);
91 ResultScanner scanner = t.getScanner(new Scan());
92 int count = 0;
93 while (scanner.next() != null) {
94 count++;
95 }
96
97
98 Assert.assertEquals(ROWCOUNT, count);
99 }
100
101 private static File untar(final File testdir) throws IOException {
102
103 final String datafile = "hbase-4388-root.dir";
104 String srcTarFile =
105 System.getProperty("project.build.testSourceDirectory", "src/test") +
106 File.separator + "data" + File.separator + datafile + ".tgz";
107 File homedir = new File(testdir.toString());
108 File tgtUntarDir = new File(homedir, datafile);
109 if (tgtUntarDir.exists()) {
110 if (!FileUtil.fullyDelete(tgtUntarDir)) {
111 throw new IOException("Failed delete of " + tgtUntarDir.toString());
112 }
113 }
114 LOG.info("Untarring " + srcTarFile + " into " + homedir.toString());
115 FileUtil.unTar(new File(srcTarFile), homedir);
116 Assert.assertTrue(tgtUntarDir.exists());
117 return tgtUntarDir;
118 }
119
120 private static void doFsCommand(final FsShell shell, final String [] args)
121 throws Exception {
122
123 int errcode = shell.run(args);
124 if (errcode != 0) throw new IOException("Failed put; errcode=" + errcode);
125 }
126
127
128
129
130 @AfterClass
131 public static void tearDownAfterClass() throws Exception {
132 TEST_UTIL.shutdownMiniCluster();
133 }
134
135 @Test
136 public void testMetaUpdatedFlagInROOT() throws Exception {
137 boolean metaUpdated = MetaMigrationRemovingHTD.
138 isMetaHRIUpdated(TEST_UTIL.getMiniHBaseCluster().getMaster());
139 assertEquals(true, metaUpdated);
140 }
141
142 @Test
143 public void testMetaMigration() throws Exception {
144 LOG.info("Starting testMetaWithLegacyHRI");
145 final byte [] FAMILY = Bytes.toBytes("family");
146 HTableDescriptor htd = new HTableDescriptor("testMetaMigration");
147 HColumnDescriptor hcd = new HColumnDescriptor(FAMILY);
148 htd.addFamily(hcd);
149 Configuration conf = TEST_UTIL.getConfiguration();
150 createMultiRegionsWithLegacyHRI(conf, htd, FAMILY,
151 new byte[][]{
152 HConstants.EMPTY_START_ROW,
153 Bytes.toBytes("region_a"),
154 Bytes.toBytes("region_b")});
155 CatalogTracker ct =
156 TEST_UTIL.getMiniHBaseCluster().getMaster().getCatalogTracker();
157
158 undoVersionInMeta();
159 MetaReader.fullScanMetaAndPrint(ct);
160 LOG.info("Meta Print completed.testUpdatesOnMetaWithLegacyHRI");
161
162 Set<HTableDescriptor> htds =
163 MetaMigrationRemovingHTD.updateMetaWithNewRegionInfo(
164 TEST_UTIL.getHBaseCluster().getMaster());
165 MetaReader.fullScanMetaAndPrint(ct);
166
167 assertEquals(1, htds.size());
168 assertTrue(htds.contains(htd));
169
170 boolean metaUpdated =
171 MetaMigrationRemovingHTD.isMetaHRIUpdated(
172 TEST_UTIL.getMiniHBaseCluster().getMaster());
173 assertEquals(true, metaUpdated);
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188 @Test
189 public void testMasterCrashDuringMetaMigration() throws Exception {
190 final byte[] FAMILY = Bytes.toBytes("family");
191 HTableDescriptor htd = new HTableDescriptor("testMasterCrashDuringMetaMigration");
192 HColumnDescriptor hcd = new HColumnDescriptor(FAMILY);
193 htd.addFamily(hcd);
194 Configuration conf = TEST_UTIL.getConfiguration();
195
196 createMultiRegionsWithNewHRI(conf, htd, FAMILY, 10);
197
198 createMultiRegionsWithLegacyHRI(conf, htd, FAMILY, 10);
199 CatalogTracker ct =
200 TEST_UTIL.getMiniHBaseCluster().getMaster().getCatalogTracker();
201
202 undoVersionInMeta();
203 MetaMigrationRemovingHTD.updateRootWithMetaMigrationStatus(ct);
204
205 LOG.info("Meta Print completed.testUpdatesOnMetaWithLegacyHRI");
206
207 Set<HTableDescriptor> htds =
208 MetaMigrationRemovingHTD.updateMetaWithNewRegionInfo(
209 TEST_UTIL.getHBaseCluster().getMaster());
210 assertEquals(1, htds.size());
211 assertTrue(htds.contains(htd));
212
213 boolean metaUpdated = MetaMigrationRemovingHTD.
214 isMetaHRIUpdated(TEST_UTIL.getMiniHBaseCluster().getMaster());
215 assertEquals(true, metaUpdated);
216 LOG.info("END testMetaWithLegacyHRI");
217 }
218
219 private void undoVersionInMeta() throws IOException {
220 Delete d = new Delete(HRegionInfo.ROOT_REGIONINFO.getRegionName());
221
222 d.deleteColumn(HConstants.CATALOG_FAMILY, HConstants.META_VERSION_QUALIFIER);
223 HTable rootTable =
224 new HTable(TEST_UTIL.getConfiguration(), HConstants.ROOT_TABLE_NAME);
225 try {
226 rootTable.delete(d);
227 } finally {
228 rootTable.close();
229 }
230 }
231
232 public static void assertEquals(int expected, int actual) {
233 if (expected != actual) {
234 throw new AssertionFailedError("expected:<" +
235 expected + "> but was:<" +
236 actual + ">");
237 }
238 }
239
240 public static void assertEquals(boolean expected, boolean actual) {
241 if (expected != actual) {
242 throw new AssertionFailedError("expected:<" +
243 expected + "> but was:<" +
244 actual + ">");
245 }
246 }
247
248
249
250
251
252
253
254
255
256
257
258
259 public int createMultiRegionsWithLegacyHRI(final Configuration c,
260 final HTableDescriptor htd, final byte [] family, int numRegions)
261 throws IOException {
262 if (numRegions < 3) throw new IOException("Must create at least 3 regions");
263 byte [] startKey = Bytes.toBytes("aaaaa");
264 byte [] endKey = Bytes.toBytes("zzzzz");
265 byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
266 byte [][] regionStartKeys = new byte[splitKeys.length+1][];
267 for (int i=0;i<splitKeys.length;i++) {
268 regionStartKeys[i+1] = splitKeys[i];
269 }
270 regionStartKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
271 return createMultiRegionsWithLegacyHRI(c, htd, family, regionStartKeys);
272 }
273
274
275
276
277
278
279
280
281
282
283
284 public int createMultiRegionsWithLegacyHRI(final Configuration c,
285 final HTableDescriptor htd, final byte[] columnFamily, byte [][] startKeys)
286 throws IOException {
287 Arrays.sort(startKeys, Bytes.BYTES_COMPARATOR);
288 HTable meta = new HTable(c, HConstants.META_TABLE_NAME);
289 if(!htd.hasFamily(columnFamily)) {
290 HColumnDescriptor hcd = new HColumnDescriptor(columnFamily);
291 htd.addFamily(hcd);
292 }
293 List<HRegionInfo090x> newRegions
294 = new ArrayList<HRegionInfo090x>(startKeys.length);
295 int count = 0;
296 for (int i = 0; i < startKeys.length; i++) {
297 int j = (i + 1) % startKeys.length;
298 HRegionInfo090x hri = new HRegionInfo090x(htd,
299 startKeys[i], startKeys[j]);
300 Put put = new Put(hri.getRegionName());
301 put.setWriteToWAL(false);
302 put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
303 Writables.getBytes(hri));
304 meta.put(put);
305 LOG.info("createMultiRegions: PUT inserted " + hri.toString());
306
307 newRegions.add(hri);
308 count++;
309 }
310 return count;
311 }
312
313 int createMultiRegionsWithNewHRI(final Configuration c,
314 final HTableDescriptor htd, final byte [] family, int numRegions)
315 throws IOException {
316 if (numRegions < 3) throw new IOException("Must create at least 3 regions");
317 byte [] startKey = Bytes.toBytes("aaaaa");
318 byte [] endKey = Bytes.toBytes("zzzzz");
319 byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
320 byte [][] regionStartKeys = new byte[splitKeys.length+1][];
321 for (int i=0;i<splitKeys.length;i++) {
322 regionStartKeys[i+1] = splitKeys[i];
323 }
324 regionStartKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
325 return createMultiRegionsWithNewHRI(c, htd, family, regionStartKeys);
326 }
327
328 int createMultiRegionsWithNewHRI(final Configuration c, final HTableDescriptor htd,
329 final byte[] columnFamily, byte [][] startKeys)
330 throws IOException {
331 Arrays.sort(startKeys, Bytes.BYTES_COMPARATOR);
332 HTable meta = new HTable(c, HConstants.META_TABLE_NAME);
333 if(!htd.hasFamily(columnFamily)) {
334 HColumnDescriptor hcd = new HColumnDescriptor(columnFamily);
335 htd.addFamily(hcd);
336 }
337 List<HRegionInfo> newRegions
338 = new ArrayList<HRegionInfo>(startKeys.length);
339 int count = 0;
340 for (int i = 0; i < startKeys.length; i++) {
341 int j = (i + 1) % startKeys.length;
342 HRegionInfo hri = new HRegionInfo(htd.getName(),
343 startKeys[i], startKeys[j]);
344 Put put = new Put(hri.getRegionName());
345 put.setWriteToWAL(false);
346 put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
347 Writables.getBytes(hri));
348 meta.put(put);
349 LOG.info("createMultiRegions: PUT inserted " + hri.toString());
350
351 newRegions.add(hri);
352 count++;
353 }
354 return count;
355 }
356 }