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.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.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 this.activeUser = RpcServer.getRequestUser();
103 if (this.activeUser == null) {
104 this.activeUser = UserProvider.instantiate(conf).getCurrent();
105 }
106 } catch (InterruptedException e) {
107 LOG.warn("Interrupted waiting for meta availability", e);
108 InterruptedIOException ie = new InterruptedIOException(e.getMessage());
109 ie.initCause(e);
110 throw ie;
111 }
112
113
114 this.tableLock.acquire();
115 boolean success = false;
116 try {
117 TableName tableName = this.hTableDescriptor.getTableName();
118 if (MetaReader.tableExists(catalogTracker, tableName)) {
119 throw new TableExistsException(tableName);
120 }
121
122
123
124
125
126
127
128
129
130 try {
131
132
133
134 if (!((HMaster) this.server).isInitialized() && tableName.isSystemTable()) {
135 this.assignmentManager.getZKTable().setEnablingTable(tableName);
136 } else if (!this.assignmentManager.getZKTable().checkAndSetEnablingTable(tableName)) {
137 throw new TableExistsException(tableName);
138 }
139 } catch (KeeperException e) {
140 throw new IOException("Unable to ensure that the table will be" +
141 " enabling because of a ZooKeeper issue", e);
142 }
143 success = true;
144 } finally {
145 if (!success) {
146 releaseTableLock();
147 }
148 }
149 return this;
150 }
151
152 @Override
153 public String toString() {
154 String name = "UnknownServerName";
155 if(server != null && server.getServerName() != null) {
156 name = server.getServerName().toString();
157 }
158 return getClass().getSimpleName() + "-" + name + "-" + getSeqid() + "-" +
159 this.hTableDescriptor.getTableName();
160 }
161
162 @Override
163 public void process() {
164 TableName tableName = this.hTableDescriptor.getTableName();
165 LOG.info("Create table " + tableName);
166
167 try {
168 final MasterCoprocessorHost cpHost = ((HMaster) this.server).getCoprocessorHost();
169 if (cpHost != null) {
170 cpHost.preCreateTableHandler(this.hTableDescriptor, this.newRegions);
171 }
172 handleCreateTable(tableName);
173 completed(null);
174 if (cpHost != null) {
175 this.activeUser.runAs(new PrivilegedExceptionAction<Void>() {
176 @Override
177 public Void run() throws Exception {
178 cpHost.postCreateTableHandler(hTableDescriptor, newRegions);
179 return null;
180 }
181 });
182 }
183 } catch (Throwable e) {
184 LOG.error("Error trying to create the table " + tableName, e);
185 completed(e);
186 }
187 }
188
189
190
191
192
193 protected void completed(final Throwable exception) {
194 releaseTableLock();
195 String msg = exception == null ? null : exception.getMessage();
196 LOG.info("Table, " + this.hTableDescriptor.getTableName() + ", creation " +
197 msg == null ? "successful" : "failed. " + msg);
198 if (exception != null) {
199
200
201
202
203 try {
204 this.assignmentManager.getZKTable().removeEnablingTable(
205 this.hTableDescriptor.getTableName(), false);
206 } catch (KeeperException e) {
207
208 LOG.error("Got a keeper exception while removing the ENABLING table znode "
209 + this.hTableDescriptor.getTableName(), e);
210 }
211 }
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 private void handleCreateTable(TableName tableName)
229 throws IOException, KeeperException {
230 Path tempdir = fileSystemManager.getTempDir();
231 FileSystem fs = fileSystemManager.getFileSystem();
232
233
234 Path tempTableDir = FSUtils.getTableDir(tempdir, tableName);
235 new FSTableDescriptors(this.conf).createTableDescriptorForTableDirectory(
236 tempTableDir, this.hTableDescriptor, false);
237 Path tableDir = FSUtils.getTableDir(fileSystemManager.getRootDir(), tableName);
238
239
240 List<HRegionInfo> regionInfos = handleCreateHdfsRegions(tempdir, tableName);
241
242 if (!fs.rename(tempTableDir, tableDir)) {
243 throw new IOException("Unable to move table from temp=" + tempTableDir +
244 " to hbase root=" + tableDir);
245 }
246
247 if (regionInfos != null && regionInfos.size() > 0) {
248
249 addRegionsToMeta(this.catalogTracker, regionInfos);
250
251
252 try {
253 assignmentManager.getRegionStates().createRegionStates(regionInfos);
254 assignmentManager.assign(regionInfos);
255 } catch (InterruptedException e) {
256 LOG.error("Caught " + e + " during round-robin assignment");
257 InterruptedIOException ie = new InterruptedIOException(e.getMessage());
258 ie.initCause(e);
259 throw ie;
260 }
261 }
262
263
264 try {
265 assignmentManager.getZKTable().setEnabledTable(tableName);
266 } catch (KeeperException e) {
267 throw new IOException("Unable to ensure that " + tableName + " will be" +
268 " enabled because of a ZooKeeper issue", e);
269 }
270
271
272 ((HMaster) this.server).getTableDescriptors().get(tableName);
273 }
274
275 private void releaseTableLock() {
276 if (this.tableLock != null) {
277 try {
278 this.tableLock.release();
279 } catch (IOException ex) {
280 LOG.warn("Could not release the table lock", ex);
281 }
282 }
283 }
284
285
286
287
288
289
290
291 protected List<HRegionInfo> handleCreateHdfsRegions(final Path tableRootDir,
292 final TableName tableName)
293 throws IOException {
294 return ModifyRegionUtils.createRegions(conf, tableRootDir,
295 hTableDescriptor, newRegions, null);
296 }
297
298
299
300
301 protected void addRegionsToMeta(final CatalogTracker ct, final List<HRegionInfo> regionInfos)
302 throws IOException {
303 MetaEditor.addRegionsToMeta(this.catalogTracker, regionInfos);
304 }
305 }