1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.master.handler;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.concurrent.ExecutorService;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.hbase.HRegionInfo;
30 import org.apache.hadoop.hbase.Server;
31 import org.apache.hadoop.hbase.ServerName;
32 import org.apache.hadoop.hbase.TableNotDisabledException;
33 import org.apache.hadoop.hbase.TableNotFoundException;
34 import org.apache.hadoop.hbase.catalog.CatalogTracker;
35 import org.apache.hadoop.hbase.catalog.MetaReader;
36 import org.apache.hadoop.hbase.executor.EventHandler;
37 import org.apache.hadoop.hbase.master.AssignmentManager;
38 import org.apache.hadoop.hbase.master.BulkAssigner;
39 import org.apache.hadoop.hbase.master.HMaster;
40 import org.apache.hadoop.hbase.master.RegionPlan;
41 import org.apache.hadoop.hbase.master.ServerManager;
42 import org.apache.hadoop.hbase.util.Bytes;
43 import org.apache.hadoop.hbase.util.Pair;
44 import org.apache.zookeeper.KeeperException;
45
46
47
48
49 public class EnableTableHandler extends EventHandler {
50 private static final Log LOG = LogFactory.getLog(EnableTableHandler.class);
51 private final byte [] tableName;
52 private final String tableNameStr;
53 private final AssignmentManager assignmentManager;
54 private final CatalogTracker ct;
55 private boolean skipTableStateCheck = false;
56
57 public EnableTableHandler(Server server, byte [] tableName,
58 CatalogTracker catalogTracker, AssignmentManager assignmentManager,
59 boolean skipTableStateCheck)
60 throws TableNotFoundException, TableNotDisabledException, IOException {
61 super(server, EventType.C_M_ENABLE_TABLE);
62 this.tableName = tableName;
63 this.tableNameStr = Bytes.toString(tableName);
64 this.ct = catalogTracker;
65 this.assignmentManager = assignmentManager;
66 this.skipTableStateCheck = skipTableStateCheck;
67
68 if (!MetaReader.tableExists(catalogTracker, this.tableNameStr)) {
69
70
71 if (!this.skipTableStateCheck) {
72 throw new TableNotFoundException(tableNameStr);
73 }
74 try {
75 this.assignmentManager.getZKTable().removeEnablingTable(tableNameStr, true);
76 throw new TableNotFoundException(tableNameStr);
77 } catch (KeeperException e) {
78
79 LOG.warn("Failed to delete the ENABLING node for the table " + tableNameStr
80 + ". The table will remain unusable. Run HBCK to manually fix the problem.");
81 }
82 }
83
84
85
86
87
88 if (!skipTableStateCheck)
89 {
90 try {
91 if (!this.assignmentManager.getZKTable().checkDisabledAndSetEnablingTable
92 (this.tableNameStr)) {
93 LOG.info("Table " + tableNameStr + " isn't disabled; skipping enable");
94 throw new TableNotDisabledException(this.tableNameStr);
95 }
96 } catch (KeeperException e) {
97 throw new IOException("Unable to ensure that the table will be" +
98 " enabling because of a ZooKeeper issue", e);
99 }
100 }
101 }
102
103 @Override
104 public String toString() {
105 String name = "UnknownServerName";
106 if(server != null && server.getServerName() != null) {
107 name = server.getServerName().toString();
108 }
109 return getClass().getSimpleName() + "-" + name + "-" + getSeqid() + "-" +
110 tableNameStr;
111 }
112
113 @Override
114 public void process() {
115 try {
116 LOG.info("Attemping to enable the table " + this.tableNameStr);
117 handleEnableTable();
118 } catch (IOException e) {
119 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
120 } catch (KeeperException e) {
121 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
122 } catch (InterruptedException e) {
123 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
124 }
125 }
126
127 private void handleEnableTable() throws IOException, KeeperException, InterruptedException {
128
129
130
131
132 this.assignmentManager.getZKTable().setEnablingTable(this.tableNameStr);
133 boolean done = false;
134
135
136 List<Pair<HRegionInfo, ServerName>> tableRegionsAndLocations = MetaReader
137 .getTableRegionsAndLocations(this.ct, tableName, true);
138 int countOfRegionsInTable = tableRegionsAndLocations.size();
139 List<HRegionInfo> regions = regionsToAssignWithServerName(tableRegionsAndLocations);
140 int regionsCount = regions.size();
141 if (regionsCount == 0) {
142 done = true;
143 }
144 LOG.info("Table has " + countOfRegionsInTable + " regions of which " +
145 regionsCount + " are offline.");
146 BulkEnabler bd = new BulkEnabler(this.server, regions, countOfRegionsInTable, true);
147 try {
148 if (bd.bulkAssign()) {
149 done = true;
150 }
151 } catch (InterruptedException e) {
152 LOG.warn("Enable was interrupted");
153
154 Thread.currentThread().interrupt();
155 }
156
157 if (done) this.assignmentManager.getZKTable().setEnabledTable(
158 this.tableNameStr);
159 LOG.info("Enabled table is done=" + done);
160 }
161
162
163
164
165
166
167 private List<HRegionInfo> regionsToAssignWithServerName(
168 final List<Pair<HRegionInfo, ServerName>> regionsInMeta) throws IOException {
169 ServerManager serverManager = ((HMaster) this.server).getServerManager();
170 List<HRegionInfo> regions = new ArrayList<HRegionInfo>();
171 List<HRegionInfo> enablingTableRegions = this.assignmentManager
172 .getEnablingTableRegions(this.tableNameStr);
173 final List<HRegionInfo> onlineRegions = this.assignmentManager.getRegionsOfTable(tableName);
174 for (Pair<HRegionInfo, ServerName> regionLocation : regionsInMeta) {
175 HRegionInfo hri = regionLocation.getFirst();
176 ServerName sn = regionLocation.getSecond();
177 if (this.skipTableStateCheck) {
178
179 if (enablingTableRegions != null && enablingTableRegions.contains(hri)) {
180 regions.add(hri);
181 if (sn != null && serverManager.isServerOnline(sn)) {
182 this.assignmentManager.addPlan(hri.getEncodedName(), new RegionPlan(hri, null, sn));
183 }
184 }
185 } else if (onlineRegions.contains(hri)) {
186 continue;
187 } else {
188 regions.add(hri);
189 if (sn != null && serverManager.isServerOnline(sn)) {
190 this.assignmentManager.addPlan(hri.getEncodedName(), new RegionPlan(hri, null, sn));
191 }
192 }
193 }
194 return regions;
195 }
196
197
198
199
200 class BulkEnabler extends BulkAssigner {
201 private final List<HRegionInfo> regions;
202
203 private final int countOfRegionsInTable;
204
205 BulkEnabler(final Server server, final List<HRegionInfo> regions,
206 final int countOfRegionsInTable,final boolean retainAssignment) {
207 super(server);
208 this.regions = regions;
209 this.countOfRegionsInTable = countOfRegionsInTable;
210 }
211
212 @Override
213 protected void populatePool(ExecutorService pool) throws IOException {
214 for (HRegionInfo region : regions) {
215 if (assignmentManager.isRegionInTransition(region) != null) {
216 continue;
217 }
218 final HRegionInfo hri = region;
219 pool.execute(new Runnable() {
220 public void run() {
221 assignmentManager.assign(hri, true, false, false);
222 }
223 });
224 }
225 }
226
227 @Override
228 protected boolean waitUntilDone(long timeout)
229 throws InterruptedException {
230 long startTime = System.currentTimeMillis();
231 long remaining = timeout;
232 List<HRegionInfo> regions = null;
233 int lastNumberOfRegions = 0;
234 while (!server.isStopped() && remaining > 0) {
235 Thread.sleep(waitingTimeForEvents);
236 regions = assignmentManager.getRegionsOfTable(tableName);
237 if (isDone(regions)) break;
238
239
240 if (regions.size() > lastNumberOfRegions) {
241 lastNumberOfRegions = regions.size();
242 timeout += waitingTimeForEvents;
243 }
244 remaining = timeout - (System.currentTimeMillis() - startTime);
245 }
246 return isDone(regions);
247 }
248
249 private boolean isDone(final List<HRegionInfo> regions) {
250 return regions != null && regions.size() >= this.countOfRegionsInTable;
251 }
252 }
253 }