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;
20
21 import java.io.IOException;
22 import java.util.Comparator;
23 import java.util.List;
24
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.hbase.CellScanner;
27 import org.apache.hadoop.hbase.Coprocessor;
28 import org.apache.hadoop.hbase.CoprocessorEnvironment;
29 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
30 import org.apache.hadoop.hbase.MetaMutationAnnotation;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.hbase.classification.InterfaceStability;
33 import org.apache.hadoop.hbase.client.Mutation;
34 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
35 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
36 import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
37 import org.apache.hadoop.hbase.coprocessor.RegionServerObserver;
38 import org.apache.hadoop.hbase.coprocessor.SingletonCoprocessorService;
39 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.WALEntry;
40 import org.apache.hadoop.hbase.replication.ReplicationEndpoint;
41
42 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
43 @InterfaceStability.Evolving
44 public class RegionServerCoprocessorHost extends
45 CoprocessorHost<RegionServerCoprocessorHost.RegionServerEnvironment> {
46
47 private RegionServerServices rsServices;
48
49 public RegionServerCoprocessorHost(RegionServerServices rsServices,
50 Configuration conf) {
51 super(rsServices);
52 this.rsServices = rsServices;
53 this.conf = conf;
54
55 loadSystemCoprocessors(conf, REGIONSERVER_COPROCESSOR_CONF_KEY);
56 }
57
58 @Override
59 public RegionServerEnvironment createEnvironment(Class<?> implClass,
60 Coprocessor instance, int priority, int sequence, Configuration conf) {
61 return new RegionServerEnvironment(implClass, instance, priority,
62 sequence, conf, this.rsServices);
63 }
64
65 public void preStop(String message) throws IOException {
66 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
67 @Override
68 public void call(RegionServerObserver oserver,
69 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
70 oserver.preStopRegionServer(ctx);
71 }
72 @Override
73 public void postEnvCall(RegionServerEnvironment env) {
74
75 shutdown(env);
76 }
77 });
78 }
79
80 public boolean preMerge(final HRegion regionA, final HRegion regionB) throws IOException {
81 return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
82 @Override
83 public void call(RegionServerObserver oserver,
84 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
85 oserver.preMerge(ctx, regionA, regionB);
86 }
87 });
88 }
89
90 public void postMerge(final HRegion regionA, final HRegion regionB, final HRegion mergedRegion)
91 throws IOException {
92 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
93 @Override
94 public void call(RegionServerObserver oserver,
95 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
96 oserver.postMerge(ctx, regionA, regionB, mergedRegion);
97 }
98 });
99 }
100
101 public boolean preMergeCommit(final HRegion regionA, final HRegion regionB,
102 final @MetaMutationAnnotation List<Mutation> metaEntries) throws IOException {
103 return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
104 @Override
105 public void call(RegionServerObserver oserver,
106 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
107 oserver.preMergeCommit(ctx, regionA, regionB, metaEntries);
108 }
109 });
110 }
111
112 public void postMergeCommit(final HRegion regionA, final HRegion regionB,
113 final HRegion mergedRegion) throws IOException {
114 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
115 @Override
116 public void call(RegionServerObserver oserver,
117 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
118 oserver.postMergeCommit(ctx, regionA, regionB, mergedRegion);
119 }
120 });
121 }
122
123 public void preRollBackMerge(final HRegion regionA, final HRegion regionB) throws IOException {
124 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
125 @Override
126 public void call(RegionServerObserver oserver,
127 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
128 oserver.preRollBackMerge(ctx, regionA, regionB);
129 }
130 });
131 }
132
133 public void postRollBackMerge(final HRegion regionA, final HRegion regionB) throws IOException {
134 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
135 @Override
136 public void call(RegionServerObserver oserver,
137 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
138 oserver.postRollBackMerge(ctx, regionA, regionB);
139 }
140 });
141 }
142
143 public void preRollWALWriterRequest() throws IOException {
144 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
145 @Override
146 public void call(RegionServerObserver oserver,
147 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
148 oserver.preRollWALWriterRequest(ctx);
149 }
150 });
151 }
152
153 public void postRollWALWriterRequest() throws IOException {
154 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
155 @Override
156 public void call(RegionServerObserver oserver,
157 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
158 oserver.postRollWALWriterRequest(ctx);
159 }
160 });
161 }
162
163 public void preReplicateLogEntries(final List<WALEntry> entries, final CellScanner cells)
164 throws IOException {
165 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
166 @Override
167 public void call(RegionServerObserver oserver,
168 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
169 oserver.preReplicateLogEntries(ctx, entries, cells);
170 }
171 });
172 }
173
174 public void postReplicateLogEntries(final List<WALEntry> entries, final CellScanner cells)
175 throws IOException {
176 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
177 @Override
178 public void call(RegionServerObserver oserver,
179 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
180 oserver.postReplicateLogEntries(ctx, entries, cells);
181 }
182 });
183 }
184
185 public ReplicationEndpoint postCreateReplicationEndPoint(final ReplicationEndpoint endpoint)
186 throws IOException {
187 return execOperationWithResult(endpoint, coprocessors.isEmpty() ? null
188 : new CoprocessOperationWithResult<ReplicationEndpoint>() {
189 @Override
190 public void call(RegionServerObserver oserver,
191 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
192 try {
193 oserver.getClass().getDeclaredMethod("postCreateReplicationEndPoint",
194 ObserverContext.class, ReplicationEndpoint.class);
195 } catch (NoSuchMethodException e) {
196 LOG.warn("The RegionServer Observer class "
197 + oserver.getClass().getName()
198 + " does not have the"
199 + "method postCreateReplicationEndPoint(). Consider upgrading inorder to replicate visibility"
200 + " labels as strings");
201 setResult(endpoint);
202 return;
203 } catch (SecurityException e) {
204 LOG.warn("The RegionServer Observer class "
205 + oserver.getClass().getName()
206 + " does not have the"
207 + "method postCreateReplicationEndPoint(). Consider upgrading inorder to replicate visibility"
208 + " labels as strings");
209 setResult(endpoint);
210 return;
211 }
212 setResult(oserver.postCreateReplicationEndPoint(ctx, getResult()));
213 }
214 });
215 }
216
217 private <T> T execOperationWithResult(final T defaultValue,
218 final CoprocessOperationWithResult<T> ctx) throws IOException {
219 if (ctx == null)
220 return defaultValue;
221 ctx.setResult(defaultValue);
222 execOperation(ctx);
223 return ctx.getResult();
224 }
225
226 private static abstract class CoprocessorOperation extends
227 ObserverContext<RegionServerCoprocessorEnvironment> {
228 public CoprocessorOperation() {
229 }
230
231 public abstract void call(RegionServerObserver oserver,
232 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException;
233
234 public void postEnvCall(RegionServerEnvironment env) {
235 }
236 }
237
238 private static abstract class CoprocessOperationWithResult<T> extends CoprocessorOperation {
239 private T result = null;
240
241 public void setResult(final T result) {
242 this.result = result;
243 }
244
245 public T getResult() {
246 return this.result;
247 }
248 }
249
250 private boolean execOperation(final CoprocessorOperation ctx) throws IOException {
251 if (ctx == null) return false;
252
253 boolean bypass = false;
254 for (RegionServerEnvironment env: coprocessors) {
255 if (env.getInstance() instanceof RegionServerObserver) {
256 ctx.prepare(env);
257 Thread currentThread = Thread.currentThread();
258 ClassLoader cl = currentThread.getContextClassLoader();
259 try {
260 currentThread.setContextClassLoader(env.getClassLoader());
261 ctx.call((RegionServerObserver)env.getInstance(), ctx);
262 } catch (Throwable e) {
263 handleCoprocessorThrowable(env, e);
264 } finally {
265 currentThread.setContextClassLoader(cl);
266 }
267 bypass |= ctx.shouldBypass();
268 if (ctx.shouldComplete()) {
269 break;
270 }
271 }
272 ctx.postEnvCall(env);
273 }
274 return bypass;
275 }
276
277
278
279
280
281 static class RegionServerEnvironment extends CoprocessorHost.Environment
282 implements RegionServerCoprocessorEnvironment {
283
284 private RegionServerServices regionServerServices;
285
286 public RegionServerEnvironment(final Class<?> implClass,
287 final Coprocessor impl, final int priority, final int seq,
288 final Configuration conf, final RegionServerServices services) {
289 super(impl, priority, seq, conf);
290 this.regionServerServices = services;
291 for (Class c : implClass.getInterfaces()) {
292 if (SingletonCoprocessorService.class.isAssignableFrom(c)) {
293 this.regionServerServices.registerService(((SingletonCoprocessorService) impl).getService());
294 break;
295 }
296 }
297 }
298
299 @Override
300 public RegionServerServices getRegionServerServices() {
301 return regionServerServices;
302 }
303 }
304
305
306
307
308
309 static class EnvironmentPriorityComparator implements
310 Comparator<CoprocessorEnvironment> {
311 public int compare(final CoprocessorEnvironment env1,
312 final CoprocessorEnvironment env2) {
313 if (env1.getPriority() < env2.getPriority()) {
314 return -1;
315 } else if (env1.getPriority() > env2.getPriority()) {
316 return 1;
317 }
318 if (env1.getLoadSequence() < env2.getLoadSequence()) {
319 return -1;
320 } else if (env1.getLoadSequence() > env2.getLoadSequence()) {
321 return 1;
322 }
323 return 0;
324 }
325 }
326 }