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.handler;
20
21 import java.io.IOException;
22 import java.io.InterruptedIOException;
23 import java.security.PrivilegedExceptionAction;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.fs.FileSystem;
32 import org.apache.hadoop.fs.Path;
33 import org.apache.hadoop.hbase.CoordinatedStateException;
34 import org.apache.hadoop.hbase.TableName;
35 import org.apache.hadoop.hbase.HRegionInfo;
36 import org.apache.hadoop.hbase.HTableDescriptor;
37 import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException;
38 import org.apache.hadoop.hbase.Server;
39 import org.apache.hadoop.hbase.TableExistsException;
40 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
41 import org.apache.hadoop.hbase.MetaTableAccessor;
42 import org.apache.hadoop.hbase.executor.EventHandler;
43 import org.apache.hadoop.hbase.executor.EventType;
44 import org.apache.hadoop.hbase.ipc.RpcServer;
45 import org.apache.hadoop.hbase.master.AssignmentManager;
46 import org.apache.hadoop.hbase.master.HMaster;
47 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
48 import org.apache.hadoop.hbase.master.MasterFileSystem;
49 import org.apache.hadoop.hbase.master.MasterServices;
50 import org.apache.hadoop.hbase.master.TableLockManager;
51 import org.apache.hadoop.hbase.master.TableLockManager.TableLock;
52 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
53 import org.apache.hadoop.hbase.security.User;
54 import org.apache.hadoop.hbase.security.UserProvider;
55 import org.apache.hadoop.hbase.util.FSTableDescriptors;
56 import org.apache.hadoop.hbase.util.FSUtils;
57 import org.apache.hadoop.hbase.util.ModifyRegionUtils;
58 import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
59
60
61
62
63 @InterfaceAudience.Private
64 public class CreateTableHandler extends EventHandler {
65 private static final Log LOG = LogFactory.getLog(CreateTableHandler.class);
66 protected final MasterFileSystem fileSystemManager;
67 protected final HTableDescriptor hTableDescriptor;
68 protected final Configuration conf;
69 private final AssignmentManager assignmentManager;
70 private final TableLockManager tableLockManager;
71 private final HRegionInfo [] newRegions;
72 private final TableLock tableLock;
73 private User activeUser;
74
75 public CreateTableHandler(Server server, MasterFileSystem fileSystemManager,
76 HTableDescriptor hTableDescriptor, Configuration conf, HRegionInfo [] newRegions,
77 MasterServices masterServices) {
78 super(server, EventType.C_M_CREATE_TABLE);
79
80 this.fileSystemManager = fileSystemManager;
81 this.hTableDescriptor = hTableDescriptor;
82 this.conf = conf;
83 this.newRegions = newRegions;
84 this.assignmentManager = masterServices.getAssignmentManager();
85 this.tableLockManager = masterServices.getTableLockManager();
86
87 this.tableLock = this.tableLockManager.writeLock(this.hTableDescriptor.getTableName()
88 , EventType.C_M_CREATE_TABLE.toString());
89 }
90
91 @Override
92 public CreateTableHandler prepare()
93 throws NotAllMetaRegionsOnlineException, TableExistsException, IOException {
94 int timeout = conf.getInt("hbase.client.catalog.timeout", 10000);
95
96 try {
97 if (server.getMetaTableLocator().waitMetaRegionLocation(
98 server.getZooKeeper(), timeout) == null) {
99 throw new NotAllMetaRegionsOnlineException();
100 }
101
102
103
104 this.activeUser = RpcServer.getRequestUser();
105 if (this.activeUser == null) {
106 this.activeUser = UserProvider.instantiate(conf).getCurrent();
107 }
108 } catch (InterruptedException e) {
109 LOG.warn("Interrupted waiting for meta availability", e);
110 InterruptedIOException ie = new InterruptedIOException(e.getMessage());
111 ie.initCause(e);
112 throw ie;
113 }
114
115
116 this.tableLock.acquire();
117 boolean success = false;
118 try {
119 TableName tableName = this.hTableDescriptor.getTableName();
120 if (MetaTableAccessor.tableExists(this.server.getConnection(), tableName)) {
121 throw new TableExistsException(tableName);
122 }
123
124
125
126
127 boolean skipTableStateCheck =
128 !((HMaster) this.server).isInitialized() && tableName.isSystemTable();
129 checkAndSetEnablingTable(assignmentManager, tableName, skipTableStateCheck);
130 success = true;
131 } finally {
132 if (!success) {
133 releaseTableLock();
134 }
135 }
136 return this;
137 }
138
139 static void checkAndSetEnablingTable(final AssignmentManager assignmentManager,
140 final TableName tableName, boolean skipTableStateCheck) throws IOException {
141
142
143
144
145
146
147
148
149
150
151 try {
152 if (skipTableStateCheck) {
153 assignmentManager.getTableStateManager().setTableState(
154 tableName,
155 ZooKeeperProtos.Table.State.ENABLING);
156 } else if (!assignmentManager.getTableStateManager().setTableStateIfNotInStates(
157 tableName,
158 ZooKeeperProtos.Table.State.ENABLING,
159 ZooKeeperProtos.Table.State.ENABLING,
160 ZooKeeperProtos.Table.State.ENABLED)) {
161 throw new TableExistsException(tableName);
162 }
163 } catch (CoordinatedStateException e) {
164 throw new IOException("Unable to ensure that the table will be" +
165 " enabling because of a ZooKeeper issue", e);
166 }
167 }
168
169 static void removeEnablingTable(final AssignmentManager assignmentManager,
170 final TableName tableName) {
171
172
173
174
175 try {
176 assignmentManager.getTableStateManager().checkAndRemoveTableState(tableName,
177 ZooKeeperProtos.Table.State.ENABLING, false);
178 } catch (CoordinatedStateException e) {
179
180 LOG.error("Got a keeper exception while removing the ENABLING table znode "
181 + tableName, e);
182 }
183 }
184
185 @Override
186 public String toString() {
187 String name = "UnknownServerName";
188 if(server != null && server.getServerName() != null) {
189 name = server.getServerName().toString();
190 }
191 return getClass().getSimpleName() + "-" + name + "-" + getSeqid() + "-" +
192 this.hTableDescriptor.getTableName();
193 }
194
195 @Override
196 public void process() {
197 TableName tableName = this.hTableDescriptor.getTableName();
198 LOG.info("Create table " + tableName);
199 HMaster master = ((HMaster) this.server);
200 try {
201 final MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost();
202 if (cpHost != null) {
203 cpHost.preCreateTableHandler(this.hTableDescriptor, this.newRegions);
204 }
205 handleCreateTable(tableName);
206 completed(null);
207 if (cpHost != null) {
208 this.activeUser.runAs(new PrivilegedExceptionAction<Void>() {
209 @Override
210 public Void run() throws Exception {
211 cpHost.postCreateTableHandler(hTableDescriptor, newRegions);
212 return null;
213 }
214 });
215 }
216 } catch (Throwable e) {
217 LOG.error("Error trying to create the table " + tableName, e);
218 if (master.isInitialized()) {
219 try {
220 ((HMaster) this.server).getMasterQuotaManager().removeTableFromNamespaceQuota(
221 hTableDescriptor.getTableName());
222 } catch (IOException e1) {
223 LOG.error("Error trying to update namespace quota " + e1);
224 }
225 }
226 completed(e);
227 }
228 }
229
230
231
232
233
234 protected void completed(final Throwable exception) {
235 releaseTableLock();
236 LOG.info("Table, " + this.hTableDescriptor.getTableName() + ", creation " +
237 (exception == null ? "successful" : "failed. " + exception));
238 if (exception != null) {
239 removeEnablingTable(this.assignmentManager, this.hTableDescriptor.getTableName());
240 }
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257 private void handleCreateTable(TableName tableName)
258 throws IOException, CoordinatedStateException {
259 Path tempdir = fileSystemManager.getTempDir();
260 FileSystem fs = fileSystemManager.getFileSystem();
261
262
263 Path tempTableDir = FSUtils.getTableDir(tempdir, tableName);
264 new FSTableDescriptors(this.conf).createTableDescriptorForTableDirectory(
265 tempTableDir, this.hTableDescriptor, false);
266 Path tableDir = FSUtils.getTableDir(fileSystemManager.getRootDir(), tableName);
267
268
269 List<HRegionInfo> regionInfos = handleCreateHdfsRegions(tempdir, tableName);
270
271 if (!fs.rename(tempTableDir, tableDir)) {
272 throw new IOException("Unable to move table from temp=" + tempTableDir +
273 " to hbase root=" + tableDir);
274 }
275
276 if (regionInfos != null && regionInfos.size() > 0) {
277
278 addRegionsToMeta(regionInfos, hTableDescriptor.getRegionReplication());
279
280 regionInfos = addReplicas(hTableDescriptor, regionInfos);
281
282
283 if (hTableDescriptor.getRegionReplication() > 1) {
284 ServerRegionReplicaUtil.setupRegionReplicaReplication(conf);
285 }
286
287
288 ModifyRegionUtils.assignRegions(assignmentManager, regionInfos);
289 }
290
291
292 try {
293 assignmentManager.getTableStateManager().setTableState(tableName,
294 ZooKeeperProtos.Table.State.ENABLED);
295 } catch (CoordinatedStateException e) {
296 throw new IOException("Unable to ensure that " + tableName + " will be" +
297 " enabled because of a ZooKeeper issue", e);
298 }
299
300
301 ((HMaster) this.server).getTableDescriptors().get(tableName);
302 }
303
304
305
306
307
308
309
310
311 protected List<HRegionInfo> addReplicas(HTableDescriptor hTableDescriptor,
312 List<HRegionInfo> regions) {
313 int numRegionReplicas = hTableDescriptor.getRegionReplication() - 1;
314 if (numRegionReplicas <= 0) {
315 return regions;
316 }
317 List<HRegionInfo> hRegionInfos =
318 new ArrayList<HRegionInfo>((numRegionReplicas+1)*regions.size());
319 for (int i = 0; i < regions.size(); i++) {
320 for (int j = 1; j <= numRegionReplicas; j++) {
321 hRegionInfos.add(RegionReplicaUtil.getRegionInfoForReplica(regions.get(i), j));
322 }
323 }
324 hRegionInfos.addAll(regions);
325 return hRegionInfos;
326 }
327
328 private void releaseTableLock() {
329 if (this.tableLock != null) {
330 try {
331 this.tableLock.release();
332 } catch (IOException ex) {
333 LOG.warn("Could not release the table lock", ex);
334 }
335 }
336 }
337
338
339
340
341
342
343
344 protected List<HRegionInfo> handleCreateHdfsRegions(final Path tableRootDir,
345 final TableName tableName)
346 throws IOException {
347 return ModifyRegionUtils.createRegions(conf, tableRootDir,
348 hTableDescriptor, newRegions, null);
349 }
350
351
352
353
354 protected void addRegionsToMeta(final List<HRegionInfo> regionInfos, int regionReplication)
355 throws IOException {
356 MetaTableAccessor.addRegionsToMeta(this.server.getConnection(), regionInfos, regionReplication);
357 }
358 }