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