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