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