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.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.fs.PathFilter;
32 import org.apache.hadoop.hbase.HBaseTestingUtility;
33 import org.apache.hadoop.hbase.HColumnDescriptor;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.HTableDescriptor;
36 import org.apache.hadoop.hbase.testclassification.LargeTests;
37 import org.apache.hadoop.hbase.client.Admin;
38 import org.apache.hadoop.hbase.client.HTable;
39 import org.apache.hadoop.hbase.InvalidFamilyOperationException;
40 import org.apache.hadoop.hbase.TableName;
41 import org.apache.hadoop.hbase.client.Admin;
42 import org.apache.hadoop.hbase.client.Table;
43 import org.apache.hadoop.hbase.testclassification.LargeTests;
44 import org.apache.hadoop.hbase.util.Bytes;
45 import org.apache.hadoop.hbase.util.FSUtils;
46 import org.apache.hadoop.hbase.wal.WALSplitter;
47 import org.junit.After;
48 import org.junit.AfterClass;
49 import org.junit.Assert;
50 import org.junit.Before;
51 import org.junit.BeforeClass;
52 import org.junit.Test;
53 import org.junit.experimental.categories.Category;
54
55 @Category(LargeTests.class)
56 public class TestTableDeleteFamilyHandler {
57
58 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
59 private static final TableName TABLENAME =
60 TableName.valueOf("column_family_handlers");
61 private static final byte[][] FAMILIES = new byte[][] { Bytes.toBytes("cf1"),
62 Bytes.toBytes("cf2"), Bytes.toBytes("cf3") };
63
64
65
66
67
68
69 @BeforeClass
70 public static void beforeAllTests() throws Exception {
71 TEST_UTIL.getConfiguration().setBoolean("dfs.support.append", true);
72 TEST_UTIL.startMiniCluster(2);
73 }
74
75 @AfterClass
76 public static void afterAllTests() throws Exception {
77 TEST_UTIL.shutdownMiniCluster();
78 }
79
80 @Before
81 public void setup() throws IOException, InterruptedException {
82
83 TEST_UTIL.createTable(TABLENAME, FAMILIES);
84 HTable t = new HTable(TEST_UTIL.getConfiguration(), TABLENAME);
85 while(TEST_UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager()
86 .getRegionStates().getRegionsInTransition().size() > 0) {
87 Thread.sleep(100);
88 }
89
90 while(TEST_UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager()
91 .getRegionStates().getRegionsInTransition().size() > 0) {
92 Thread.sleep(100);
93 }
94
95 TEST_UTIL.loadTable(t, FAMILIES);
96
97 TEST_UTIL.flush();
98
99 t.close();
100
101 TEST_UTIL.ensureSomeRegionServersAvailable(2);
102 }
103
104 @After
105 public void cleanup() throws Exception {
106 TEST_UTIL.deleteTable(TABLENAME);
107 }
108
109 @Test
110 public void deleteColumnFamilyWithMultipleRegions() throws Exception {
111 Admin admin = TEST_UTIL.getHBaseAdmin();
112 HTableDescriptor beforehtd = admin.getTableDescriptor(TABLENAME);
113
114 FileSystem fs = TEST_UTIL.getDFSCluster().getFileSystem();
115
116
117 assertTrue(admin.isTableAvailable(TABLENAME));
118
119
120 assertEquals(3, beforehtd.getColumnFamilies().length);
121 HColumnDescriptor[] families = beforehtd.getColumnFamilies();
122 for (int i = 0; i < families.length; i++) {
123 assertTrue(families[i].getNameAsString().equals("cf" + (i + 1)));
124 }
125
126
127 Path tableDir = FSUtils.getTableDir(TEST_UTIL.getDefaultRootDirPath(), TABLENAME);
128 assertTrue(fs.exists(tableDir));
129
130
131 FileStatus[] fileStatus = fs.listStatus(tableDir);
132 for (int i = 0; i < fileStatus.length; i++) {
133 if (fileStatus[i].isDirectory() == true) {
134 FileStatus[] cf = fs.listStatus(fileStatus[i].getPath(), new PathFilter() {
135 @Override
136 public boolean accept(Path p) {
137 if (p.getName().contains(HConstants.RECOVERED_EDITS_DIR)) {
138 return false;
139 }
140 return true;
141 }
142 });
143 int k = 1;
144 for (int j = 0; j < cf.length; j++) {
145 if (cf[j].isDirectory() == true
146 && cf[j].getPath().getName().startsWith(".") == false) {
147 assertEquals(cf[j].getPath().getName(), "cf" + k);
148 k++;
149 }
150 }
151 }
152 }
153
154
155 admin.disableTable(TABLENAME);
156 admin.deleteColumn(TABLENAME, Bytes.toBytes("cf2"));
157
158
159 HTableDescriptor afterhtd = admin.getTableDescriptor(TABLENAME);
160 assertEquals(2, afterhtd.getColumnFamilies().length);
161 HColumnDescriptor[] newFamilies = afterhtd.getColumnFamilies();
162 assertTrue(newFamilies[0].getNameAsString().equals("cf1"));
163 assertTrue(newFamilies[1].getNameAsString().equals("cf3"));
164
165
166 fileStatus = fs.listStatus(tableDir);
167 for (int i = 0; i < fileStatus.length; i++) {
168 if (fileStatus[i].isDirectory() == true) {
169 FileStatus[] cf = fs.listStatus(fileStatus[i].getPath(), new PathFilter() {
170 @Override
171 public boolean accept(Path p) {
172 if (WALSplitter.isSequenceIdFile(p)) {
173 return false;
174 }
175 return true;
176 }
177 });
178 for (int j = 0; j < cf.length; j++) {
179 if (cf[j].isDirectory() == true) {
180 assertFalse(cf[j].getPath().getName().equals("cf2"));
181 }
182 }
183 }
184 }
185 }
186
187 @Test
188 public void deleteColumnFamilyTwice() throws Exception {
189
190 Admin admin = TEST_UTIL.getHBaseAdmin();
191 HTableDescriptor beforehtd = admin.getTableDescriptor(TABLENAME);
192 String cfToDelete = "cf1";
193
194 FileSystem fs = TEST_UTIL.getDFSCluster().getFileSystem();
195
196
197 assertTrue(admin.isTableAvailable(TABLENAME));
198
199
200 HColumnDescriptor[] families = beforehtd.getColumnFamilies();
201 Boolean foundCF = false;
202 int i;
203 for (i = 0; i < families.length; i++) {
204 if (families[i].getNameAsString().equals(cfToDelete)) {
205 foundCF = true;
206 break;
207 }
208 }
209 assertTrue(foundCF);
210
211
212 Path tableDir = FSUtils.getTableDir(TEST_UTIL.getDefaultRootDirPath(), TABLENAME);
213 assertTrue(fs.exists(tableDir));
214
215
216 FileStatus[] fileStatus = fs.listStatus(tableDir);
217 foundCF = false;
218 for (i = 0; i < fileStatus.length; i++) {
219 if (fileStatus[i].isDirectory() == true) {
220 FileStatus[] cf = fs.listStatus(fileStatus[i].getPath(), new PathFilter() {
221 @Override
222 public boolean accept(Path p) {
223 if (p.getName().contains(HConstants.RECOVERED_EDITS_DIR)) {
224 return false;
225 }
226 return true;
227 }
228 });
229 for (int j = 0; j < cf.length; j++) {
230 if (cf[j].isDirectory() == true && cf[j].getPath().getName().equals(cfToDelete)) {
231 foundCF = true;
232 break;
233 }
234 }
235 }
236 if (foundCF) {
237 break;
238 }
239 }
240 assertTrue(foundCF);
241
242
243 if (admin.isTableEnabled(TABLENAME)) {
244 admin.disableTable(TABLENAME);
245 }
246 admin.deleteColumn(TABLENAME, Bytes.toBytes(cfToDelete));
247
248
249 fileStatus = fs.listStatus(tableDir);
250 for (i = 0; i < fileStatus.length; i++) {
251 if (fileStatus[i].isDirectory() == true) {
252 FileStatus[] cf = fs.listStatus(fileStatus[i].getPath(), new PathFilter() {
253 @Override
254 public boolean accept(Path p) {
255 if (WALSplitter.isSequenceIdFile(p)) {
256 return false;
257 }
258 return true;
259 }
260 });
261 for (int j = 0; j < cf.length; j++) {
262 if (cf[j].isDirectory() == true) {
263 assertFalse(cf[j].getPath().getName().equals(cfToDelete));
264 }
265 }
266 }
267 }
268
269 try {
270
271 admin.deleteColumn(TABLENAME, Bytes.toBytes(cfToDelete));
272 Assert.fail("Delete a non-exist column family should fail");
273 } catch (InvalidFamilyOperationException e) {
274
275 }
276 }
277
278 }