1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.util;
21  
22  import static org.junit.Assert.assertEquals;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.HServerInfo;
30  import org.apache.hadoop.hbase.HTableDescriptor;
31  import org.apache.hadoop.hbase.client.HTable;
32  import org.apache.hadoop.hbase.client.Put;
33  import org.apache.hadoop.hbase.client.Result;
34  import org.apache.hadoop.hbase.client.ResultScanner;
35  import org.apache.hadoop.hbase.client.Scan;
36  import org.junit.BeforeClass;
37  import org.junit.Test;
38  
39  public class TestHBaseFsck {
40  
41    final Log LOG = LogFactory.getLog(getClass());
42    private final static HBaseTestingUtility TEST_UTIL =
43        new HBaseTestingUtility();
44    private final static Configuration conf = TEST_UTIL.getConfiguration();
45    private final static byte[] TABLE = Bytes.toBytes("table");
46    private final static byte[] FAM = Bytes.toBytes("fam");
47  
48    @BeforeClass
49    public static void setUpBeforeClass() throws Exception {
50      TEST_UTIL.startMiniCluster(3);
51    }
52  
53    private int doFsck(boolean fix) throws Exception {
54      HBaseFsck fsck = new HBaseFsck(conf);
55      fsck.displayFullReport();
56      fsck.setTimeLag(0);
57      fsck.setFixErrors(fix);
58      // Most basic check ever, 0 tables
59      return fsck.doWork();
60    }
61  
62    @Test
63    public void testHBaseFsck() throws Exception {
64      int result = doFsck(false);
65      assertEquals(0, result);
66  
67      TEST_UTIL.createTable(TABLE, FAM);
68  
69      // We created 1 table, should be fine
70      result = doFsck(false);
71      assertEquals(0, result);
72  
73      // Now let's mess it up and change the assignment in .META. to
74      // point to a different region server
75      HTable meta = new HTable(conf, HTableDescriptor.META_TABLEDESC.getName());
76      ResultScanner scanner = meta.getScanner(new Scan());
77  
78      resforloop : for (Result res : scanner) {
79        long startCode = Bytes.toLong(res.getValue(HConstants.CATALOG_FAMILY,
80            HConstants.STARTCODE_QUALIFIER));
81  
82        for (JVMClusterUtil.RegionServerThread rs :
83            TEST_UTIL.getHBaseCluster().getRegionServerThreads()) {
84  
85          HServerInfo hsi = rs.getRegionServer().getServerInfo();
86  
87          // When we find a diff RS, change the assignment and break
88          if (startCode != hsi.getStartCode()) {
89            Put put = new Put(res.getRow());
90            put.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
91                Bytes.toBytes(hsi.getHostnamePort()));
92            put.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
93                Bytes.toBytes(hsi.getStartCode()));
94            meta.put(put);
95            break resforloop;
96          }
97        }
98      }
99  
100     // Try to fix the data
101     result = doFsck(true);
102     assertEquals(-1, result);
103 
104     Thread.sleep(15000);
105     result = doFsck(false);
106     // Should have fixed
107     assertEquals(0, result);
108     new HTable(conf, TABLE).getScanner(new Scan());
109   }
110 }