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