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.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.TableName;
33 import org.apache.hadoop.hbase.HRegionInfo;
34 import org.apache.hadoop.hbase.HTableDescriptor;
35 import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException;
36 import org.apache.hadoop.hbase.Server;
37 import org.apache.hadoop.hbase.TableExistsException;
38 import org.apache.hadoop.hbase.catalog.CatalogTracker;
39 import org.apache.hadoop.hbase.catalog.MetaEditor;
40 import org.apache.hadoop.hbase.catalog.MetaReader;
41 import org.apache.hadoop.hbase.executor.EventHandler;
42 import org.apache.hadoop.hbase.executor.EventType;
43 import org.apache.hadoop.hbase.ipc.RequestContext;
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.security.User;
52 import org.apache.hadoop.hbase.security.UserProvider;
53 import org.apache.hadoop.hbase.util.FSTableDescriptors;
54 import org.apache.hadoop.hbase.util.FSUtils;
55 import org.apache.hadoop.hbase.util.ModifyRegionUtils;
56 import org.apache.zookeeper.KeeperException;
57
58
59
60
61 @InterfaceAudience.Private
62 public class CreateTableHandler extends EventHandler {
63 private static final Log LOG = LogFactory.getLog(CreateTableHandler.class);
64 protected final MasterFileSystem fileSystemManager;
65 protected final HTableDescriptor hTableDescriptor;
66 protected final Configuration conf;
67 private final AssignmentManager assignmentManager;
68 private final CatalogTracker catalogTracker;
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.catalogTracker = masterServices.getCatalogTracker();
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 public CreateTableHandler prepare()
92 throws NotAllMetaRegionsOnlineException, TableExistsException, IOException {
93 int timeout = conf.getInt("hbase.client.catalog.timeout", 10000);
94
95 try {
96 if(catalogTracker.waitForMeta(timeout) == null) {
97 throw new NotAllMetaRegionsOnlineException();
98 }
99
100
101
102 if (RequestContext.isInRequestContext()) {
103 this.activeUser = RequestContext.getRequestUser();
104 } else {
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 (MetaReader.tableExists(catalogTracker, tableName)) {
120 throw new TableExistsException(tableName);
121 }
122
123
124
125
126
127
128
129
130
131 try {
132 if (!this.assignmentManager.getZKTable().checkAndSetEnablingTable(tableName)) {
133 throw new TableExistsException(tableName);
134 }
135 } catch (KeeperException e) {
136 throw new IOException("Unable to ensure that the table will be" +
137 " enabling because of a ZooKeeper issue", e);
138 }
139 success = true;
140 } finally {
141 if (!success) {
142 releaseTableLock();
143 }
144 }
145 return this;
146 }
147
148 @Override
149 public String toString() {
150 String name = "UnknownServerName";
151 if(server != null && server.getServerName() != null) {
152 name = server.getServerName().toString();
153 }
154 return getClass().getSimpleName() + "-" + name + "-" + getSeqid() + "-" +
155 this.hTableDescriptor.getTableName();
156 }
157
158 @Override
159 public void process() {
160 TableName tableName = this.hTableDescriptor.getTableName();
161 LOG.info("Create table " + tableName);
162
163 try {
164 final MasterCoprocessorHost cpHost = ((HMaster) this.server).getCoprocessorHost();
165 if (cpHost != null) {
166 cpHost.preCreateTableHandler(this.hTableDescriptor, this.newRegions);
167 }
168 handleCreateTable(tableName);
169 completed(null);
170 if (cpHost != null) {
171 this.activeUser.runAs(new PrivilegedExceptionAction<Void>() {
172 @Override
173 public Void run() throws Exception {
174 cpHost.postCreateTableHandler(hTableDescriptor, newRegions);
175 return null;
176 }
177 });
178 }
179 } catch (Throwable e) {
180 LOG.error("Error trying to create the table " + tableName, e);
181 completed(e);
182 }
183 }
184
185
186
187
188
189 protected void completed(final Throwable exception) {
190 releaseTableLock();
191 String msg = exception == null ? null : exception.getMessage();
192 LOG.info("Table, " + this.hTableDescriptor.getTableName() + ", creation " +
193 msg == null ? "successful" : "failed. " + msg);
194 if (exception != null) {
195
196
197
198
199 try {
200 this.assignmentManager.getZKTable().removeEnablingTable(
201 this.hTableDescriptor.getTableName(), false);
202 } catch (KeeperException e) {
203
204 LOG.error("Got a keeper exception while removing the ENABLING table znode "
205 + this.hTableDescriptor.getTableName(), e);
206 }
207 }
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 private void handleCreateTable(TableName tableName)
225 throws IOException, KeeperException {
226 Path tempdir = fileSystemManager.getTempDir();
227 FileSystem fs = fileSystemManager.getFileSystem();
228
229
230 Path tempTableDir = FSUtils.getTableDir(tempdir, tableName);
231 new FSTableDescriptors(this.conf).createTableDescriptorForTableDirectory(
232 tempTableDir, this.hTableDescriptor, false);
233 Path tableDir = FSUtils.getTableDir(fileSystemManager.getRootDir(), tableName);
234
235
236 List<HRegionInfo> regionInfos = handleCreateHdfsRegions(tempdir, tableName);
237
238 if (!fs.rename(tempTableDir, tableDir)) {
239 throw new IOException("Unable to move table from temp=" + tempTableDir +
240 " to hbase root=" + tableDir);
241 }
242
243 if (regionInfos != null && regionInfos.size() > 0) {
244
245 addRegionsToMeta(this.catalogTracker, regionInfos);
246
247
248 try {
249 assignmentManager.getRegionStates().createRegionStates(regionInfos);
250 assignmentManager.assign(regionInfos);
251 } catch (InterruptedException e) {
252 LOG.error("Caught " + e + " during round-robin assignment");
253 InterruptedIOException ie = new InterruptedIOException(e.getMessage());
254 ie.initCause(e);
255 throw ie;
256 }
257 }
258
259
260 try {
261 assignmentManager.getZKTable().setEnabledTable(tableName);
262 } catch (KeeperException e) {
263 throw new IOException("Unable to ensure that " + tableName + " will be" +
264 " enabled because of a ZooKeeper issue", e);
265 }
266
267
268 ((HMaster) this.server).getTableDescriptors().get(tableName);
269 }
270
271 private void releaseTableLock() {
272 if (this.tableLock != null) {
273 try {
274 this.tableLock.release();
275 } catch (IOException ex) {
276 LOG.warn("Could not release the table lock", ex);
277 }
278 }
279 }
280
281
282
283
284
285
286
287 protected List<HRegionInfo> handleCreateHdfsRegions(final Path tableRootDir,
288 final TableName tableName)
289 throws IOException {
290 return ModifyRegionUtils.createRegions(conf, tableRootDir,
291 hTableDescriptor, newRegions, null);
292 }
293
294
295
296
297 protected void addRegionsToMeta(final CatalogTracker ct, final List<HRegionInfo> regionInfos)
298 throws IOException {
299 MetaEditor.addRegionsToMeta(this.catalogTracker, regionInfos);
300 }
301 }