1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.regionserver.handler;
20
21 import java.io.IOException;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.hadoop.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.HRegionInfo;
27 import org.apache.hadoop.hbase.Server;
28 import org.apache.hadoop.hbase.ServerName;
29 import org.apache.hadoop.hbase.executor.EventHandler;
30 import org.apache.hadoop.hbase.executor.EventType;
31 import org.apache.hadoop.hbase.regionserver.HRegion;
32 import org.apache.hadoop.hbase.regionserver.RegionServerServices;
33 import org.apache.hadoop.hbase.zookeeper.ZKAssign;
34 import org.apache.zookeeper.KeeperException;
35
36
37
38
39 @InterfaceAudience.Private
40 public class CloseRegionHandler extends EventHandler {
41
42
43
44
45
46 private static final Log LOG = LogFactory.getLog(CloseRegionHandler.class);
47
48 private final int FAILED = -1;
49 int expectedVersion = FAILED;
50
51 private final RegionServerServices rsServices;
52
53 private final HRegionInfo regionInfo;
54
55
56
57 private final boolean abort;
58
59
60
61
62
63 private final boolean zk;
64 private ServerName destination;
65
66
67 public CloseRegionHandler(final Server server,
68 final RegionServerServices rsServices, HRegionInfo regionInfo) {
69 this(server, rsServices, regionInfo, false, true, -1, EventType.M_RS_CLOSE_REGION, null);
70 }
71
72
73
74
75
76
77
78
79
80 public CloseRegionHandler(final Server server,
81 final RegionServerServices rsServices,
82 final HRegionInfo regionInfo, final boolean abort, final boolean zk,
83 final int versionOfClosingNode) {
84 this(server, rsServices, regionInfo, abort, zk, versionOfClosingNode,
85 EventType.M_RS_CLOSE_REGION, null);
86 }
87
88 public CloseRegionHandler(final Server server,
89 final RegionServerServices rsServices,
90 final HRegionInfo regionInfo, final boolean abort, final boolean zk,
91 final int versionOfClosingNode, ServerName destination) {
92 this(server, rsServices, regionInfo, abort, zk, versionOfClosingNode,
93 EventType.M_RS_CLOSE_REGION, destination);
94 }
95
96 public CloseRegionHandler(final Server server,
97 final RegionServerServices rsServices, HRegionInfo regionInfo,
98 boolean abort, final boolean zk, final int versionOfClosingNode,
99 EventType eventType) {
100 this(server, rsServices, regionInfo, abort, zk, versionOfClosingNode, eventType, null);
101 }
102
103 protected CloseRegionHandler(final Server server,
104 final RegionServerServices rsServices, HRegionInfo regionInfo,
105 boolean abort, final boolean zk, final int versionOfClosingNode,
106 EventType eventType, ServerName destination) {
107 super(server, eventType);
108 this.server = server;
109 this.rsServices = rsServices;
110 this.regionInfo = regionInfo;
111 this.abort = abort;
112 this.zk = zk;
113 this.expectedVersion = versionOfClosingNode;
114 this.destination = destination;
115 }
116
117 public HRegionInfo getRegionInfo() {
118 return regionInfo;
119 }
120
121 @Override
122 public void process() {
123 try {
124 String name = regionInfo.getRegionNameAsString();
125 LOG.debug("Processing close of " + name);
126 String encodedRegionName = regionInfo.getEncodedName();
127
128 HRegion region = this.rsServices.getFromOnlineRegions(encodedRegionName);
129 if (region == null) {
130 LOG.warn("Received CLOSE for region " + name + " but currently not serving - ignoring");
131 if (zk){
132 LOG.error("The znode is not modified as we are not serving " + name);
133 }
134
135 return;
136 }
137
138
139 try {
140 if (zk && !ZKAssign.checkClosingState(server.getZooKeeper(), regionInfo, expectedVersion)){
141
142 return;
143 }
144
145
146
147 if (region.close(abort) == null) {
148
149
150
151 LOG.warn("Can't close region: was already closed during close(): " +
152 regionInfo.getRegionNameAsString());
153 return;
154 }
155 } catch (Throwable t) {
156
157
158
159 server.abort("Unrecoverable exception while closing region " +
160 regionInfo.getRegionNameAsString() + ", still finishing close", t);
161 throw new RuntimeException(t);
162 }
163
164 this.rsServices.removeFromOnlineRegions(region, destination);
165
166 if (this.zk) {
167 if (setClosedState(this.expectedVersion, region)) {
168 LOG.debug("Set closed state in zk for " + name + " on " + this.server.getServerName());
169 } else {
170 LOG.debug("Set closed state in zk UNSUCCESSFUL for " + name + " on " +
171 this.server.getServerName());
172 }
173 }
174
175
176 LOG.debug("Closed " + region.getRegionNameAsString());
177 } finally {
178 this.rsServices.getRegionsInTransitionInRS().
179 remove(this.regionInfo.getEncodedNameAsBytes());
180 }
181 }
182
183
184
185
186
187
188 private boolean setClosedState(final int expectedVersion, final HRegion region) {
189 try {
190 if (ZKAssign.transitionNodeClosed(server.getZooKeeper(), regionInfo,
191 server.getServerName(), expectedVersion) == FAILED) {
192 LOG.warn("Completed the CLOSE of a region but when transitioning from " +
193 " CLOSING to CLOSED got a version mismatch, someone else clashed " +
194 "so now unassigning");
195 region.close();
196 return false;
197 }
198 } catch (NullPointerException e) {
199
200 LOG.warn("NPE during close -- catching and continuing...", e);
201 return false;
202 } catch (KeeperException e) {
203 LOG.error("Failed transitioning node from CLOSING to CLOSED", e);
204 return false;
205 } catch (IOException e) {
206 LOG.error("Failed to close region after failing to transition", e);
207 return false;
208 }
209 return true;
210 }
211 }