1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master.procedure;
20
21 import static org.junit.Assert.assertTrue;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.hbase.HBaseTestingUtility;
27 import org.apache.hadoop.hbase.HColumnDescriptor;
28 import org.apache.hadoop.hbase.HTableDescriptor;
29 import org.apache.hadoop.hbase.InvalidFamilyOperationException;
30 import org.apache.hadoop.hbase.ProcedureInfo;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
33 import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
34 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.AddColumnFamilyState;
35 import org.apache.hadoop.hbase.testclassification.MediumTests;
36 import org.junit.After;
37 import org.junit.AfterClass;
38 import org.junit.Before;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.junit.experimental.categories.Category;
42
43 @Category(MediumTests.class)
44 public class TestAddColumnFamilyProcedure {
45 private static final Log LOG = LogFactory.getLog(TestAddColumnFamilyProcedure.class);
46
47 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
48
49 private static void setupConf(Configuration conf) {
50 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
51 }
52
53 @BeforeClass
54 public static void setupCluster() throws Exception {
55 setupConf(UTIL.getConfiguration());
56 UTIL.startMiniCluster(1);
57 }
58
59 @AfterClass
60 public static void cleanupTest() throws Exception {
61 try {
62 UTIL.shutdownMiniCluster();
63 } catch (Exception e) {
64 LOG.warn("failure shutting down cluster", e);
65 }
66 }
67
68 @Before
69 public void setup() throws Exception {
70 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
71 }
72
73 @After
74 public void tearDown() throws Exception {
75 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
76 for (HTableDescriptor htd: UTIL.getHBaseAdmin().listTables()) {
77 LOG.info("Tear down, remove table=" + htd.getTableName());
78 UTIL.deleteTable(htd.getTableName());
79 }
80 }
81
82 @Test(timeout = 60000)
83 public void testAddColumnFamily() throws Exception {
84 final TableName tableName = TableName.valueOf("testAddColumnFamily");
85 final String cf1 = "cf1";
86 final String cf2 = "cf2";
87 final HColumnDescriptor columnDescriptor1 = new HColumnDescriptor(cf1);
88 final HColumnDescriptor columnDescriptor2 = new HColumnDescriptor(cf2);
89 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
90
91 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f3");
92
93
94 long procId1 = procExec.submitProcedure(
95 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor1));
96
97 ProcedureTestingUtility.waitProcedure(procExec, procId1);
98 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
99
100 MasterProcedureTestingUtility.validateColumnFamilyAddition(UTIL.getHBaseCluster().getMaster(),
101 tableName, cf1);
102
103
104 UTIL.getHBaseAdmin().disableTable(tableName);
105 long procId2 = procExec.submitProcedure(
106 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor2));
107
108 ProcedureTestingUtility.waitProcedure(procExec, procId2);
109 ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
110 MasterProcedureTestingUtility.validateColumnFamilyAddition(UTIL.getHBaseCluster().getMaster(),
111 tableName, cf2);
112 }
113
114 @Test(timeout=60000)
115 public void testAddSameColumnFamilyTwice() throws Exception {
116 final TableName tableName = TableName.valueOf("testAddColumnFamilyTwice");
117 final String cf2 = "cf2";
118 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf2);
119
120 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
121
122 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1");
123
124
125 long procId1 = procExec.submitProcedure(
126 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor));
127
128 ProcedureTestingUtility.waitProcedure(procExec, procId1);
129 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
130 MasterProcedureTestingUtility.validateColumnFamilyAddition(UTIL.getHBaseCluster().getMaster(),
131 tableName, cf2);
132
133
134 long procId2 = procExec.submitProcedure(
135 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor));
136
137 ProcedureTestingUtility.waitProcedure(procExec, procId2);
138
139
140 ProcedureInfo result = procExec.getResult(procId2);
141 assertTrue(result.isFailed());
142 LOG.debug("Add failed with exception: " + result.getExceptionFullMessage());
143 assertTrue(
144 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
145
146
147 UTIL.getHBaseAdmin().disableTable(tableName);
148 long procId3 = procExec.submitProcedure(
149 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor));
150
151 ProcedureTestingUtility.waitProcedure(procExec, procId3);
152
153
154 result = procExec.getResult(procId3);
155 assertTrue(result.isFailed());
156 LOG.debug("Add failed with exception: " + result.getExceptionFullMessage());
157 assertTrue(
158 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
159 }
160
161 @Test(timeout = 60000)
162 public void testRecoveryAndDoubleExecutionOffline() throws Exception {
163 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOffline");
164 final String cf4 = "cf4";
165 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf4);
166 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
167
168 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", "f3");
169 UTIL.getHBaseAdmin().disableTable(tableName);
170
171 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
172 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
173
174
175 long procId = procExec.submitProcedure(
176 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor));
177
178
179 int numberOfSteps = AddColumnFamilyState.values().length;
180 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, numberOfSteps,
181 AddColumnFamilyState.values());
182
183 MasterProcedureTestingUtility.validateColumnFamilyAddition(UTIL.getHBaseCluster().getMaster(),
184 tableName, cf4);
185 }
186
187 @Test(timeout = 60000)
188 public void testRecoveryAndDoubleExecutionOnline() throws Exception {
189 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOnline");
190 final String cf5 = "cf5";
191 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf5);
192 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
193
194 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", "f3");
195
196 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
197 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
198
199
200 long procId = procExec.submitProcedure(
201 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor));
202
203
204 int numberOfSteps = AddColumnFamilyState.values().length;
205 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, numberOfSteps,
206 AddColumnFamilyState.values());
207
208 MasterProcedureTestingUtility.validateColumnFamilyAddition(UTIL.getHBaseCluster().getMaster(),
209 tableName, cf5);
210 }
211
212 @Test(timeout = 60000)
213 public void testRollbackAndDoubleExecution() throws Exception {
214 final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution");
215 final String cf6 = "cf6";
216 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf6);
217 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
218
219
220 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
221 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
222 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
223
224
225 long procId = procExec.submitProcedure(
226 new AddColumnFamilyProcedure(procExec.getEnvironment(), tableName, columnDescriptor));
227
228 int numberOfSteps = AddColumnFamilyState.values().length - 2;
229 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(procExec, procId, numberOfSteps,
230 AddColumnFamilyState.values());
231
232 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
233 tableName, cf6);
234 }
235
236 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
237 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
238 }
239 }