1   /**
2    * Copyright 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.master.handler;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.io.IOException;
27  
28  import org.apache.hadoop.fs.FileStatus;
29  import org.apache.hadoop.fs.FileSystem;
30  import org.apache.hadoop.fs.Path;
31  import org.apache.hadoop.hbase.HBaseTestingUtility;
32  import org.apache.hadoop.hbase.HColumnDescriptor;
33  import org.apache.hadoop.hbase.HTableDescriptor;
34  import org.apache.hadoop.hbase.LargeTests;
35  import org.apache.hadoop.hbase.client.HBaseAdmin;
36  import org.apache.hadoop.hbase.client.HTable;
37  import org.apache.hadoop.hbase.util.Bytes;
38  import org.junit.AfterClass;
39  import org.junit.Before;
40  import org.junit.BeforeClass;
41  import org.junit.Test;
42  import org.junit.experimental.categories.Category;
43  
44  @Category(LargeTests.class)
45  public class TestTableDeleteFamilyHandler {
46  
47    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
48    private static final String TABLENAME = "column_family_handlers";
49    private static final byte[][] FAMILIES = new byte[][] { Bytes.toBytes("cf1"),
50        Bytes.toBytes("cf2"), Bytes.toBytes("cf3") };
51  
52    /**
53     * Start up a mini cluster and put a small table of empty regions into it.
54     * 
55     * @throws Exception
56     */
57    @BeforeClass
58    public static void beforeAllTests() throws Exception {
59  
60      TEST_UTIL.getConfiguration().setBoolean("dfs.support.append", true);
61      TEST_UTIL.startMiniCluster(2);
62  
63      // Create a table of three families. This will assign a region.
64      TEST_UTIL.createTable(Bytes.toBytes(TABLENAME), FAMILIES);
65      HTable t = new HTable(TEST_UTIL.getConfiguration(), TABLENAME);
66  
67      // Create multiple regions in all the three column families
68      TEST_UTIL.createMultiRegions(t, FAMILIES[0]);
69  
70      // Load the table with data for all families
71      TEST_UTIL.loadTable(t, FAMILIES);
72  
73      TEST_UTIL.flush();
74  
75      t.close();
76    }
77  
78    @AfterClass
79    public static void afterAllTests() throws Exception {
80      TEST_UTIL.deleteTable(Bytes.toBytes(TABLENAME));
81      TEST_UTIL.shutdownMiniCluster();
82    }
83  
84    @Before
85    public void setup() throws IOException, InterruptedException {
86      TEST_UTIL.ensureSomeRegionServersAvailable(2);
87    }
88  
89    @Test
90    public void deleteColumnFamilyWithMultipleRegions() throws Exception {
91  
92      HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
93      HTableDescriptor beforehtd = admin.getTableDescriptor(Bytes
94          .toBytes(TABLENAME));
95  
96      FileSystem fs = TEST_UTIL.getDFSCluster().getFileSystem();
97  
98      // 1 - Check if table exists in descriptor
99      assertTrue(admin.isTableAvailable(TABLENAME));
100 
101     // 2 - Check if all three families exist in descriptor
102     assertEquals(3, beforehtd.getColumnFamilies().length);
103     HColumnDescriptor[] families = beforehtd.getColumnFamilies();
104     for (int i = 0; i < families.length; i++) {
105 
106       assertTrue(families[i].getNameAsString().equals("cf" + (i + 1)));
107     }
108 
109     // 3 - Check if table exists in FS
110     Path tableDir = new Path(TEST_UTIL.getDefaultRootDirPath().toString() + "/"
111         + TABLENAME);
112     assertTrue(fs.exists(tableDir));
113 
114     // 4 - Check if all the 3 column families exist in FS
115     FileStatus[] fileStatus = fs.listStatus(tableDir);
116     for (int i = 0; i < fileStatus.length; i++) {
117       if (fileStatus[i].isDir() == true) {
118         FileStatus[] cf = fs.listStatus(fileStatus[i].getPath());
119         int k = 1;
120         for (int j = 0; j < cf.length; j++) {
121           if (cf[j].isDir() == true
122               && cf[j].getPath().getName().startsWith(".") == false) {
123             assertTrue(cf[j].getPath().getName().equals("cf" + k));
124             k++;
125           }
126         }
127       }
128     }
129 
130     // TEST - Disable and delete the column family
131     admin.disableTable(TABLENAME);
132     admin.deleteColumn(TABLENAME, "cf2");
133 
134     // 5 - Check if only 2 column families exist in the descriptor
135     HTableDescriptor afterhtd = admin.getTableDescriptor(Bytes
136         .toBytes(TABLENAME));
137     assertEquals(2, afterhtd.getColumnFamilies().length);
138     HColumnDescriptor[] newFamilies = afterhtd.getColumnFamilies();
139     assertTrue(newFamilies[0].getNameAsString().equals("cf1"));
140     assertTrue(newFamilies[1].getNameAsString().equals("cf3"));
141 
142     // 6 - Check if the second column family is gone from the FS
143     fileStatus = fs.listStatus(tableDir);
144     for (int i = 0; i < fileStatus.length; i++) {
145       if (fileStatus[i].isDir() == true) {
146         FileStatus[] cf = fs.listStatus(fileStatus[i].getPath());
147         for (int j = 0; j < cf.length; j++) {
148           if (cf[j].isDir() == true) {
149             assertFalse(cf[j].getPath().getName().equals("cf2"));
150           }
151         }
152       }
153     }
154   }
155 
156   @org.junit.Rule
157   public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = 
158     new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
159 }