View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.util.hbck;
19  
20  import static org.apache.hadoop.hbase.util.hbck.HbckTestingUtil.assertErrors;
21  import static org.apache.hadoop.hbase.util.hbck.HbckTestingUtil.doFsck;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertNotNull;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.io.IOException;
27  import java.util.Arrays;
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.FileStatus;
33  import org.apache.hadoop.fs.FileSystem;
34  import org.apache.hadoop.fs.Path;
35  import org.apache.hadoop.hbase.HConstants;
36  import org.apache.hadoop.hbase.HTableDescriptor;
37  import org.apache.hadoop.hbase.NamespaceDescriptor;
38  import org.apache.hadoop.hbase.TableName;
39  import org.apache.hadoop.hbase.testclassification.MediumTests;
40  import org.apache.hadoop.hbase.client.Admin;
41  import org.apache.hadoop.hbase.client.Connection;
42  import org.apache.hadoop.hbase.client.ConnectionFactory;
43  import org.apache.hadoop.hbase.util.Bytes;
44  import org.apache.hadoop.hbase.util.FSUtils;
45  import org.apache.hadoop.hbase.util.HBaseFsck;
46  import org.apache.hadoop.hbase.util.HBaseFsck.ErrorReporter.ERROR_CODE;
47  import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
48  import org.junit.Test;
49  import org.junit.experimental.categories.Category;
50  
51  /**
52   * This builds a table, removes info from meta, and then rebuilds meta.
53   */
54  @Category(MediumTests.class)
55  public class TestOfflineMetaRebuildBase extends OfflineMetaRebuildTestCore {
56    private static final Log LOG = LogFactory.getLog(TestOfflineMetaRebuildBase.class);
57  
58    @Test(timeout = 120000)
59    public void testMetaRebuild() throws Exception {
60      wipeOutMeta();
61  
62      // is meta really messed up?
63      assertEquals(1, scanMeta());
64      assertErrors(doFsck(conf, false),
65          new ERROR_CODE[] {
66              ERROR_CODE.NOT_IN_META_OR_DEPLOYED,
67              ERROR_CODE.NOT_IN_META_OR_DEPLOYED,
68              ERROR_CODE.NOT_IN_META_OR_DEPLOYED,
69              ERROR_CODE.NOT_IN_META_OR_DEPLOYED});
70      // Note, would like to check # of tables, but this takes a while to time
71      // out.
72  
73      // shutdown the minicluster
74      TEST_UTIL.shutdownMiniHBaseCluster();
75      TEST_UTIL.shutdownMiniZKCluster();
76  
77      // rebuild meta table from scratch
78      HBaseFsck fsck = new HBaseFsck(conf);
79      assertTrue(fsck.rebuildMeta(false));
80      assertTrue("HBCK meta recovery WAL directory exist.", validateHBCKMetaRecoveryWALDir());
81  
82      // bring up the minicluster
83      TEST_UTIL.startMiniZKCluster();
84      TEST_UTIL.restartHBaseCluster(3);
85      validateMetaAndUserTableRows(1, 5);
86    }
87  
88    @Test(timeout = 300000)
89    public void testHMasterStartupOnMetaRebuild() throws Exception {
90      // shutdown the minicluster
91      TEST_UTIL.shutdownMiniHBaseCluster();
92  
93      // Assign meta in master and restart HBase cluster
94      TEST_UTIL.getConfiguration().set("hbase.balancer.tablesOnMaster", "hbase:meta");
95      // Set namespace initialization timeout
96      TEST_UTIL.getConfiguration().set("hbase.master.namespace.init.timeout", "150000");
97      TEST_UTIL.restartHBaseCluster(3);
98      TEST_UTIL.getMiniHBaseCluster().waitForActiveAndReadyMaster();
99  
100     try {
101       // Create namespace
102       TEST_UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create("ns1").build());
103       TEST_UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create("ns2").build());
104       // Create tables
105       TEST_UTIL.createTable(TableName.valueOf("ns1:testHMasterStartupOnMetaRebuild"),
106         Bytes.toBytes("cf1"));
107       TEST_UTIL.createTable(TableName.valueOf("ns2:testHMasterStartupOnMetaRebuild"),
108         Bytes.toBytes("cf1"));
109 
110       // Flush meta
111       TEST_UTIL.flush(TableName.META_TABLE_NAME);
112 
113       // HMaster graceful shutdown
114       TEST_UTIL.getHBaseCluster().getMaster().shutdown();
115 
116       // Kill region servers
117       List<RegionServerThread> regionServerThreads =
118           TEST_UTIL.getHBaseCluster().getRegionServerThreads();
119       for (RegionServerThread regionServerThread : regionServerThreads) {
120         TEST_UTIL.getHBaseCluster()
121             .killRegionServer(regionServerThread.getRegionServer().getServerName());
122       }
123 
124       // rebuild meta table from scratch
125       HBaseFsck fsck = new HBaseFsck(conf);
126       assertTrue(fsck.rebuildMeta(false));
127 
128       // bring up the minicluster
129       TEST_UTIL.restartHBaseCluster(3);
130       validateMetaAndUserTableRows(3, 7);
131     } finally {
132       // Remove table and namesapce
133       TEST_UTIL.deleteTable("ns1:testHMasterStartupOnMetaRebuild");
134       TEST_UTIL.deleteTable("ns2:testHMasterStartupOnMetaRebuild");
135       TEST_UTIL.getHBaseAdmin().deleteNamespace("ns1");
136       TEST_UTIL.getHBaseAdmin().deleteNamespace("ns2");
137     }
138   }
139 
140   /*
141    * Validate meta table region count and user table rows.
142    */
143   private void validateMetaAndUserTableRows(int totalTableCount, int totalRegionCount)
144       throws Exception {
145     try (Connection connection = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
146       Admin admin = connection.getAdmin();
147       admin.enableTable(table);
148       LOG.info("Waiting for no more RIT");
149       TEST_UTIL.waitUntilNoRegionsInTransition(60000);
150       LOG.info("No more RIT in ZK, now doing final test verification");
151 
152       // everything is good again.
153       assertEquals(totalRegionCount, scanMeta());
154       HTableDescriptor[] htbls = admin.listTables();
155       LOG.info("Tables present after restart: " + Arrays.toString(htbls));
156       assertEquals(totalTableCount, htbls.length);
157     }
158 
159     assertErrors(doFsck(conf, false), new ERROR_CODE[] {});
160     LOG.info("Table " + table + " has " + tableRowCount(conf, table) + " entries.");
161     assertEquals(16, tableRowCount(conf, table));
162   }
163 
164   /**
165    * Validate whether Meta recovery empty WAL directory is removed.
166    * @return True if directory is removed otherwise false.
167    */
168   private boolean validateHBCKMetaRecoveryWALDir() throws IOException {
169     Path rootdir = FSUtils.getRootDir(TEST_UTIL.getConfiguration());
170     Path walLogDir = new Path(rootdir, HConstants.HREGION_LOGDIR_NAME);
171     FileSystem fs = TEST_UTIL.getTestFileSystem();
172     FileStatus[] walFiles = FSUtils.listStatus(fs, walLogDir, null);
173     assertNotNull(walFiles);
174     for (FileStatus fsStat : walFiles) {
175       if (fsStat.isDirectory() && fsStat.getPath().getName().startsWith("hregion-")) {
176         return false;
177       }
178     }
179     return true;
180   }
181 }