1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.regionserver.wal;
22
23 import java.io.IOException;
24 import java.util.List;
25
26 import org.apache.hadoop.fs.Path;
27 import org.apache.hadoop.hbase.Coprocessor;
28 import org.apache.hadoop.hbase.HRegionInfo;
29 import org.apache.hadoop.hbase.coprocessor.*;
30 import org.apache.hadoop.hbase.classification.InterfaceAudience;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
33 import org.apache.hadoop.hbase.coprocessor.MetricsCoprocessor;
34 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
35 import org.apache.hadoop.hbase.coprocessor.WALCoprocessorEnvironment;
36 import org.apache.hadoop.hbase.coprocessor.WALObserver;
37 import org.apache.hadoop.hbase.metrics.MetricRegistry;
38 import org.apache.hadoop.hbase.wal.WAL;
39 import org.apache.hadoop.hbase.wal.WALKey;
40
41
42
43
44
45 @InterfaceAudience.Private
46 public class WALCoprocessorHost
47 extends CoprocessorHost<WALCoprocessorHost.WALEnvironment> {
48
49
50
51
52 static class WALEnvironment extends CoprocessorHost.Environment
53 implements WALCoprocessorEnvironment {
54
55 private final WAL wal;
56
57 final boolean useLegacyPre;
58 final boolean useLegacyPost;
59 private final MetricRegistry metricRegistry;
60
61 @Override
62 public WAL getWAL() {
63 return wal;
64 }
65
66
67
68
69
70
71
72
73
74
75 public WALEnvironment(Class<?> implClass, final Coprocessor impl,
76 final int priority, final int seq, final Configuration conf,
77 final WAL wal) {
78 super(impl, priority, seq, conf);
79 this.wal = wal;
80
81
82
83
84 useLegacyPre = useLegacyMethod(impl.getClass(), "preWALWrite", ObserverContext.class,
85 HRegionInfo.class, WALKey.class, WALEdit.class);
86 useLegacyPost = useLegacyMethod(impl.getClass(), "postWALWrite", ObserverContext.class,
87 HRegionInfo.class, WALKey.class, WALEdit.class);
88 this.metricRegistry = MetricsCoprocessor.createRegistryForWALCoprocessor(implClass.getName());
89 }
90
91 @Override
92 public MetricRegistry getMetricRegistryForRegionServer() {
93 return metricRegistry;
94 }
95
96 @Override
97 protected void shutdown() {
98 super.shutdown();
99 MetricsCoprocessor.removeRegistry(this.metricRegistry);
100 }
101 }
102
103 private final WAL wal;
104
105
106
107
108
109
110 public WALCoprocessorHost(final WAL log, final Configuration conf) {
111
112
113
114
115
116
117 super(null);
118 this.wal = log;
119
120 loadSystemCoprocessors(conf, WAL_COPROCESSOR_CONF_KEY);
121 }
122
123 @Override
124 public WALEnvironment createEnvironment(final Class<?> implClass,
125 final Coprocessor instance, final int priority, final int seq,
126 final Configuration conf) {
127 return new WALEnvironment(implClass, instance, priority, seq, conf,
128 this.wal);
129 }
130
131
132
133
134
135
136
137
138 public boolean preWALWrite(final HRegionInfo info, final WALKey logKey, final WALEdit logEdit)
139 throws IOException {
140 boolean bypass = false;
141 if (this.coprocessors == null || this.coprocessors.isEmpty()) return bypass;
142 ObserverContext<WALCoprocessorEnvironment> ctx = null;
143 List<WALEnvironment> envs = coprocessors.get();
144 for (int i = 0; i < envs.size(); i++) {
145 WALEnvironment env = envs.get(i);
146 if (env.getInstance() instanceof WALObserver) {
147 final WALObserver observer = (WALObserver)env.getInstance();
148 ctx = ObserverContext.createAndPrepare(env, ctx);
149 Thread currentThread = Thread.currentThread();
150 ClassLoader cl = currentThread.getContextClassLoader();
151 try {
152 currentThread.setContextClassLoader(env.getClassLoader());
153 if (env.useLegacyPre) {
154 if (logKey instanceof HLogKey) {
155 observer.preWALWrite(ctx, info, (HLogKey)logKey, logEdit);
156 } else {
157 legacyWarning(observer.getClass(),
158 "There are wal keys present that are not HLogKey.");
159 }
160 } else {
161 observer.preWALWrite(ctx, info, logKey, logEdit);
162 }
163 } catch (Throwable e) {
164 handleCoprocessorThrowable(env, e);
165 } finally {
166 currentThread.setContextClassLoader(cl);
167 }
168 bypass |= ctx.shouldBypass();
169 if (ctx.shouldComplete()) {
170 break;
171 }
172 }
173 }
174 return bypass;
175 }
176
177
178
179
180
181
182
183 public void postWALWrite(final HRegionInfo info, final WALKey logKey, final WALEdit logEdit)
184 throws IOException {
185 if (this.coprocessors == null || this.coprocessors.isEmpty()) return;
186 ObserverContext<WALCoprocessorEnvironment> ctx = null;
187 List<WALEnvironment> envs = coprocessors.get();
188 for (int i = 0; i < envs.size(); i++) {
189 WALEnvironment env = envs.get(i);
190 if (env.getInstance() instanceof WALObserver) {
191 final WALObserver observer = (WALObserver)env.getInstance();
192 ctx = ObserverContext.createAndPrepare(env, ctx);
193 Thread currentThread = Thread.currentThread();
194 ClassLoader cl = currentThread.getContextClassLoader();
195 try {
196 currentThread.setContextClassLoader(env.getClassLoader());
197 if (env.useLegacyPost) {
198 if (logKey instanceof HLogKey) {
199 observer.postWALWrite(ctx, info, (HLogKey)logKey, logEdit);
200 } else {
201 legacyWarning(observer.getClass(),
202 "There are wal keys present that are not HLogKey.");
203 }
204 } else {
205 observer.postWALWrite(ctx, info, logKey, logEdit);
206 }
207 } catch (Throwable e) {
208 handleCoprocessorThrowable(env, e);
209 } finally {
210 currentThread.setContextClassLoader(cl);
211 }
212 if (ctx.shouldComplete()) {
213 break;
214 }
215 }
216 }
217 }
218
219
220
221
222
223
224 public void preWALRoll(Path oldPath, Path newPath) throws IOException {
225 if (this.coprocessors == null || this.coprocessors.isEmpty()) return;
226 ObserverContext<WALCoprocessorEnvironment> ctx = null;
227 List<WALEnvironment> envs = coprocessors.get();
228 for (int i = 0; i < envs.size(); i++) {
229 WALEnvironment env = envs.get(i);
230 if (env.getInstance() instanceof WALObserver) {
231 final WALObserver observer = (WALObserver)env.getInstance();
232 ctx = ObserverContext.createAndPrepare(env, ctx);
233 Thread currentThread = Thread.currentThread();
234 ClassLoader cl = currentThread.getContextClassLoader();
235 try {
236 currentThread.setContextClassLoader(env.getClassLoader());
237 observer.preWALRoll(ctx, oldPath, newPath);
238 } catch (Throwable e) {
239 handleCoprocessorThrowable(env, e);
240 } finally {
241 currentThread.setContextClassLoader(cl);
242 }
243 if (ctx.shouldComplete()) {
244 break;
245 }
246 }
247 }
248 }
249
250
251
252
253
254
255 public void postWALRoll(Path oldPath, Path newPath) throws IOException {
256 if (this.coprocessors == null || this.coprocessors.isEmpty()) return;
257 ObserverContext<WALCoprocessorEnvironment> ctx = null;
258 List<WALEnvironment> envs = coprocessors.get();
259 for (int i = 0; i < envs.size(); i++) {
260 WALEnvironment env = envs.get(i);
261 if (env.getInstance() instanceof WALObserver) {
262 final WALObserver observer = (WALObserver)env.getInstance();
263 ctx = ObserverContext.createAndPrepare(env, ctx);
264 Thread currentThread = Thread.currentThread();
265 ClassLoader cl = currentThread.getContextClassLoader();
266 try {
267 currentThread.setContextClassLoader(env.getClassLoader());
268 observer.postWALRoll(ctx, oldPath, newPath);
269 } catch (Throwable e) {
270 handleCoprocessorThrowable(env, e);
271 } finally {
272 currentThread.setContextClassLoader(cl);
273 }
274 if (ctx.shouldComplete()) {
275 break;
276 }
277 }
278 }
279 }
280 }