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.ModifyColumnFamilyState;
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 TestModifyColumnFamilyProcedure {
45 private static final Log LOG = LogFactory.getLog(TestModifyColumnFamilyProcedure.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 testModifyColumnFamily() throws Exception {
84 final TableName tableName = TableName.valueOf("testModifyColumnFamily");
85 final String cf1 = "cf1";
86 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf1);
87 int oldBlockSize = columnDescriptor.getBlocksize();
88 int newBlockSize = 3 * oldBlockSize;
89
90 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
91
92 MasterProcedureTestingUtility.createTable(procExec, tableName, null, cf1, "f2");
93
94
95 columnDescriptor.setBlocksize(newBlockSize);
96 long procId1 = procExec.submitProcedure(new ModifyColumnFamilyProcedure(
97 procExec.getEnvironment(), tableName, columnDescriptor));
98
99 ProcedureTestingUtility.waitProcedure(procExec, procId1);
100 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
101 MasterProcedureTestingUtility.validateColumnFamilyModification(UTIL.getHBaseCluster()
102 .getMaster(), tableName, cf1, columnDescriptor);
103
104
105 UTIL.getHBaseAdmin().disableTable(tableName);
106 columnDescriptor.setBlocksize(newBlockSize * 2);
107 long procId2 =
108 procExec.submitProcedure(new ModifyColumnFamilyProcedure(procExec.getEnvironment(),
109 tableName, columnDescriptor));
110
111 ProcedureTestingUtility.waitProcedure(procExec, procId2);
112 ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
113 MasterProcedureTestingUtility.validateColumnFamilyModification(UTIL.getHBaseCluster()
114 .getMaster(), tableName, cf1, columnDescriptor);
115 }
116
117 @Test(timeout=60000)
118 public void testModifyNonExistingColumnFamily() throws Exception {
119 final TableName tableName = TableName.valueOf("testModifyExistingColumnFamily");
120 final String cf2 = "cf2";
121 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf2);
122 int oldBlockSize = columnDescriptor.getBlocksize();
123 int newBlockSize = 2 * oldBlockSize;
124
125 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
126
127 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1");
128
129
130 columnDescriptor.setBlocksize(newBlockSize);
131 long procId1 = procExec.submitProcedure(new ModifyColumnFamilyProcedure(
132 procExec.getEnvironment(), tableName, columnDescriptor));
133
134 ProcedureTestingUtility.waitProcedure(procExec, procId1);
135
136 ProcedureInfo result = procExec.getResult(procId1);
137 assertTrue(result.isFailed());
138 LOG.debug("Modify failed with exception: " + result.getExceptionFullMessage());
139 assertTrue(
140 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
141 }
142
143 @Test(timeout=60000)
144 public void testRecoveryAndDoubleExecutionOffline() throws Exception {
145 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOffline");
146 final String cf3 = "cf3";
147 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf3);
148 int oldBlockSize = columnDescriptor.getBlocksize();
149 int newBlockSize = 4 * oldBlockSize;
150
151 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
152
153
154 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", cf3);
155 UTIL.getHBaseAdmin().disableTable(tableName);
156 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
157 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
158
159
160 columnDescriptor.setBlocksize(newBlockSize);
161 long procId = procExec.submitProcedure(new ModifyColumnFamilyProcedure(
162 procExec.getEnvironment(), tableName, columnDescriptor));
163
164
165 int numberOfSteps = ModifyColumnFamilyState.values().length;
166 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
167 procExec,
168 procId,
169 numberOfSteps,
170 ModifyColumnFamilyState.values());
171
172 MasterProcedureTestingUtility.validateColumnFamilyModification(UTIL.getHBaseCluster()
173 .getMaster(), tableName, cf3, columnDescriptor);
174 }
175
176 @Test(timeout = 60000)
177 public void testRecoveryAndDoubleExecutionOnline() throws Exception {
178 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOnline");
179 final String cf4 = "cf4";
180 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf4);
181 int oldBlockSize = columnDescriptor.getBlocksize();
182 int newBlockSize = 4 * oldBlockSize;
183
184 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
185
186
187 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", cf4);
188 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
189 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
190
191
192 columnDescriptor.setBlocksize(newBlockSize);
193 long procId =
194 procExec.submitProcedure(new ModifyColumnFamilyProcedure(procExec.getEnvironment(),
195 tableName, columnDescriptor));
196
197
198 int numberOfSteps = ModifyColumnFamilyState.values().length;
199 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, numberOfSteps,
200 ModifyColumnFamilyState.values());
201
202 MasterProcedureTestingUtility.validateColumnFamilyModification(UTIL.getHBaseCluster()
203 .getMaster(), tableName, cf4, columnDescriptor);
204 }
205
206 @Test(timeout = 60000)
207 public void testRollbackAndDoubleExecution() throws Exception {
208 final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution");
209 final String cf3 = "cf3";
210 final HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf3);
211 int oldBlockSize = columnDescriptor.getBlocksize();
212 int newBlockSize = 4 * oldBlockSize;
213
214 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
215
216
217 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", cf3);
218 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
219 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
220
221
222 columnDescriptor.setBlocksize(newBlockSize);
223 long procId = procExec.submitProcedure(new ModifyColumnFamilyProcedure(
224 procExec.getEnvironment(), tableName, columnDescriptor));
225
226
227 int numberOfSteps = ModifyColumnFamilyState.values().length - 2;
228 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(
229 procExec,
230 procId,
231 numberOfSteps,
232 ModifyColumnFamilyState.values());
233 }
234
235 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
236 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
237 }
238 }