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.List;
24 import java.util.concurrent.ExecutorService;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.hbase.HRegionInfo;
29 import org.apache.hadoop.hbase.Server;
30 import org.apache.hadoop.hbase.TableNotDisabledException;
31 import org.apache.hadoop.hbase.TableNotFoundException;
32 import org.apache.hadoop.hbase.catalog.CatalogTracker;
33 import org.apache.hadoop.hbase.catalog.MetaReader;
34 import org.apache.hadoop.hbase.executor.EventHandler;
35 import org.apache.hadoop.hbase.master.AssignmentManager;
36 import org.apache.hadoop.hbase.master.BulkAssigner;
37 import org.apache.hadoop.hbase.util.Bytes;
38 import org.apache.zookeeper.KeeperException;
39
40
41
42
43 public class EnableTableHandler extends EventHandler {
44 private static final Log LOG = LogFactory.getLog(EnableTableHandler.class);
45 private final byte [] tableName;
46 private final String tableNameStr;
47 private final AssignmentManager assignmentManager;
48 private final CatalogTracker ct;
49
50 public EnableTableHandler(Server server, byte [] tableName,
51 CatalogTracker catalogTracker, AssignmentManager assignmentManager,
52 boolean skipTableStateCheck)
53 throws TableNotFoundException, TableNotDisabledException, IOException {
54 super(server, EventType.C_M_ENABLE_TABLE);
55 this.tableName = tableName;
56 this.tableNameStr = Bytes.toString(tableName);
57 this.ct = catalogTracker;
58 this.assignmentManager = assignmentManager;
59
60 if (!MetaReader.tableExists(catalogTracker, this.tableNameStr)) {
61 throw new TableNotFoundException(Bytes.toString(tableName));
62 }
63
64
65
66
67
68 if (!skipTableStateCheck)
69 {
70 try {
71 if (!this.assignmentManager.getZKTable().checkDisabledAndSetEnablingTable
72 (this.tableNameStr)) {
73 LOG.info("Table " + tableNameStr + " isn't disabled; skipping enable");
74 throw new TableNotDisabledException(this.tableNameStr);
75 }
76 } catch (KeeperException e) {
77 throw new IOException("Unable to ensure that the table will be" +
78 " enabling because of a ZooKeeper issue", e);
79 }
80 }
81 }
82
83 @Override
84 public String toString() {
85 String name = "UnknownServerName";
86 if(server != null && server.getServerName() != null) {
87 name = server.getServerName().toString();
88 }
89 return getClass().getSimpleName() + "-" + name + "-" + getSeqid() + "-" +
90 tableNameStr;
91 }
92
93 @Override
94 public void process() {
95 try {
96 LOG.info("Attemping to enable the table " + this.tableNameStr);
97 handleEnableTable();
98 } catch (IOException e) {
99 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
100 } catch (KeeperException e) {
101 LOG.error("Error trying to enable the table " + this.tableNameStr, e);
102 }
103 }
104
105 private void handleEnableTable() throws IOException, KeeperException {
106
107
108
109
110 this.assignmentManager.getZKTable().setEnablingTable(this.tableNameStr);
111 boolean done = false;
112
113
114 List<HRegionInfo> regionsInMeta;
115 regionsInMeta = MetaReader.getTableRegions(this.ct, tableName, true);
116 int countOfRegionsInTable = regionsInMeta.size();
117 List<HRegionInfo> regions = regionsToAssign(regionsInMeta);
118 int regionsCount = regions.size();
119 if (regionsCount == 0) {
120 done = true;
121 }
122 LOG.info("Table has " + countOfRegionsInTable + " regions of which " +
123 regionsCount + " are offline.");
124 BulkEnabler bd = new BulkEnabler(this.server, regions,
125 countOfRegionsInTable);
126 try {
127 if (bd.bulkAssign()) {
128 done = true;
129 }
130 } catch (InterruptedException e) {
131 LOG.warn("Enable was interrupted");
132
133 Thread.currentThread().interrupt();
134 }
135
136 if (done) this.assignmentManager.getZKTable().setEnabledTable(
137 this.tableNameStr);
138 LOG.info("Enabled table is done=" + done);
139 }
140
141
142
143
144
145
146
147 private List<HRegionInfo> regionsToAssign(
148 final List<HRegionInfo> regionsInMeta)
149 throws IOException {
150 final List<HRegionInfo> onlineRegions =
151 this.assignmentManager.getRegionsOfTable(tableName);
152 regionsInMeta.removeAll(onlineRegions);
153 return regionsInMeta;
154 }
155
156
157
158
159 class BulkEnabler extends BulkAssigner {
160 private final List<HRegionInfo> regions;
161
162 private final int countOfRegionsInTable;
163
164 BulkEnabler(final Server server, final List<HRegionInfo> regions,
165 final int countOfRegionsInTable) {
166 super(server);
167 this.regions = regions;
168 this.countOfRegionsInTable = countOfRegionsInTable;
169 }
170
171 @Override
172 protected void populatePool(ExecutorService pool) {
173 for (HRegionInfo region: regions) {
174 if (assignmentManager.isRegionInTransition(region) != null) continue;
175 final HRegionInfo hri = region;
176 pool.execute(new Runnable() {
177 public void run() {
178 assignmentManager.assign(hri, true);
179 }
180 });
181 }
182 }
183
184 @Override
185 protected boolean waitUntilDone(long timeout)
186 throws InterruptedException {
187 long startTime = System.currentTimeMillis();
188 long remaining = timeout;
189 List<HRegionInfo> regions = null;
190 int lastNumberOfRegions = this.countOfRegionsInTable;
191 while (!server.isStopped() && remaining > 0) {
192 Thread.sleep(waitingTimeForEvents);
193 regions = assignmentManager.getRegionsOfTable(tableName);
194 if (isDone(regions)) break;
195
196
197 if (regions.size() > lastNumberOfRegions) {
198 lastNumberOfRegions = regions.size();
199 timeout += waitingTimeForEvents;
200 }
201 remaining = timeout - (System.currentTimeMillis() - startTime);
202 }
203 return isDone(regions);
204 }
205
206 private boolean isDone(final List<HRegionInfo> regions) {
207 return regions != null && regions.size() >= this.countOfRegionsInTable;
208 }
209 }
210 }