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.TableNotFoundException;
31 import org.apache.hadoop.hbase.catalog.CatalogTracker;
32 import org.apache.hadoop.hbase.catalog.MetaReader;
33 import org.apache.hadoop.hbase.executor.EventHandler;
34 import org.apache.hadoop.hbase.master.AssignmentManager;
35 import org.apache.hadoop.hbase.master.BulkAssigner;
36 import org.apache.hadoop.hbase.util.Bytes;
37 import org.apache.zookeeper.KeeperException;
38
39
40
41
42 public class DisableTableHandler extends EventHandler {
43 private static final Log LOG = LogFactory.getLog(DisableTableHandler.class);
44 private final byte [] tableName;
45 private final String tableNameStr;
46 private final AssignmentManager assignmentManager;
47
48 public DisableTableHandler(Server server, byte [] tableName,
49 CatalogTracker catalogTracker, AssignmentManager assignmentManager)
50 throws TableNotFoundException, IOException {
51 super(server, EventType.C_M_DISABLE_TABLE);
52 this.tableName = tableName;
53 this.tableNameStr = Bytes.toString(this.tableName);
54 this.assignmentManager = assignmentManager;
55
56
57
58
59 if (!MetaReader.tableExists(catalogTracker, this.tableNameStr)) {
60 throw new TableNotFoundException(Bytes.toString(tableName));
61 }
62 }
63
64 @Override
65 public void process() {
66 try {
67 LOG.info("Attemping to disable table " + this.tableNameStr);
68 handleDisableTable();
69 } catch (IOException e) {
70 LOG.error("Error trying to disable table " + this.tableNameStr, e);
71 } catch (KeeperException e) {
72 LOG.error("Error trying to disable table " + this.tableNameStr, e);
73 }
74 }
75
76 private void handleDisableTable() throws IOException, KeeperException {
77 if (this.assignmentManager.getZKTable().isDisabledTable(this.tableNameStr)) {
78 LOG.info("Table " + tableNameStr + " already disabled; skipping disable");
79 return;
80 }
81
82 this.assignmentManager.getZKTable().setDisablingTable(this.tableNameStr);
83 boolean done = false;
84 while (true) {
85
86
87
88
89 final List<HRegionInfo> regions =
90 this.assignmentManager.getRegionsOfTable(tableName);
91 if (regions.size() == 0) {
92 done = true;
93 break;
94 }
95 LOG.info("Offlining " + regions.size() + " regions.");
96 BulkDisabler bd = new BulkDisabler(this.server, regions);
97 try {
98 if (bd.bulkAssign()) {
99 done = true;
100 break;
101 }
102 } catch (InterruptedException e) {
103 LOG.warn("Disable was interrupted");
104
105 Thread.currentThread().interrupt();
106 break;
107 }
108 }
109
110 if (done) this.assignmentManager.getZKTable().setDisabledTable(this.tableNameStr);
111 LOG.info("Disabled table is done=" + done);
112 }
113
114
115
116
117 class BulkDisabler extends BulkAssigner {
118 private final List<HRegionInfo> regions;
119
120 BulkDisabler(final Server server, final List<HRegionInfo> regions) {
121 super(server);
122 this.regions = regions;
123 }
124
125 @Override
126 protected void populatePool(ExecutorService pool) {
127 for (HRegionInfo region: regions) {
128 if (assignmentManager.isRegionInTransition(region) != null) continue;
129 final HRegionInfo hri = region;
130 pool.execute(new Runnable() {
131 public void run() {
132 assignmentManager.unassign(hri);
133 }
134 });
135 }
136 }
137
138 @Override
139 protected boolean waitUntilDone(long timeout)
140 throws InterruptedException {
141 long startTime = System.currentTimeMillis();
142 long remaining = timeout;
143 List<HRegionInfo> regions = null;
144 while (!server.isStopped() && remaining > 0) {
145 Thread.sleep(waitingTimeForEvents);
146 regions = assignmentManager.getRegionsOfTable(tableName);
147 if (regions.isEmpty()) break;
148 remaining = timeout - (System.currentTimeMillis() - startTime);
149 }
150 return regions != null && regions.isEmpty();
151 }
152 }
153 }