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 } catch (KeeperException e) {
77
78 LOG.warn("Failed to delete the ENABLING node for the table " + tableNameStr
79 + ". The table will remain unusable. Run HBCK to manually fix the problem.");
80 }
81 }
82
83
84
85
86
87 if (!skipTableStateCheck)
88 {
89 try {
90 if (!this.assignmentManager.getZKTable().checkDisabledAndSetEnablingTable
91 (this.tableNameStr)) {
92 LOG.info("Table " + tableNameStr + " isn't disabled; skipping enable");
93 throw new TableNotDisabledException(this.tableNameStr);
94 }
95 } catch (KeeperException e) {
96 throw new IOException("Unable to ensure that the table will be" +
97 " enabling because of a ZooKeeper issue", e);
98 }
99 }
100 }
101
102 @Override
103 public String toString() {
104 String name = "UnknownServerName";
105 if(server != null && server.getServerName() != null) {
106 name = server.getServerName().toString();
107 }
108 return getClass().getSimpleName() + "-" + name + "-" + getSeqid() + "-" +
109 tableNameStr;
110 }
111
112 @Override
113 public void process() {
114 try {
115 LOG.info("Attemping to enable the table " + this.tableNameStr);
116 handleEnableTable();
117 } catch (IOException e) {
118 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
119 } catch (KeeperException e) {
120 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
121 } catch (InterruptedException e) {
122 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
123 }
124 }
125
126 private void handleEnableTable() throws IOException, KeeperException, InterruptedException {
127
128
129
130
131 this.assignmentManager.getZKTable().setEnablingTable(this.tableNameStr);
132 boolean done = false;
133
134
135 List<Pair<HRegionInfo, ServerName>> tableRegionsAndLocations = MetaReader
136 .getTableRegionsAndLocations(this.ct, tableName, true);
137 int countOfRegionsInTable = tableRegionsAndLocations.size();
138 List<HRegionInfo> regions = regionsToAssignWithServerName(tableRegionsAndLocations);
139 int regionsCount = regions.size();
140 if (regionsCount == 0) {
141 done = true;
142 }
143 LOG.info("Table has " + countOfRegionsInTable + " regions of which " +
144 regionsCount + " are offline.");
145 BulkEnabler bd = new BulkEnabler(this.server, regions, countOfRegionsInTable, true);
146 try {
147 if (bd.bulkAssign()) {
148 done = true;
149 }
150 } catch (InterruptedException e) {
151 LOG.warn("Enable was interrupted");
152
153 Thread.currentThread().interrupt();
154 }
155
156 if (done) this.assignmentManager.getZKTable().setEnabledTable(
157 this.tableNameStr);
158 LOG.info("Enabled table is done=" + done);
159 }
160
161
162
163
164
165
166 private List<HRegionInfo> regionsToAssignWithServerName(
167 final List<Pair<HRegionInfo, ServerName>> regionsInMeta) throws IOException {
168 ServerManager serverManager = ((HMaster) this.server).getServerManager();
169 List<HRegionInfo> regions = new ArrayList<HRegionInfo>();
170 List<HRegionInfo> enablingTableRegions = this.assignmentManager
171 .getEnablingTableRegions(this.tableNameStr);
172 final List<HRegionInfo> onlineRegions = this.assignmentManager.getRegionsOfTable(tableName);
173 for (Pair<HRegionInfo, ServerName> regionLocation : regionsInMeta) {
174 HRegionInfo hri = regionLocation.getFirst();
175 ServerName sn = regionLocation.getSecond();
176 if (this.skipTableStateCheck) {
177
178 if (enablingTableRegions != null && enablingTableRegions.contains(hri)) {
179 regions.add(hri);
180 if (sn != null && serverManager.isServerOnline(sn)) {
181 this.assignmentManager.addPlan(hri.getEncodedName(), new RegionPlan(hri, null, sn));
182 }
183 }
184 } else if (onlineRegions.contains(hri)) {
185 continue;
186 } else {
187 regions.add(hri);
188 if (sn != null && serverManager.isServerOnline(sn)) {
189 this.assignmentManager.addPlan(hri.getEncodedName(), new RegionPlan(hri, null, sn));
190 }
191 }
192 }
193 return regions;
194 }
195
196
197
198
199 class BulkEnabler extends BulkAssigner {
200 private final List<HRegionInfo> regions;
201
202 private final int countOfRegionsInTable;
203
204 BulkEnabler(final Server server, final List<HRegionInfo> regions,
205 final int countOfRegionsInTable,final boolean retainAssignment) {
206 super(server);
207 this.regions = regions;
208 this.countOfRegionsInTable = countOfRegionsInTable;
209 }
210
211 @Override
212 protected void populatePool(ExecutorService pool) throws IOException {
213 for (HRegionInfo region : regions) {
214 if (assignmentManager.isRegionInTransition(region) != null) {
215 continue;
216 }
217 final HRegionInfo hri = region;
218 pool.execute(new Runnable() {
219 public void run() {
220 assignmentManager.assign(hri, true, false, false);
221 }
222 });
223 }
224 }
225
226 @Override
227 protected boolean waitUntilDone(long timeout)
228 throws InterruptedException {
229 long startTime = System.currentTimeMillis();
230 long remaining = timeout;
231 List<HRegionInfo> regions = null;
232 int lastNumberOfRegions = 0;
233 while (!server.isStopped() && remaining > 0) {
234 Thread.sleep(waitingTimeForEvents);
235 regions = assignmentManager.getRegionsOfTable(tableName);
236 if (isDone(regions)) break;
237
238
239 if (regions.size() > lastNumberOfRegions) {
240 lastNumberOfRegions = regions.size();
241 timeout += waitingTimeForEvents;
242 }
243 remaining = timeout - (System.currentTimeMillis() - startTime);
244 }
245 return isDone(regions);
246 }
247
248 private boolean isDone(final List<HRegionInfo> regions) {
249 return regions != null && regions.size() >= this.countOfRegionsInTable;
250 }
251 }
252 }