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