View Javadoc

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.assertTrue;
24  
25  import java.io.IOException;
26  import java.util.Set;
27  
28  import org.apache.hadoop.fs.Path;
29  import org.apache.hadoop.hbase.HBaseTestingUtility;
30  import org.apache.hadoop.hbase.HColumnDescriptor;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  import org.apache.hadoop.hbase.testclassification.LargeTests;
33  import org.apache.hadoop.hbase.TableName;
34  import org.apache.hadoop.hbase.client.HBaseAdmin;
35  import org.apache.hadoop.hbase.master.MasterFileSystem;
36  import org.apache.hadoop.hbase.util.Bytes;
37  import org.apache.hadoop.hbase.util.FSTableDescriptors;
38  import org.apache.hadoop.hbase.util.FSUtils;
39  import org.junit.AfterClass;
40  import org.junit.Before;
41  import org.junit.BeforeClass;
42  import org.junit.Rule;
43  import org.junit.Test;
44  import org.junit.experimental.categories.Category;
45  import org.junit.rules.TestName;
46  
47  /**
48   * Verify that the HTableDescriptor is updated after
49   * addColumn(), deleteColumn() and modifyTable() operations.
50   */
51  @Category(LargeTests.class)
52  public class TestTableDescriptorModification {
53    
54    @Rule public TestName name = new TestName();
55    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
56    private static TableName TABLE_NAME = null;
57    private static final byte[] FAMILY_0 = Bytes.toBytes("cf0");
58    private static final byte[] FAMILY_1 = Bytes.toBytes("cf1");
59  
60    /**
61     * Start up a mini cluster and put a small table of empty regions into it.
62     *
63     * @throws Exception
64     */
65    @BeforeClass
66    public static void beforeAllTests() throws Exception {
67      TEST_UTIL.startMiniCluster(1);
68    }
69  
70    @Before
71    public void setup() {
72      TABLE_NAME = TableName.valueOf(name.getMethodName());
73  
74    }
75    
76    @AfterClass
77    public static void afterAllTests() throws Exception {
78      TEST_UTIL.shutdownMiniCluster();
79    }
80  
81    @Test
82    public void testModifyTable() throws IOException {
83      HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
84      // Create a table with one family
85      HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
86      baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
87      admin.createTable(baseHtd);
88      admin.disableTable(TABLE_NAME);
89      try {
90        // Verify the table descriptor
91        verifyTableDescriptor(TABLE_NAME, FAMILY_0);
92  
93        // Modify the table adding another family and verify the descriptor
94        HTableDescriptor modifiedHtd = new HTableDescriptor(TABLE_NAME);
95        modifiedHtd.addFamily(new HColumnDescriptor(FAMILY_0));
96        modifiedHtd.addFamily(new HColumnDescriptor(FAMILY_1));
97        admin.modifyTable(TABLE_NAME, modifiedHtd);
98        verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
99      } finally {
100       admin.deleteTable(TABLE_NAME);
101     }
102   }
103 
104   @Test
105   public void testAddColumn() throws IOException {
106     HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
107     // Create a table with two families
108     HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
109     baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
110     admin.createTable(baseHtd);
111     admin.disableTable(TABLE_NAME);
112     try {
113       // Verify the table descriptor
114       verifyTableDescriptor(TABLE_NAME, FAMILY_0);
115 
116       // Modify the table removing one family and verify the descriptor
117       admin.addColumn(TABLE_NAME, new HColumnDescriptor(FAMILY_1));
118       verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
119     } finally {
120       admin.deleteTable(TABLE_NAME);
121     }
122   }
123 
124   @Test
125   public void testDeleteColumn() throws IOException {
126     HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
127     // Create a table with two families
128     HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
129     baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
130     baseHtd.addFamily(new HColumnDescriptor(FAMILY_1));
131     admin.createTable(baseHtd);
132     admin.disableTable(TABLE_NAME);
133     try {
134       // Verify the table descriptor
135       verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
136 
137       // Modify the table removing one family and verify the descriptor
138       admin.deleteColumn(TABLE_NAME, FAMILY_1);
139       verifyTableDescriptor(TABLE_NAME, FAMILY_0);
140     } finally {
141       admin.deleteTable(TABLE_NAME);
142     }
143   }
144 
145   private void verifyTableDescriptor(final TableName tableName,
146                                      final byte[]... families) throws IOException {
147     HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
148 
149     // Verify descriptor from master
150     HTableDescriptor htd = admin.getTableDescriptor(tableName);
151     verifyTableDescriptor(htd, tableName, families);
152 
153     // Verify descriptor from HDFS
154     MasterFileSystem mfs = TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterFileSystem();
155     Path tableDir = FSUtils.getTableDir(mfs.getRootDir(), tableName);
156     htd = FSTableDescriptors.getTableDescriptorFromFs(mfs.getFileSystem(), tableDir);
157     verifyTableDescriptor(htd, tableName, families);
158   }
159 
160   private void verifyTableDescriptor(final HTableDescriptor htd,
161       final TableName tableName, final byte[]... families) {
162     Set<byte[]> htdFamilies = htd.getFamiliesKeys();
163     assertEquals(tableName, htd.getTableName());
164     assertEquals(families.length, htdFamilies.size());
165     for (byte[] familyName: families) {
166       assertTrue("Expected family " + Bytes.toString(familyName), htdFamilies.contains(familyName));
167     }
168   }
169 }