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.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.classification.InterfaceStability;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.hbase.Coprocessor;
29 import org.apache.hadoop.hbase.CoprocessorEnvironment;
30 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
31 import org.apache.hadoop.hbase.MetaMutationAnnotation;
32 import org.apache.hadoop.hbase.client.Mutation;
33 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
34 import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
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
40 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
41 @InterfaceStability.Evolving
42 public class RegionServerCoprocessorHost extends
43 CoprocessorHost<RegionServerCoprocessorHost.RegionServerEnvironment> {
44
45 private RegionServerServices rsServices;
46
47 public RegionServerCoprocessorHost(RegionServerServices rsServices,
48 Configuration conf) {
49 super(rsServices);
50 this.rsServices = rsServices;
51 this.conf = conf;
52
53 loadSystemCoprocessors(conf, REGIONSERVER_COPROCESSOR_CONF_KEY);
54 }
55
56 @Override
57 public RegionServerEnvironment createEnvironment(Class<?> implClass,
58 Coprocessor instance, int priority, int sequence, Configuration conf) {
59 return new RegionServerEnvironment(implClass, instance, priority,
60 sequence, conf, this.rsServices);
61 }
62
63 public void preStop(String message) throws IOException {
64 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
65 @Override
66 public void call(RegionServerObserver oserver,
67 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
68 oserver.preStopRegionServer(ctx);
69 }
70 @Override
71 public void postEnvCall(RegionServerEnvironment env) {
72
73 shutdown(env);
74 }
75 });
76 }
77
78 public boolean preMerge(final HRegion regionA, final HRegion regionB) throws IOException {
79 return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
80 @Override
81 public void call(RegionServerObserver oserver,
82 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
83 oserver.preMerge(ctx, regionA, regionB);
84 }
85 });
86 }
87
88 public void postMerge(final HRegion regionA, final HRegion regionB, final HRegion mergedRegion)
89 throws IOException {
90 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
91 @Override
92 public void call(RegionServerObserver oserver,
93 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
94 oserver.postMerge(ctx, regionA, regionB, mergedRegion);
95 }
96 });
97 }
98
99 public boolean preMergeCommit(final HRegion regionA, final HRegion regionB,
100 final @MetaMutationAnnotation List<Mutation> metaEntries) throws IOException {
101 return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
102 @Override
103 public void call(RegionServerObserver oserver,
104 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
105 oserver.preMergeCommit(ctx, regionA, regionB, metaEntries);
106 }
107 });
108 }
109
110 public void postMergeCommit(final HRegion regionA, final HRegion regionB,
111 final HRegion mergedRegion) throws IOException {
112 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
113 @Override
114 public void call(RegionServerObserver oserver,
115 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
116 oserver.postMergeCommit(ctx, regionA, regionB, mergedRegion);
117 }
118 });
119 }
120
121 public void preRollBackMerge(final HRegion regionA, final HRegion regionB) throws IOException {
122 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
123 @Override
124 public void call(RegionServerObserver oserver,
125 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
126 oserver.preRollBackMerge(ctx, regionA, regionB);
127 }
128 });
129 }
130
131 public void postRollBackMerge(final HRegion regionA, final HRegion regionB) throws IOException {
132 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
133 @Override
134 public void call(RegionServerObserver oserver,
135 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
136 oserver.postRollBackMerge(ctx, regionA, regionB);
137 }
138 });
139 }
140
141 public void preRollWALWriterRequest() throws IOException {
142 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
143 @Override
144 public void call(RegionServerObserver oserver,
145 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
146 oserver.preRollWALWriterRequest(ctx);
147 }
148 });
149 }
150
151 public void postRollWALWriterRequest() throws IOException {
152 execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
153 @Override
154 public void call(RegionServerObserver oserver,
155 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException {
156 oserver.postRollWALWriterRequest(ctx);
157 }
158 });
159 }
160
161 private static abstract class CoprocessorOperation
162 extends ObserverContext<RegionServerCoprocessorEnvironment> {
163 public CoprocessorOperation() {
164 }
165
166 public abstract void call(RegionServerObserver oserver,
167 ObserverContext<RegionServerCoprocessorEnvironment> ctx) throws IOException;
168
169 public void postEnvCall(RegionServerEnvironment env) {
170 }
171 }
172
173 private boolean execOperation(final CoprocessorOperation ctx) throws IOException {
174 if (ctx == null) return false;
175
176 boolean bypass = false;
177 for (RegionServerEnvironment env: coprocessors) {
178 if (env.getInstance() instanceof RegionServerObserver) {
179 ctx.prepare(env);
180 Thread currentThread = Thread.currentThread();
181 ClassLoader cl = currentThread.getContextClassLoader();
182 try {
183 currentThread.setContextClassLoader(env.getClassLoader());
184 ctx.call((RegionServerObserver)env.getInstance(), ctx);
185 } catch (Throwable e) {
186 handleCoprocessorThrowable(env, e);
187 } finally {
188 currentThread.setContextClassLoader(cl);
189 }
190 bypass |= ctx.shouldBypass();
191 if (ctx.shouldComplete()) {
192 break;
193 }
194 }
195 ctx.postEnvCall(env);
196 }
197 return bypass;
198 }
199
200
201
202
203
204 static class RegionServerEnvironment extends CoprocessorHost.Environment
205 implements RegionServerCoprocessorEnvironment {
206
207 private RegionServerServices regionServerServices;
208
209 public RegionServerEnvironment(final Class<?> implClass,
210 final Coprocessor impl, final int priority, final int seq,
211 final Configuration conf, final RegionServerServices services) {
212 super(impl, priority, seq, conf);
213 this.regionServerServices = services;
214 for (Class c : implClass.getInterfaces()) {
215 if (SingletonCoprocessorService.class.isAssignableFrom(c)) {
216 this.regionServerServices.registerService(((SingletonCoprocessorService) impl).getService());
217 break;
218 }
219 }
220 }
221
222 @Override
223 public RegionServerServices getRegionServerServices() {
224 return regionServerServices;
225 }
226 }
227
228
229
230
231
232 static class EnvironmentPriorityComparator implements
233 Comparator<CoprocessorEnvironment> {
234 public int compare(final CoprocessorEnvironment env1,
235 final CoprocessorEnvironment env2) {
236 if (env1.getPriority() < env2.getPriority()) {
237 return -1;
238 } else if (env1.getPriority() > env2.getPriority()) {
239 return 1;
240 }
241 if (env1.getLoadSequence() < env2.getLoadSequence()) {
242 return -1;
243 } else if (env1.getLoadSequence() > env2.getLoadSequence()) {
244 return 1;
245 }
246 return 0;
247 }
248 }
249 }