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 java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.util.concurrent.atomic.AtomicBoolean;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.hbase.NamespaceDescriptor;
29 import org.apache.hadoop.hbase.NamespaceExistException;
30 import org.apache.hadoop.hbase.TableName;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.hbase.master.MasterFileSystem;
33 import org.apache.hadoop.hbase.master.TableNamespaceManager;
34 import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
35 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
36 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos;
37 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.CreateNamespaceState;
38 import org.apache.hadoop.hbase.util.FSUtils;
39
40
41
42
43 @InterfaceAudience.Private
44 public class CreateNamespaceProcedure
45 extends StateMachineProcedure<MasterProcedureEnv, CreateNamespaceState>
46 implements TableProcedureInterface {
47 private static final Log LOG = LogFactory.getLog(CreateNamespaceProcedure.class);
48
49 private final AtomicBoolean aborted = new AtomicBoolean(false);
50
51 private NamespaceDescriptor nsDescriptor;
52 private Boolean traceEnabled;
53
54 public CreateNamespaceProcedure() {
55 this.traceEnabled = null;
56 }
57
58 public CreateNamespaceProcedure(final MasterProcedureEnv env,
59 final NamespaceDescriptor nsDescriptor) {
60 this.nsDescriptor = nsDescriptor;
61 this.traceEnabled = null;
62 this.setOwner(env.getRequestUser().getUGI().getShortUserName());
63 }
64
65 @Override
66 protected Flow executeFromState(final MasterProcedureEnv env, final CreateNamespaceState state)
67 throws InterruptedException {
68 if (isTraceEnabled()) {
69 LOG.trace(this + " execute state=" + state);
70 }
71
72 try {
73 switch (state) {
74 case CREATE_NAMESPACE_PREPARE:
75 prepareCreate(env);
76 setNextState(CreateNamespaceState.CREATE_NAMESPACE_CREATE_DIRECTORY);
77 break;
78 case CREATE_NAMESPACE_CREATE_DIRECTORY:
79 createDirectory(env, nsDescriptor);
80 setNextState(CreateNamespaceState.CREATE_NAMESPACE_INSERT_INTO_NS_TABLE);
81 break;
82 case CREATE_NAMESPACE_INSERT_INTO_NS_TABLE:
83 insertIntoNSTable(env, nsDescriptor);
84 setNextState(CreateNamespaceState.CREATE_NAMESPACE_UPDATE_ZK);
85 break;
86 case CREATE_NAMESPACE_UPDATE_ZK:
87 updateZKNamespaceManager(env, nsDescriptor);
88 setNextState(CreateNamespaceState.CREATE_NAMESPACE_SET_NAMESPACE_QUOTA);
89 break;
90 case CREATE_NAMESPACE_SET_NAMESPACE_QUOTA:
91 setNamespaceQuota(env, nsDescriptor);
92 return Flow.NO_MORE_STATE;
93 default:
94 throw new UnsupportedOperationException(this + " unhandled state=" + state);
95 }
96 } catch (IOException e) {
97 LOG.warn("Error trying to create the namespace" + nsDescriptor.getName()
98 + " (in state=" + state + ")", e);
99
100 setFailure("master-create-namespace", e);
101 }
102 return Flow.HAS_MORE_STATE;
103 }
104
105 @Override
106 protected void rollbackState(final MasterProcedureEnv env, final CreateNamespaceState state)
107 throws IOException {
108 if (isTraceEnabled()) {
109 LOG.trace(this + " rollback state=" + state);
110 }
111 try {
112 switch (state) {
113 case CREATE_NAMESPACE_SET_NAMESPACE_QUOTA:
114 rollbackSetNamespaceQuota(env);
115 break;
116 case CREATE_NAMESPACE_UPDATE_ZK:
117 rollbackZKNamespaceManagerChange(env);
118 break;
119 case CREATE_NAMESPACE_INSERT_INTO_NS_TABLE:
120 rollbackInsertIntoNSTable(env);
121 break;
122 case CREATE_NAMESPACE_CREATE_DIRECTORY:
123 rollbackCreateDirectory(env);
124 break;
125 case CREATE_NAMESPACE_PREPARE:
126 break;
127 default:
128 throw new UnsupportedOperationException(this + " unhandled state=" + state);
129 }
130 } catch (IOException e) {
131
132
133 LOG.warn("Failed rollback attempt step " + state + " for creating the namespace "
134 + nsDescriptor.getName(), e);
135 throw e;
136 }
137 }
138
139 @Override
140 protected CreateNamespaceState getState(final int stateId) {
141 return CreateNamespaceState.valueOf(stateId);
142 }
143
144 @Override
145 protected int getStateId(final CreateNamespaceState state) {
146 return state.getNumber();
147 }
148
149 @Override
150 protected CreateNamespaceState getInitialState() {
151 return CreateNamespaceState.CREATE_NAMESPACE_PREPARE;
152 }
153
154 @Override
155 protected void setNextState(CreateNamespaceState state) {
156 if (aborted.get()) {
157 setAbortFailure("create-namespace", "abort requested");
158 } else {
159 super.setNextState(state);
160 }
161 }
162
163 @Override
164 public boolean abort(final MasterProcedureEnv env) {
165 aborted.set(true);
166 return true;
167 }
168
169 @Override
170 public void serializeStateData(final OutputStream stream) throws IOException {
171 super.serializeStateData(stream);
172
173 MasterProcedureProtos.CreateNamespaceStateData.Builder createNamespaceMsg =
174 MasterProcedureProtos.CreateNamespaceStateData.newBuilder().setNamespaceDescriptor(
175 ProtobufUtil.toProtoNamespaceDescriptor(this.nsDescriptor));
176 createNamespaceMsg.build().writeDelimitedTo(stream);
177 }
178
179 @Override
180 public void deserializeStateData(final InputStream stream) throws IOException {
181 super.deserializeStateData(stream);
182
183 MasterProcedureProtos.CreateNamespaceStateData createNamespaceMsg =
184 MasterProcedureProtos.CreateNamespaceStateData.parseDelimitedFrom(stream);
185 nsDescriptor = ProtobufUtil.toNamespaceDescriptor(createNamespaceMsg.getNamespaceDescriptor());
186 }
187
188 @Override
189 public void toStringClassDetails(StringBuilder sb) {
190 sb.append(getClass().getSimpleName());
191 sb.append(" (Namespace=");
192 sb.append(nsDescriptor.getName());
193 sb.append(")");
194 }
195
196 private boolean isBootstrapNamespace() {
197 return nsDescriptor.equals(NamespaceDescriptor.DEFAULT_NAMESPACE) ||
198 nsDescriptor.equals(NamespaceDescriptor.SYSTEM_NAMESPACE);
199 }
200
201 @Override
202 protected boolean acquireLock(final MasterProcedureEnv env) {
203 if (!env.getMasterServices().isInitialized()) {
204
205
206
207 if (!isBootstrapNamespace() && env.waitInitialized(this)) {
208 return false;
209 }
210 }
211 return env.getProcedureQueue().tryAcquireNamespaceExclusiveLock(this, getNamespaceName());
212 }
213
214 @Override
215 protected void releaseLock(final MasterProcedureEnv env) {
216 env.getProcedureQueue().releaseNamespaceExclusiveLock(this, getNamespaceName());
217 }
218
219 @Override
220 public TableName getTableName() {
221 return TableName.NAMESPACE_TABLE_NAME;
222 }
223
224 @Override
225 public TableOperationType getTableOperationType() {
226 return TableOperationType.EDIT;
227 }
228
229 private String getNamespaceName() {
230 return nsDescriptor.getName();
231 }
232
233
234
235
236
237
238 private void prepareCreate(final MasterProcedureEnv env) throws IOException {
239 if (getTableNamespaceManager(env).doesNamespaceExist(nsDescriptor.getName())) {
240 throw new NamespaceExistException(nsDescriptor.getName());
241 }
242 getTableNamespaceManager(env).validateTableAndRegionCount(nsDescriptor);
243 }
244
245
246
247
248
249
250
251 protected static void createDirectory(
252 final MasterProcedureEnv env,
253 final NamespaceDescriptor nsDescriptor) throws IOException {
254 MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem();
255 mfs.getFileSystem().mkdirs(
256 FSUtils.getNamespaceDir(mfs.getRootDir(), nsDescriptor.getName()));
257 }
258
259
260
261
262
263
264 private void rollbackCreateDirectory(final MasterProcedureEnv env) throws IOException {
265 try {
266 DeleteNamespaceProcedure.deleteDirectory(env, nsDescriptor.getName());
267 } catch (Exception e) {
268
269 LOG.debug("Rollback of createDirectory throws exception: " + e);
270 }
271 }
272
273
274
275
276
277
278
279 protected static void insertIntoNSTable(
280 final MasterProcedureEnv env,
281 final NamespaceDescriptor nsDescriptor) throws IOException {
282 getTableNamespaceManager(env).insertIntoNSTable(nsDescriptor);
283 }
284
285
286
287
288
289
290 private void rollbackInsertIntoNSTable(final MasterProcedureEnv env) throws IOException {
291 try {
292 DeleteNamespaceProcedure.deleteFromNSTable(env, nsDescriptor.getName());
293 } catch (Exception e) {
294
295 LOG.debug("Rollback of insertIntoNSTable throws exception: " + e);
296 }
297 }
298
299
300
301
302
303
304
305 protected static void updateZKNamespaceManager(
306 final MasterProcedureEnv env,
307 final NamespaceDescriptor nsDescriptor) throws IOException {
308 getTableNamespaceManager(env).updateZKNamespaceManager(nsDescriptor);
309 }
310
311
312
313
314
315
316 private void rollbackZKNamespaceManagerChange(final MasterProcedureEnv env) throws IOException {
317 try {
318 DeleteNamespaceProcedure.removeFromZKNamespaceManager(env, nsDescriptor.getName());
319 } catch (Exception e) {
320
321 LOG.debug("Rollback of updateZKNamespaceManager throws exception: " + e);
322 }
323 }
324
325
326
327
328
329
330
331 protected static void setNamespaceQuota(
332 final MasterProcedureEnv env,
333 final NamespaceDescriptor nsDescriptor) throws IOException {
334 if (env.getMasterServices().isInitialized()) {
335 env.getMasterServices().getMasterQuotaManager().setNamespaceQuota(nsDescriptor);
336 }
337 }
338
339
340
341
342
343
344 private void rollbackSetNamespaceQuota(final MasterProcedureEnv env) throws IOException {
345 try {
346 DeleteNamespaceProcedure.removeNamespaceQuota(env, nsDescriptor.getName());
347 } catch (Exception e) {
348
349 LOG.debug("Rollback of setNamespaceQuota throws exception: " + e);
350 }
351 }
352
353 private static TableNamespaceManager getTableNamespaceManager(final MasterProcedureEnv env) {
354 return env.getMasterServices().getTableNamespaceManager();
355 }
356
357
358
359
360
361
362 private Boolean isTraceEnabled() {
363 if (traceEnabled == null) {
364 traceEnabled = LOG.isTraceEnabled();
365 }
366 return traceEnabled;
367 }
368
369 @Override
370 protected boolean shouldWaitClientAck(MasterProcedureEnv env) {
371
372
373 return !isBootstrapNamespace();
374 }
375 }