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.NamespaceNotFoundException;
30 import org.apache.hadoop.hbase.TableName;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.hbase.master.TableNamespaceManager;
33 import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
34 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
35 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos;
36 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.ModifyNamespaceState;
37
38
39
40
41 @InterfaceAudience.Private
42 public class ModifyNamespaceProcedure
43 extends StateMachineProcedure<MasterProcedureEnv, ModifyNamespaceState>
44 implements TableProcedureInterface {
45 private static final Log LOG = LogFactory.getLog(ModifyNamespaceProcedure.class);
46
47 private final AtomicBoolean aborted = new AtomicBoolean(false);
48
49 private NamespaceDescriptor oldNsDescriptor;
50 private NamespaceDescriptor newNsDescriptor;
51 private Boolean traceEnabled;
52
53 public ModifyNamespaceProcedure() {
54 this.oldNsDescriptor = null;
55 this.traceEnabled = null;
56 }
57
58 public ModifyNamespaceProcedure(final MasterProcedureEnv env,
59 final NamespaceDescriptor newNsDescriptor) {
60 this.oldNsDescriptor = null;
61 this.newNsDescriptor = newNsDescriptor;
62 this.traceEnabled = null;
63 this.setOwner(env.getRequestUser().getUGI().getShortUserName());
64 }
65
66 @Override
67 protected Flow executeFromState(final MasterProcedureEnv env, final ModifyNamespaceState state)
68 throws InterruptedException {
69 if (isTraceEnabled()) {
70 LOG.trace(this + " execute state=" + state);
71 }
72
73 try {
74 switch (state) {
75 case MODIFY_NAMESPACE_PREPARE:
76 prepareModify(env);
77 setNextState(ModifyNamespaceState.MODIFY_NAMESPACE_UPDATE_NS_TABLE);
78 break;
79 case MODIFY_NAMESPACE_UPDATE_NS_TABLE:
80 insertIntoNSTable(env);
81 setNextState(ModifyNamespaceState.MODIFY_NAMESPACE_UPDATE_ZK);
82 break;
83 case MODIFY_NAMESPACE_UPDATE_ZK:
84 updateZKNamespaceManager(env);
85 return Flow.NO_MORE_STATE;
86 default:
87 throw new UnsupportedOperationException(this + " unhandled state=" + state);
88 }
89 } catch (IOException e) {
90 LOG.warn("Error trying to modify the namespace" + newNsDescriptor.getName()
91 + " (in state=" + state + ")", e);
92
93 setFailure("master-modify-namespace", e);
94 }
95 return Flow.HAS_MORE_STATE;
96 }
97
98 @Override
99 protected void rollbackState(final MasterProcedureEnv env, final ModifyNamespaceState state)
100 throws IOException {
101 if (isTraceEnabled()) {
102 LOG.trace(this + " rollback state=" + state);
103 }
104 try {
105 switch (state) {
106 case MODIFY_NAMESPACE_UPDATE_ZK:
107 rollbackZKNamespaceManagerChange(env);
108 break;
109 case MODIFY_NAMESPACE_UPDATE_NS_TABLE:
110 rollbackUpdateInNSTable(env);
111 break;
112 case MODIFY_NAMESPACE_PREPARE:
113 break;
114 default:
115 throw new UnsupportedOperationException(this + " unhandled state=" + state);
116 }
117 } catch (IOException e) {
118
119
120 LOG.warn("Failed rollback attempt step " + state + " for creating the namespace "
121 + newNsDescriptor.getName(), e);
122 throw e;
123 }
124 }
125
126 @Override
127 protected ModifyNamespaceState getState(final int stateId) {
128 return ModifyNamespaceState.valueOf(stateId);
129 }
130
131 @Override
132 protected int getStateId(final ModifyNamespaceState state) {
133 return state.getNumber();
134 }
135
136 @Override
137 protected ModifyNamespaceState getInitialState() {
138 return ModifyNamespaceState.MODIFY_NAMESPACE_PREPARE;
139 }
140
141 @Override
142 protected void setNextState(ModifyNamespaceState state) {
143 if (aborted.get()) {
144 setAbortFailure("modify-namespace", "abort requested");
145 } else {
146 super.setNextState(state);
147 }
148 }
149
150 @Override
151 public boolean abort(final MasterProcedureEnv env) {
152 aborted.set(true);
153 return true;
154 }
155
156 @Override
157 public void serializeStateData(final OutputStream stream) throws IOException {
158 super.serializeStateData(stream);
159
160 MasterProcedureProtos.ModifyNamespaceStateData.Builder modifyNamespaceMsg =
161 MasterProcedureProtos.ModifyNamespaceStateData.newBuilder().setNamespaceDescriptor(
162 ProtobufUtil.toProtoNamespaceDescriptor(this.newNsDescriptor));
163 if (this.oldNsDescriptor != null) {
164 modifyNamespaceMsg.setUnmodifiedNamespaceDescriptor(
165 ProtobufUtil.toProtoNamespaceDescriptor(this.oldNsDescriptor));
166 }
167 modifyNamespaceMsg.build().writeDelimitedTo(stream);
168 }
169
170 @Override
171 public void deserializeStateData(final InputStream stream) throws IOException {
172 super.deserializeStateData(stream);
173
174 MasterProcedureProtos.ModifyNamespaceStateData modifyNamespaceMsg =
175 MasterProcedureProtos.ModifyNamespaceStateData.parseDelimitedFrom(stream);
176 newNsDescriptor =
177 ProtobufUtil.toNamespaceDescriptor(modifyNamespaceMsg.getNamespaceDescriptor());
178 if (modifyNamespaceMsg.hasUnmodifiedNamespaceDescriptor()) {
179 oldNsDescriptor =
180 ProtobufUtil.toNamespaceDescriptor(modifyNamespaceMsg.getUnmodifiedNamespaceDescriptor());
181 }
182 }
183
184 @Override
185 public void toStringClassDetails(StringBuilder sb) {
186 sb.append(getClass().getSimpleName());
187 sb.append(" (Namespace=");
188 sb.append(newNsDescriptor.getName());
189 sb.append(")");
190 }
191
192 @Override
193 protected boolean acquireLock(final MasterProcedureEnv env) {
194 if (env.waitInitialized(this)) return false;
195 return env.getProcedureQueue().tryAcquireNamespaceExclusiveLock(this, getNamespaceName());
196 }
197
198 @Override
199 protected void releaseLock(final MasterProcedureEnv env) {
200 env.getProcedureQueue().releaseNamespaceExclusiveLock(this, getNamespaceName());
201 }
202
203 @Override
204 public TableName getTableName() {
205 return TableName.NAMESPACE_TABLE_NAME;
206 }
207
208 @Override
209 public TableOperationType getTableOperationType() {
210 return TableOperationType.EDIT;
211 }
212
213 private String getNamespaceName() {
214 return newNsDescriptor.getName();
215 }
216
217
218
219
220
221
222 private void prepareModify(final MasterProcedureEnv env) throws IOException {
223 if (getTableNamespaceManager(env).doesNamespaceExist(newNsDescriptor.getName()) == false) {
224 throw new NamespaceNotFoundException(newNsDescriptor.getName());
225 }
226 getTableNamespaceManager(env).validateTableAndRegionCount(newNsDescriptor);
227
228
229 oldNsDescriptor = getTableNamespaceManager(env).get(newNsDescriptor.getName());
230 }
231
232
233
234
235
236
237 private void insertIntoNSTable(final MasterProcedureEnv env) throws IOException {
238 getTableNamespaceManager(env).insertIntoNSTable(newNsDescriptor);
239 }
240
241
242
243
244
245
246 private void rollbackUpdateInNSTable(final MasterProcedureEnv env) throws IOException {
247 if (oldNsDescriptor != null) {
248 getTableNamespaceManager(env).insertIntoNSTable(oldNsDescriptor);
249 }
250 }
251
252
253
254
255
256
257 private void updateZKNamespaceManager(final MasterProcedureEnv env) throws IOException {
258 getTableNamespaceManager(env).updateZKNamespaceManager(newNsDescriptor);
259 }
260
261
262
263
264
265
266 private void rollbackZKNamespaceManagerChange(final MasterProcedureEnv env) throws IOException {
267 if (oldNsDescriptor != null) {
268 getTableNamespaceManager(env).updateZKNamespaceManager(oldNsDescriptor);
269 }
270 }
271
272 private TableNamespaceManager getTableNamespaceManager(final MasterProcedureEnv env) {
273 return env.getMasterServices().getTableNamespaceManager();
274 }
275
276
277
278
279
280 private Boolean isTraceEnabled() {
281 if (traceEnabled == null) {
282 traceEnabled = LOG.isTraceEnabled();
283 }
284 return traceEnabled;
285 }
286 }