View Javadoc

1   
2   /*
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
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.hbase.Coprocessor;
27  import org.apache.hadoop.hbase.HRegionInfo;
28  import org.apache.hadoop.hbase.coprocessor.*;
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  import org.apache.hadoop.conf.Configuration;
31  
32  /**
33   * Implements the coprocessor environment and runtime support for coprocessors
34   * loaded within a {@link FSHLog}.
35   */
36  @InterfaceAudience.Private
37  public class WALCoprocessorHost
38      extends CoprocessorHost<WALCoprocessorHost.WALEnvironment> {
39    
40    /**
41     * Encapsulation of the environment of each coprocessor
42     */
43    static class WALEnvironment extends CoprocessorHost.Environment
44      implements WALCoprocessorEnvironment {
45  
46      private FSHLog wal;
47  
48      @Override
49      public FSHLog getWAL() {
50        return wal;
51      }
52  
53      /**
54       * Constructor
55       * @param implClass - not used
56       * @param impl the coprocessor instance
57       * @param priority chaining priority
58       * @param seq load sequence
59       * @param conf configuration
60       * @param hlog HLog
61       */
62      public WALEnvironment(Class<?> implClass, final Coprocessor impl,
63          final int priority, final int seq, final Configuration conf,
64          final FSHLog hlog) {
65        super(impl, priority, seq, conf);
66        this.wal = hlog;
67      }
68    }
69  
70    FSHLog wal;
71    /**
72     * Constructor
73     * @param log the write ahead log
74     * @param conf the configuration
75     */
76    public WALCoprocessorHost(final FSHLog log, final Configuration conf) {
77      // We don't want to require an Abortable passed down through (FS)HLog, so
78      // this means that a failure to load of a WAL coprocessor won't abort the
79      // server. This isn't ideal, and means that security components that
80      // utilize a WALObserver will have to check the observer initialization
81      // state manually. However, WALObservers will eventually go away so it
82      // should be an acceptable state of affairs.
83      super(null);
84      this.wal = log;
85      // load system default cp's from configuration.
86      loadSystemCoprocessors(conf, WAL_COPROCESSOR_CONF_KEY);
87    }
88  
89    @Override
90    public WALEnvironment createEnvironment(final Class<?> implClass,
91        final Coprocessor instance, final int priority, final int seq,
92        final Configuration conf) {
93      return new WALEnvironment(implClass, instance, priority, seq, conf,
94          this.wal);
95    }
96  
97    /**
98     * @param info
99     * @param logKey
100    * @param logEdit
101    * @return true if default behavior should be bypassed, false otherwise
102    * @throws IOException
103    */
104   public boolean preWALWrite(final HRegionInfo info, final HLogKey logKey, final WALEdit logEdit)
105       throws IOException {
106     boolean bypass = false;
107     ObserverContext<WALCoprocessorEnvironment> ctx = null;
108     List<WALEnvironment> envs = coprocessors.get();
109     for (int i = 0; i < envs.size(); i++) {
110       WALEnvironment env = envs.get(i);
111       if (env.getInstance() instanceof
112           org.apache.hadoop.hbase.coprocessor.WALObserver) {
113         ctx = ObserverContext.createAndPrepare(env, ctx);
114         Thread currentThread = Thread.currentThread();
115         ClassLoader cl = currentThread.getContextClassLoader();
116         try {
117           currentThread.setContextClassLoader(env.getClassLoader());
118           ((org.apache.hadoop.hbase.coprocessor.WALObserver)env.getInstance()).
119             preWALWrite(ctx, info, logKey, logEdit);
120         } catch (Throwable e) {
121           handleCoprocessorThrowable(env, e);
122         } finally {
123           currentThread.setContextClassLoader(cl);
124         }
125         bypass |= ctx.shouldBypass();
126         if (ctx.shouldComplete()) {
127           break;
128         }
129       }
130     }
131     return bypass;
132   }
133 
134   /**
135    * @param info
136    * @param logKey
137    * @param logEdit
138    * @throws IOException
139    */
140   public void postWALWrite(final HRegionInfo info, final HLogKey logKey, final WALEdit logEdit)
141       throws IOException {
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
147           org.apache.hadoop.hbase.coprocessor.WALObserver) {
148         ctx = ObserverContext.createAndPrepare(env, ctx);
149         Thread currentThread = Thread.currentThread();
150         ClassLoader cl = currentThread.getContextClassLoader();
151         try {
152           currentThread.setContextClassLoader(env.getClassLoader());
153           ((org.apache.hadoop.hbase.coprocessor.WALObserver)env.getInstance()).
154             postWALWrite(ctx, info, logKey, logEdit);
155         } catch (Throwable e) {
156           handleCoprocessorThrowable(env, e);
157         } finally {
158           currentThread.setContextClassLoader(cl);
159         }
160         if (ctx.shouldComplete()) {
161           break;
162         }
163       }
164     }
165   }
166 }