1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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.InvalidFamilyOperationException;
34 import org.apache.hadoop.hbase.TableName;
35 import org.apache.hadoop.hbase.client.Admin;
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.Assert;
42 import org.junit.Before;
43 import org.junit.BeforeClass;
44 import org.junit.Rule;
45 import org.junit.Test;
46 import org.junit.experimental.categories.Category;
47 import org.junit.rules.TestName;
48
49
50
51
52
53 @Category(LargeTests.class)
54 public class TestTableDescriptorModification {
55
56 @Rule public TestName name = new TestName();
57 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
58 private static TableName TABLE_NAME = null;
59 private static final byte[] FAMILY_0 = Bytes.toBytes("cf0");
60 private static final byte[] FAMILY_1 = Bytes.toBytes("cf1");
61
62
63
64
65
66
67 @BeforeClass
68 public static void beforeAllTests() throws Exception {
69 TEST_UTIL.startMiniCluster(1);
70 }
71
72 @Before
73 public void setup() {
74 TABLE_NAME = TableName.valueOf(name.getMethodName());
75
76 }
77
78 @AfterClass
79 public static void afterAllTests() throws Exception {
80 TEST_UTIL.shutdownMiniCluster();
81 }
82
83 @Test
84 public void testModifyTable() throws IOException {
85 Admin admin = TEST_UTIL.getHBaseAdmin();
86
87 HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
88 baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
89 admin.createTable(baseHtd);
90 admin.disableTable(TABLE_NAME);
91 try {
92
93 verifyTableDescriptor(TABLE_NAME, FAMILY_0);
94
95
96 HTableDescriptor modifiedHtd = new HTableDescriptor(TABLE_NAME);
97 modifiedHtd.addFamily(new HColumnDescriptor(FAMILY_0));
98 modifiedHtd.addFamily(new HColumnDescriptor(FAMILY_1));
99 admin.modifyTable(TABLE_NAME, modifiedHtd);
100 verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
101 } finally {
102 admin.deleteTable(TABLE_NAME);
103 }
104 }
105
106 @Test
107 public void testAddColumn() throws IOException {
108 Admin admin = TEST_UTIL.getHBaseAdmin();
109
110 HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
111 baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
112 admin.createTable(baseHtd);
113 admin.disableTable(TABLE_NAME);
114 try {
115
116 verifyTableDescriptor(TABLE_NAME, FAMILY_0);
117
118
119 admin.addColumn(TABLE_NAME, new HColumnDescriptor(FAMILY_1));
120 verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
121 } finally {
122 admin.deleteTable(TABLE_NAME);
123 }
124 }
125
126 @Test
127 public void testAddSameColumnFamilyTwice() throws IOException {
128 Admin admin = TEST_UTIL.getHBaseAdmin();
129
130 HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
131 baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
132 admin.createTable(baseHtd);
133 admin.disableTable(TABLE_NAME);
134 try {
135
136 verifyTableDescriptor(TABLE_NAME, FAMILY_0);
137
138
139 admin.addColumn(TABLE_NAME, new HColumnDescriptor(FAMILY_1));
140 verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
141
142 try {
143
144 admin.addColumn(TABLE_NAME, new HColumnDescriptor(FAMILY_1));
145 Assert.fail("Delete a non-exist column family should fail");
146 } catch (InvalidFamilyOperationException e) {
147
148 }
149
150 } finally {
151 admin.deleteTable(TABLE_NAME);
152 }
153 }
154
155 @Test
156 public void testModifyColumnFamily() throws IOException {
157 Admin admin = TEST_UTIL.getHBaseAdmin();
158
159 HColumnDescriptor cfDescriptor = new HColumnDescriptor(FAMILY_0);
160 int blockSize = cfDescriptor.getBlocksize();
161
162 HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
163 baseHtd.addFamily(cfDescriptor);
164 admin.createTable(baseHtd);
165 admin.disableTable(TABLE_NAME);
166 try {
167
168 verifyTableDescriptor(TABLE_NAME, FAMILY_0);
169
170 int newBlockSize = 2 * blockSize;
171 cfDescriptor.setBlocksize(newBlockSize);
172
173
174 admin.modifyColumn(TABLE_NAME, cfDescriptor);
175
176 HTableDescriptor htd = admin.getTableDescriptor(TABLE_NAME);
177 HColumnDescriptor hcfd = htd.getFamily(FAMILY_0);
178 assertTrue(hcfd.getBlocksize() == newBlockSize);
179 } finally {
180 admin.deleteTable(TABLE_NAME);
181 }
182 }
183
184 @Test
185 public void testModifyNonExistingColumnFamily() throws IOException {
186 Admin admin = TEST_UTIL.getHBaseAdmin();
187
188 HColumnDescriptor cfDescriptor = new HColumnDescriptor(FAMILY_1);
189 int blockSize = cfDescriptor.getBlocksize();
190
191 HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
192 baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
193 admin.createTable(baseHtd);
194 admin.disableTable(TABLE_NAME);
195 try {
196
197 verifyTableDescriptor(TABLE_NAME, FAMILY_0);
198
199 int newBlockSize = 2 * blockSize;
200 cfDescriptor.setBlocksize(newBlockSize);
201
202
203 try {
204 admin.modifyColumn(TABLE_NAME, cfDescriptor);
205 Assert.fail("Modify a non-exist column family should fail");
206 } catch (InvalidFamilyOperationException e) {
207
208 }
209
210 } finally {
211 admin.deleteTable(TABLE_NAME);
212 }
213 }
214
215 @Test
216 public void testDeleteColumn() throws IOException {
217 Admin admin = TEST_UTIL.getHBaseAdmin();
218
219 HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
220 baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
221 baseHtd.addFamily(new HColumnDescriptor(FAMILY_1));
222 admin.createTable(baseHtd);
223 admin.disableTable(TABLE_NAME);
224 try {
225
226 verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
227
228
229 admin.deleteColumn(TABLE_NAME, FAMILY_1);
230 verifyTableDescriptor(TABLE_NAME, FAMILY_0);
231 } finally {
232 admin.deleteTable(TABLE_NAME);
233 }
234 }
235
236 @Test
237 public void testDeleteSameColumnFamilyTwice() throws IOException {
238 Admin admin = TEST_UTIL.getHBaseAdmin();
239
240 HTableDescriptor baseHtd = new HTableDescriptor(TABLE_NAME);
241 baseHtd.addFamily(new HColumnDescriptor(FAMILY_0));
242 baseHtd.addFamily(new HColumnDescriptor(FAMILY_1));
243 admin.createTable(baseHtd);
244 admin.disableTable(TABLE_NAME);
245 try {
246
247 verifyTableDescriptor(TABLE_NAME, FAMILY_0, FAMILY_1);
248
249
250 admin.deleteColumn(TABLE_NAME, FAMILY_1);
251 verifyTableDescriptor(TABLE_NAME, FAMILY_0);
252
253 try {
254
255 admin.deleteColumn(TABLE_NAME, FAMILY_1);
256 Assert.fail("Delete a non-exist column family should fail");
257 } catch (Exception e) {
258
259 }
260 } finally {
261 admin.deleteTable(TABLE_NAME);
262 }
263 }
264
265 private void verifyTableDescriptor(final TableName tableName,
266 final byte[]... families) throws IOException {
267 Admin admin = TEST_UTIL.getHBaseAdmin();
268
269
270 HTableDescriptor htd = admin.getTableDescriptor(tableName);
271 verifyTableDescriptor(htd, tableName, families);
272
273
274 MasterFileSystem mfs = TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterFileSystem();
275 Path tableDir = FSUtils.getTableDir(mfs.getRootDir(), tableName);
276 htd = FSTableDescriptors.getTableDescriptorFromFs(mfs.getFileSystem(), tableDir);
277 verifyTableDescriptor(htd, tableName, families);
278 }
279
280 private void verifyTableDescriptor(final HTableDescriptor htd,
281 final TableName tableName, final byte[]... families) {
282 Set<byte[]> htdFamilies = htd.getFamiliesKeys();
283 assertEquals(tableName, htd.getTableName());
284 assertEquals(families.length, htdFamilies.size());
285 for (byte[] familyName: families) {
286 assertTrue("Expected family " + Bytes.toString(familyName), htdFamilies.contains(familyName));
287 }
288 }
289 }