hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a...@apache.org
Subject [6/7] hbase git commit: HBASE-17732 Coprocessor Design Improvements
Date Wed, 27 Sep 2017 19:45:37 GMT
http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java
----------------------------------------------------------------------
diff --git a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java
index f3040af..025bb24 100644
--- a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java
+++ b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java
@@ -161,7 +161,7 @@ public class TestRSGroupsOfflineMode {
 
     // Get groupInfoManager from the new active master.
     RSGroupInfoManager groupMgr = ((MiniHBaseCluster)cluster).getMaster().getMasterCoprocessorHost()
-            .findCoprocessors(RSGroupAdminEndpoint.class).get(0).getGroupInfoManager();
+            .findCoprocessor(RSGroupAdminEndpoint.class).getGroupInfoManager();
     // Make sure balancer is in offline mode, since this is what we're testing.
     assertFalse(groupMgr.isOnline());
     // Verify the group affiliation that's loaded from ZK instead of tables.

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/JMXListener.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/JMXListener.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/JMXListener.java
index 788d25b..1472057 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/JMXListener.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/JMXListener.java
@@ -18,6 +18,7 @@
  */
 package org.apache.hadoop.hbase;
 
+import com.google.protobuf.Service;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
@@ -32,6 +33,7 @@ import java.rmi.server.RMIClientSocketFactory;
 import java.rmi.server.RMIServerSocketFactory;
 import java.rmi.server.UnicastRemoteObject;
 import java.util.HashMap;
+import java.util.Optional;
 
 import javax.management.MBeanServer;
 import javax.management.remote.JMXConnectorServer;
@@ -46,8 +48,7 @@ import javax.management.remote.rmi.RMIConnectorServer;
  * 2)support password authentication
  * 3)support subset of SSL (with default configuration)
  */
-public class JMXListener implements Coprocessor {
-
+public class JMXListener implements MasterCoprocessor, RegionServerCoprocessor {
   private static final Log LOG = LogFactory.getLog(JMXListener.class);
   public static final String RMI_REGISTRY_PORT_CONF_KEY = ".rmi.registry.port";
   public static final String RMI_CONNECTOR_PORT_CONF_KEY = ".rmi.connector.port";

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/client/HTableWrapper.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/HTableWrapper.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/HTableWrapper.java
index a7ccb18..ef09b5b 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/HTableWrapper.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/HTableWrapper.java
@@ -38,7 +38,7 @@ import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.yetus.audience.InterfaceStability;
 import org.apache.hadoop.hbase.client.coprocessor.Batch;
 import org.apache.hadoop.hbase.client.coprocessor.Batch.Callback;
-import org.apache.hadoop.hbase.coprocessor.CoprocessorHost.Environment;
+import org.apache.hadoop.hbase.coprocessor.BaseEnvironment;
 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
 import org.apache.hadoop.io.MultipleIOException;
@@ -70,7 +70,7 @@ public final class HTableWrapper implements Table {
    * @throws IOException
    */
   public static Table createWrapper(List<Table> openTables,
-      TableName tableName, Environment env, ExecutorService pool) throws IOException {
+      TableName tableName, BaseEnvironment env, ExecutorService pool) throws IOException {
     return new HTableWrapper(openTables, tableName,
         CoprocessorHConnection.getConnectionForEnvironment(env), pool);
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/constraint/ConstraintProcessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/constraint/ConstraintProcessor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/constraint/ConstraintProcessor.java
index f01034c..582fabf 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/constraint/ConstraintProcessor.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/constraint/ConstraintProcessor.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.constraint;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -30,6 +31,7 @@ import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.Durability;
 import org.apache.hadoop.hbase.client.TableDescriptor;
 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
+import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor;
 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
 import org.apache.hadoop.hbase.coprocessor.RegionObserver;
 import org.apache.hadoop.hbase.regionserver.InternalScanner;
@@ -42,7 +44,7 @@ import org.apache.hadoop.hbase.wal.WALEdit;
  * implemented on any given system by a coprocessor.
  */
 @InterfaceAudience.Private
-public class ConstraintProcessor implements RegionObserver {
+public class ConstraintProcessor implements RegionCoprocessor, RegionObserver {
 
   private static final Log LOG = LogFactory.getLog(ConstraintProcessor.class);
 
@@ -50,6 +52,11 @@ public class ConstraintProcessor implements RegionObserver {
 
   private List<? extends Constraint> constraints = new ArrayList<>();
 
+  @Override
+  public Optional<RegionObserver> getRegionObserver() {
+    return Optional.of(this);
+  }
+
   /**
    * Create the constraint processor.
    * <p>

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseEnvironment.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseEnvironment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseEnvironment.java
new file mode 100644
index 0000000..a491d60
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseEnvironment.java
@@ -0,0 +1,187 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.coprocessor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.Coprocessor;
+import org.apache.hadoop.hbase.CoprocessorEnvironment;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.HTableWrapper;
+import org.apache.hadoop.hbase.client.Table;
+import org.apache.hadoop.hbase.util.VersionInfo;
+import org.apache.yetus.audience.InterfaceAudience;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Encapsulation of the environment of each coprocessor
+ */
+@InterfaceAudience.Private
+public class BaseEnvironment<C extends Coprocessor> implements CoprocessorEnvironment<C> {
+  private static final Log LOG = LogFactory.getLog(BaseEnvironment.class);
+
+  /** The coprocessor */
+  public C impl;
+  /** Chaining priority */
+  protected int priority = Coprocessor.PRIORITY_USER;
+  /** Current coprocessor state */
+  Coprocessor.State state = Coprocessor.State.UNINSTALLED;
+  /** Accounting for tables opened by the coprocessor */
+  protected List<Table> openTables =
+    Collections.synchronizedList(new ArrayList<Table>());
+  private int seq;
+  private Configuration conf;
+  private ClassLoader classLoader;
+
+  /**
+   * Constructor
+   * @param impl the coprocessor instance
+   * @param priority chaining priority
+   */
+  public BaseEnvironment(final C impl, final int priority,
+      final int seq, final Configuration conf) {
+    this.impl = impl;
+    this.classLoader = impl.getClass().getClassLoader();
+    this.priority = priority;
+    this.state = Coprocessor.State.INSTALLED;
+    this.seq = seq;
+    this.conf = conf;
+  }
+
+  /** Initialize the environment */
+  @Override
+  public void startup() throws IOException {
+    if (state == Coprocessor.State.INSTALLED ||
+        state == Coprocessor.State.STOPPED) {
+      state = Coprocessor.State.STARTING;
+      Thread currentThread = Thread.currentThread();
+      ClassLoader hostClassLoader = currentThread.getContextClassLoader();
+      try {
+        currentThread.setContextClassLoader(this.getClassLoader());
+        impl.start(this);
+        state = Coprocessor.State.ACTIVE;
+      } finally {
+        currentThread.setContextClassLoader(hostClassLoader);
+      }
+    } else {
+      LOG.warn("Not starting coprocessor " + impl.getClass().getName() +
+          " because not inactive (state=" + state.toString() + ")");
+    }
+  }
+
+  /** Clean up the environment */
+  @Override
+  public void shutdown() {
+    if (state == Coprocessor.State.ACTIVE) {
+      state = Coprocessor.State.STOPPING;
+      Thread currentThread = Thread.currentThread();
+      ClassLoader hostClassLoader = currentThread.getContextClassLoader();
+      try {
+        currentThread.setContextClassLoader(this.getClassLoader());
+        impl.stop(this);
+        state = Coprocessor.State.STOPPED;
+      } catch (IOException ioe) {
+        LOG.error("Error stopping coprocessor "+impl.getClass().getName(), ioe);
+      } finally {
+        currentThread.setContextClassLoader(hostClassLoader);
+      }
+    } else {
+      LOG.warn("Not stopping coprocessor "+impl.getClass().getName()+
+          " because not active (state="+state.toString()+")");
+    }
+    synchronized (openTables) {
+      // clean up any table references
+      for (Table table: openTables) {
+        try {
+          ((HTableWrapper)table).internalClose();
+        } catch (IOException e) {
+          // nothing can be done here
+          LOG.warn("Failed to close " +
+              table.getName(), e);
+        }
+      }
+    }
+  }
+
+  @Override
+  public C getInstance() {
+    return impl;
+  }
+
+  @Override
+  public ClassLoader getClassLoader() {
+    return classLoader;
+  }
+
+  @Override
+  public int getPriority() {
+    return priority;
+  }
+
+  @Override
+  public int getLoadSequence() {
+    return seq;
+  }
+
+  /** @return the coprocessor environment version */
+  @Override
+  public int getVersion() {
+    return Coprocessor.VERSION;
+  }
+
+  /** @return the HBase release */
+  @Override
+  public String getHBaseVersion() {
+    return VersionInfo.getVersion();
+  }
+
+  @Override
+  public Configuration getConfiguration() {
+    return conf;
+  }
+
+  /**
+   * Open a table from within the Coprocessor environment
+   * @param tableName the table name
+   * @return an interface for manipulating the table
+   * @exception IOException Exception
+   */
+  @Override
+  public Table getTable(TableName tableName) throws IOException {
+    return this.getTable(tableName, null);
+  }
+
+  /**
+   * Open a table from within the Coprocessor environment
+   * @param tableName the table name
+   * @return an interface for manipulating the table
+   * @exception IOException Exception
+   */
+  @Override
+  public Table getTable(TableName tableName, ExecutorService pool) throws IOException {
+    return HTableWrapper.createWrapper(openTables, tableName, this, pool);
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRowProcessorEndpoint.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRowProcessorEndpoint.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRowProcessorEndpoint.java
index 5886715..df3ed23 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRowProcessorEndpoint.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRowProcessorEndpoint.java
@@ -20,11 +20,11 @@ package org.apache.hadoop.hbase.coprocessor;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Optional;
 
 import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.yetus.audience.InterfaceStability;
 import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
-import org.apache.hadoop.hbase.Coprocessor;
 import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
 import org.apache.hadoop.hbase.HConstants;
@@ -46,19 +46,19 @@ import com.google.protobuf.Service;
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public abstract class BaseRowProcessorEndpoint<S extends Message, T extends Message> 
-extends RowProcessorService implements CoprocessorService, Coprocessor {
+public abstract class BaseRowProcessorEndpoint<S extends Message, T extends Message>
+extends RowProcessorService implements RegionCoprocessor {
   private RegionCoprocessorEnvironment env;
   /**
    * Pass a processor to region to process multiple rows atomically.
-   * 
+   *
    * The RowProcessor implementations should be the inner classes of your
    * RowProcessorEndpoint. This way the RowProcessor can be class-loaded with
    * the Coprocessor endpoint together.
    *
    * See {@code TestRowProcessorEndpoint} for example.
    *
-   * The request contains information for constructing processor 
+   * The request contains information for constructing processor
    * (see {@link #constructRowProcessorFromRequest}. The processor object defines
    * the read-modify-write procedure.
    */
@@ -83,8 +83,8 @@ extends RowProcessorService implements CoprocessorService, Coprocessor {
   }
 
   @Override
-  public Service getService() {
-    return this;
+  public Optional<Service> getService() {
+    return Optional.of(this);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BulkLoadObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BulkLoadObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BulkLoadObserver.java
index e891cc0..25e6522 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BulkLoadObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BulkLoadObserver.java
@@ -49,7 +49,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CleanupBul
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface BulkLoadObserver extends Coprocessor {
+public interface BulkLoadObserver {
     /**
       * Called as part of SecureBulkLoadEndpoint.prepareBulkLoad() RPC call.
       * It can't bypass the default action, e.g., ctx.bypass() won't have effect.

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
index 27ac33a..da07c40 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
@@ -25,12 +25,13 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentSkipListSet;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -44,22 +45,22 @@ import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.DoNotRetryIOException;
 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
 import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.client.HTableWrapper;
-import org.apache.hadoop.hbase.client.Table;
+import org.apache.hadoop.hbase.ipc.RpcServer;
+import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.shaded.com.google.common.annotations.VisibleForTesting;
 import org.apache.hadoop.hbase.util.CoprocessorClassLoader;
 import org.apache.hadoop.hbase.util.SortedList;
-import org.apache.hadoop.hbase.util.VersionInfo;
 
 /**
  * Provides the common setup framework and runtime services for coprocessor
  * invocation from HBase services.
- * @param <E> the specific environment extension that a concrete implementation
+ * @param <C> type of specific coprocessor this host will handle
+ * @param <E> type of specific coprocessor environment this host requires.
  * provides
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
+public abstract class CoprocessorHost<C extends Coprocessor, E extends CoprocessorEnvironment<C>> {
   public static final String REGION_COPROCESSOR_CONF_KEY =
       "hbase.coprocessor.region.classes";
   public static final String REGIONSERVER_COPROCESSOR_CONF_KEY =
@@ -81,7 +82,8 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
   private static final Log LOG = LogFactory.getLog(CoprocessorHost.class);
   protected Abortable abortable;
   /** Ordered set of loaded coprocessors with lock */
-  protected SortedList<E> coprocessors = new SortedList<>(new EnvironmentPriorityComparator());
+  protected final SortedList<E> coprocEnvironments =
+      new SortedList<>(new EnvironmentPriorityComparator());
   protected Configuration conf;
   // unique file prefix to use for local copies of jars when classloading
   protected String pathPrefix;
@@ -96,7 +98,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
    * Not to be confused with the per-object _coprocessors_ (above),
    * coprocessorNames is static and stores the set of all coprocessors ever
    * loaded by any thread in this JVM. It is strictly additive: coprocessors are
-   * added to coprocessorNames, by loadInstance() but are never removed, since
+   * added to coprocessorNames, by checkAndLoadInstance() but are never removed, since
    * the intention is to preserve a history of all loaded coprocessors for
    * diagnosis in case of server crash (HBASE-4014).
    */
@@ -118,7 +120,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
    */
   public Set<String> getCoprocessors() {
     Set<String> returnValue = new TreeSet<>();
-    for (CoprocessorEnvironment e: coprocessors) {
+    for (E e: coprocEnvironments) {
       returnValue.add(e.getInstance().getClass().getSimpleName());
     }
     return returnValue;
@@ -135,7 +137,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
       return;
     }
 
-    Class<?> implClass = null;
+    Class<?> implClass;
 
     // load default coprocessors from configure file
     String[] defaultCPClasses = conf.getStrings(confKey);
@@ -156,10 +158,13 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
         implClass = cl.loadClass(className);
         // Add coprocessors as we go to guard against case where a coprocessor is specified twice
         // in the configuration
-        this.coprocessors.add(loadInstance(implClass, priority, conf));
-        LOG.info("System coprocessor " + className + " was loaded " +
-            "successfully with priority (" + priority + ").");
-        ++priority;
+        E env = checkAndLoadInstance(implClass, priority, conf);
+        if (env != null) {
+          this.coprocEnvironments.add(env);
+          LOG.info(
+              "System coprocessor " + className + " was loaded " + "successfully with priority (" + priority + ").");
+          ++priority;
+        }
       } catch (Throwable t) {
         // We always abort if system coprocessors cannot be loaded
         abortServer(className, t);
@@ -196,7 +201,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
    */
   public E load(Path path, String className, int priority,
       Configuration conf, String[] includedClassPrefixes) throws IOException {
-    Class<?> implClass = null;
+    Class<?> implClass;
     LOG.debug("Loading coprocessor class " + className + " with path " +
         path + " and priority " + priority);
 
@@ -223,7 +228,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
     try{
       // switch temporarily to the thread classloader for custom CP
       currentThread.setContextClassLoader(cl);
-      E cpInstance = loadInstance(implClass, priority, conf);
+      E cpInstance = checkAndLoadInstance(implClass, priority, conf);
       return cpInstance;
     } finally {
       // restore the fresh (host) classloader
@@ -231,16 +236,11 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
     }
   }
 
-  /**
-   * @param implClass Implementation class
-   * @param priority priority
-   * @param conf configuration
-   * @throws java.io.IOException Exception
-   */
-  public void load(Class<?> implClass, int priority, Configuration conf)
+  @VisibleForTesting
+  public void load(Class<? extends C> implClass, int priority, Configuration conf)
       throws IOException {
-    E env = loadInstance(implClass, priority, conf);
-    coprocessors.add(env);
+    E env = checkAndLoadInstance(implClass, priority, conf);
+    coprocEnvironments.add(env);
   }
 
   /**
@@ -249,29 +249,22 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
    * @param conf configuration
    * @throws java.io.IOException Exception
    */
-  public E loadInstance(Class<?> implClass, int priority, Configuration conf)
+  public E checkAndLoadInstance(Class<?> implClass, int priority, Configuration conf)
       throws IOException {
-    if (!Coprocessor.class.isAssignableFrom(implClass)) {
-      throw new IOException("Configured class " + implClass.getName() + " must implement "
-          + Coprocessor.class.getName() + " interface ");
-    }
-
     // create the instance
-    Coprocessor impl;
-    Object o = null;
+    C impl;
     try {
-      o = implClass.newInstance();
-      impl = (Coprocessor)o;
-    } catch (InstantiationException e) {
-      throw new IOException(e);
-    } catch (IllegalAccessException e) {
+      impl = checkAndGetInstance(implClass);
+      if (impl == null) {
+        LOG.error("Cannot load coprocessor " + implClass.getSimpleName());
+        return null;
+      }
+    } catch (InstantiationException|IllegalAccessException e) {
       throw new IOException(e);
     }
     // create the environment
-    E env = createEnvironment(implClass, impl, priority, loadSequence.incrementAndGet(), conf);
-    if (env instanceof Environment) {
-      ((Environment)env).startup();
-    }
+    E env = createEnvironment(impl, priority, loadSequence.incrementAndGet(), conf);
+    env.startup();
     // HBASE-4014: maintain list of loaded coprocessors for later crash analysis
     // if server (master or regionserver) aborts.
     coprocessorNames.add(implClass.getName());
@@ -281,28 +274,30 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
   /**
    * Called when a new Coprocessor class is loaded
    */
-  public abstract E createEnvironment(Class<?> implClass, Coprocessor instance,
-      int priority, int sequence, Configuration conf);
+  public abstract E createEnvironment(C instance, int priority, int sequence, Configuration conf);
 
-  public void shutdown(CoprocessorEnvironment e) {
-    if (e instanceof Environment) {
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Stop coprocessor " + e.getInstance().getClass().getName());
-      }
-      ((Environment)e).shutdown();
-    } else {
-      LOG.warn("Shutdown called on unknown environment: "+
-          e.getClass().getName());
+  /**
+   * Called when a new Coprocessor class needs to be loaded. Checks if type of the given class
+   * is what the corresponding host implementation expects. If it is of correct type, returns an
+   * instance of the coprocessor to be loaded. If not, returns null.
+   * If an exception occurs when trying to create instance of a coprocessor, it's passed up and
+   * eventually results into server aborting.
+   */
+  public abstract C checkAndGetInstance(Class<?> implClass)
+      throws InstantiationException, IllegalAccessException;
+
+  public void shutdown(E e) {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Stop coprocessor " + e.getInstance().getClass().getName());
     }
+    e.shutdown();
   }
 
   /**
-   * Find a coprocessor implementation by class name
-   * @param className the class name
-   * @return the coprocessor, or null if not found
+   * Find coprocessors by full class name or simple name.
    */
-  public Coprocessor findCoprocessor(String className) {
-    for (E env: coprocessors) {
+  public C findCoprocessor(String className) {
+    for (E env: coprocEnvironments) {
       if (env.getInstance().getClass().getName().equals(className) ||
           env.getInstance().getClass().getSimpleName().equals(className)) {
         return env.getInstance();
@@ -311,40 +306,30 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
     return null;
   }
 
-  /**
-   * Find list of coprocessors that extend/implement the given class/interface
-   * @param cls the class/interface to look for
-   * @return the list of coprocessors, or null if not found
-   */
-  public <T extends Coprocessor> List<T> findCoprocessors(Class<T> cls) {
-    ArrayList<T> ret = new ArrayList<>();
-
-    for (E env: coprocessors) {
-      Coprocessor cp = env.getInstance();
-
-      if(cp != null) {
-        if (cls.isAssignableFrom(cp.getClass())) {
-          ret.add((T)cp);
-        }
+  @VisibleForTesting
+  public <T extends C> T findCoprocessor(Class<T> cls) {
+    for (E env: coprocEnvironments) {
+      if (cls.isAssignableFrom(env.getInstance().getClass())) {
+        return (T) env.getInstance();
       }
     }
-    return ret;
+    return null;
   }
 
   /**
-   * Find list of CoprocessorEnvironment that extend/implement the given class/interface
+   * Find list of coprocessors that extend/implement the given class/interface
    * @param cls the class/interface to look for
-   * @return the list of CoprocessorEnvironment, or null if not found
+   * @return the list of coprocessors, or null if not found
    */
-  public List<CoprocessorEnvironment> findCoprocessorEnvironment(Class<?> cls) {
-    ArrayList<CoprocessorEnvironment> ret = new ArrayList<>();
+  public <T extends C> List<T> findCoprocessors(Class<T> cls) {
+    ArrayList<T> ret = new ArrayList<>();
 
-    for (E env: coprocessors) {
-      Coprocessor cp = env.getInstance();
+    for (E env: coprocEnvironments) {
+      C cp = env.getInstance();
 
       if(cp != null) {
         if (cls.isAssignableFrom(cp.getClass())) {
-          ret.add(env);
+          ret.add((T)cp);
         }
       }
     }
@@ -356,8 +341,9 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
    * @param className the class name
    * @return the coprocessor, or null if not found
    */
-  public CoprocessorEnvironment findCoprocessorEnvironment(String className) {
-    for (E env: coprocessors) {
+  @VisibleForTesting
+  public E findCoprocessorEnvironment(String className) {
+    for (E env: coprocEnvironments) {
       if (env.getInstance().getClass().getName().equals(className) ||
           env.getInstance().getClass().getSimpleName().equals(className)) {
         return env;
@@ -374,7 +360,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
   Set<ClassLoader> getExternalClassLoaders() {
     Set<ClassLoader> externalClassLoaders = new HashSet<>();
     final ClassLoader systemClassLoader = this.getClass().getClassLoader();
-    for (E env : coprocessors) {
+    for (E env : coprocEnvironments) {
       ClassLoader cl = env.getInstance().getClass().getClassLoader();
       if (cl != systemClassLoader){
         //do not include system classloader
@@ -388,8 +374,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
    * Environment priority comparator.
    * Coprocessors are chained in sorted order.
    */
-  static class EnvironmentPriorityComparator
-      implements Comparator<CoprocessorEnvironment> {
+  static class EnvironmentPriorityComparator implements Comparator<CoprocessorEnvironment> {
     @Override
     public int compare(final CoprocessorEnvironment env1,
         final CoprocessorEnvironment env2) {
@@ -407,153 +392,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
     }
   }
 
-  /**
-   * Encapsulation of the environment of each coprocessor
-   */
-  public static class Environment implements CoprocessorEnvironment {
-
-    /** The coprocessor */
-    public Coprocessor impl;
-    /** Chaining priority */
-    protected int priority = Coprocessor.PRIORITY_USER;
-    /** Current coprocessor state */
-    Coprocessor.State state = Coprocessor.State.UNINSTALLED;
-    /** Accounting for tables opened by the coprocessor */
-    protected List<Table> openTables =
-      Collections.synchronizedList(new ArrayList<Table>());
-    private int seq;
-    private Configuration conf;
-    private ClassLoader classLoader;
-
-    /**
-     * Constructor
-     * @param impl the coprocessor instance
-     * @param priority chaining priority
-     */
-    public Environment(final Coprocessor impl, final int priority,
-        final int seq, final Configuration conf) {
-      this.impl = impl;
-      this.classLoader = impl.getClass().getClassLoader();
-      this.priority = priority;
-      this.state = Coprocessor.State.INSTALLED;
-      this.seq = seq;
-      this.conf = conf;
-    }
-
-    /** Initialize the environment */
-    public void startup() throws IOException {
-      if (state == Coprocessor.State.INSTALLED ||
-          state == Coprocessor.State.STOPPED) {
-        state = Coprocessor.State.STARTING;
-        Thread currentThread = Thread.currentThread();
-        ClassLoader hostClassLoader = currentThread.getContextClassLoader();
-        try {
-          currentThread.setContextClassLoader(this.getClassLoader());
-          impl.start(this);
-          state = Coprocessor.State.ACTIVE;
-        } finally {
-          currentThread.setContextClassLoader(hostClassLoader);
-        }
-      } else {
-        LOG.warn("Not starting coprocessor "+impl.getClass().getName()+
-            " because not inactive (state="+state.toString()+")");
-      }
-    }
-
-    /** Clean up the environment */
-    protected void shutdown() {
-      if (state == Coprocessor.State.ACTIVE) {
-        state = Coprocessor.State.STOPPING;
-        Thread currentThread = Thread.currentThread();
-        ClassLoader hostClassLoader = currentThread.getContextClassLoader();
-        try {
-          currentThread.setContextClassLoader(this.getClassLoader());
-          impl.stop(this);
-          state = Coprocessor.State.STOPPED;
-        } catch (IOException ioe) {
-          LOG.error("Error stopping coprocessor "+impl.getClass().getName(), ioe);
-        } finally {
-          currentThread.setContextClassLoader(hostClassLoader);
-        }
-      } else {
-        LOG.warn("Not stopping coprocessor "+impl.getClass().getName()+
-            " because not active (state="+state.toString()+")");
-      }
-      synchronized (openTables) {
-        // clean up any table references
-        for (Table table: openTables) {
-          try {
-            ((HTableWrapper)table).internalClose();
-          } catch (IOException e) {
-            // nothing can be done here
-            LOG.warn("Failed to close " +
-                table.getName(), e);
-          }
-        }
-      }
-    }
-
-    @Override
-    public Coprocessor getInstance() {
-      return impl;
-    }
-
-    @Override
-    public ClassLoader getClassLoader() {
-      return classLoader;
-    }
-
-    @Override
-    public int getPriority() {
-      return priority;
-    }
-
-    @Override
-    public int getLoadSequence() {
-      return seq;
-    }
-
-    /** @return the coprocessor environment version */
-    @Override
-    public int getVersion() {
-      return Coprocessor.VERSION;
-    }
-
-    /** @return the HBase release */
-    @Override
-    public String getHBaseVersion() {
-      return VersionInfo.getVersion();
-    }
-
-    @Override
-    public Configuration getConfiguration() {
-      return conf;
-    }
-
-    /**
-     * Open a table from within the Coprocessor environment
-     * @param tableName the table name
-     * @return an interface for manipulating the table
-     * @exception java.io.IOException Exception
-     */
-    @Override
-    public Table getTable(TableName tableName) throws IOException {
-      return this.getTable(tableName, null);
-    }
-
-    /**
-     * Open a table from within the Coprocessor environment
-     * @param tableName the table name
-     * @return an interface for manipulating the table
-     * @exception java.io.IOException Exception
-     */
-    @Override
-    public Table getTable(TableName tableName, ExecutorService pool) throws IOException {
-      return HTableWrapper.createWrapper(openTables, tableName, this, pool);
-    }
-  }
-
-  protected void abortServer(final CoprocessorEnvironment environment, final Throwable e) {
+  protected void abortServer(final E environment, final Throwable e) {
     abortServer(environment.getInstance().getClass().getName(), e);
   }
 
@@ -586,8 +425,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
   // etc) mention this nuance of our exception handling so that coprocessor can throw appropriate
   // exceptions depending on situation. If any changes are made to this logic, make sure to
   // update all classes' comments.
-  protected void handleCoprocessorThrowable(final CoprocessorEnvironment env, final Throwable e)
-      throws IOException {
+  protected void handleCoprocessorThrowable(final E env, final Throwable e) throws IOException {
     if (e instanceof IOException) {
       throw (IOException)e;
     }
@@ -610,7 +448,7 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
                 "environment",e);
       }
 
-      coprocessors.remove(env);
+      coprocEnvironments.remove(env);
       try {
         shutdown(env);
       } catch (Exception x) {
@@ -695,4 +533,192 @@ public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
           "'. Details of the problem: " + message);
     }
   }
+
+  /**
+   * Implementations defined function to get an observer of type {@code O} from a coprocessor of
+   * type {@code C}. Concrete implementations of CoprocessorHost define one getter for each
+   * observer they can handle. For e.g. RegionCoprocessorHost will use 3 getters, one for
+   * each of RegionObserver, EndpointObserver and BulkLoadObserver.
+   * These getters are used by {@code ObserverOperation} to get appropriate observer from the
+   * coprocessor.
+   */
+  @FunctionalInterface
+  public interface ObserverGetter<C, O> extends Function<C, Optional<O>> {}
+
+  private abstract class ObserverOperation<O> extends ObserverContext<E> {
+    ObserverGetter<C, O> observerGetter;
+
+    ObserverOperation(ObserverGetter<C, O> observerGetter) {
+      this(observerGetter, RpcServer.getRequestUser());
+    }
+
+    ObserverOperation(ObserverGetter<C, O> observerGetter, User user) {
+      super(user);
+      this.observerGetter = observerGetter;
+    }
+
+    abstract void callObserver() throws IOException;
+    protected void postEnvCall() {}
+  }
+
+  // Can't derive ObserverOperation from ObserverOperationWithResult (R = Void) because then all
+  // ObserverCaller implementations will have to have a return statement.
+  // O = observer, E = environment, C = coprocessor, R=result type
+  public abstract class ObserverOperationWithoutResult<O> extends ObserverOperation<O> {
+    protected abstract void call(O observer) throws IOException;
+
+    public ObserverOperationWithoutResult(ObserverGetter<C, O> observerGetter) {
+      super(observerGetter);
+    }
+
+    public ObserverOperationWithoutResult(ObserverGetter<C, O> observerGetter, User user) {
+      super(observerGetter, user);
+    }
+
+    /**
+     * In case of coprocessors which have many kinds of observers (for eg, {@link RegionCoprocessor}
+     * has BulkLoadObserver, RegionObserver, etc), some implementations may not need all
+     * observers, in which case they will return null for that observer's getter.
+     * We simply ignore such cases.
+     */
+    @Override
+    void callObserver() throws IOException {
+      Optional<O> observer = observerGetter.apply(getEnvironment().getInstance());
+      if (observer.isPresent()) {
+        call(observer.get());
+      }
+    }
+  }
+
+  public abstract class ObserverOperationWithResult<O, R> extends ObserverOperation<O> {
+    protected abstract R call(O observer) throws IOException;
+
+    private R result;
+
+    public ObserverOperationWithResult(ObserverGetter<C, O> observerGetter) {
+      super(observerGetter);
+    }
+
+    public ObserverOperationWithResult(ObserverGetter<C, O> observerGetter, User user) {
+      super(observerGetter, user);
+    }
+
+    void setResult(final R result) {
+      this.result = result;
+    }
+
+    protected R getResult() {
+      return this.result;
+    }
+
+    void callObserver() throws IOException {
+      Optional<O> observer = observerGetter.apply(getEnvironment().getInstance());
+      if (observer.isPresent()) {
+        result = call(observer.get());
+      }
+    }
+  }
+
+  //////////////////////////////////////////////////////////////////////////////////////////
+  // Functions to execute observer hooks and handle results (if any)
+  //////////////////////////////////////////////////////////////////////////////////////////
+  protected <O, R> R execOperationWithResult(final R defaultValue,
+      final ObserverOperationWithResult<O, R> observerOperation) throws IOException {
+    if (observerOperation == null) {
+      return defaultValue;
+    }
+    observerOperation.setResult(defaultValue);
+    execOperation(observerOperation);
+    return observerOperation.getResult();
+  }
+
+  // what does bypass mean?
+  protected <O, R> R execOperationWithResult(final boolean ifBypass, final R defaultValue,
+      final ObserverOperationWithResult<O, R> observerOperation) throws IOException {
+    if (observerOperation == null) {
+      return ifBypass ? null : defaultValue;
+    } else {
+      observerOperation.setResult(defaultValue);
+      boolean bypass = execOperation(true, observerOperation);
+      R result = observerOperation.getResult();
+      return bypass == ifBypass ? result : null;
+    }
+  }
+
+  protected <O> boolean execOperation(final ObserverOperation<O> observerOperation)
+      throws IOException {
+    return execOperation(true, observerOperation);
+  }
+
+  protected <O> boolean execOperation(final boolean earlyExit,
+      final ObserverOperation<O> observerOperation) throws IOException {
+    if (observerOperation == null) return false;
+    boolean bypass = false;
+    List<E> envs = coprocEnvironments.get();
+    for (E env : envs) {
+      observerOperation.prepare(env);
+      Thread currentThread = Thread.currentThread();
+      ClassLoader cl = currentThread.getContextClassLoader();
+      try {
+        currentThread.setContextClassLoader(env.getClassLoader());
+        observerOperation.callObserver();
+      } catch (Throwable e) {
+        handleCoprocessorThrowable(env, e);
+      } finally {
+        currentThread.setContextClassLoader(cl);
+      }
+      bypass |= observerOperation.shouldBypass();
+      if (earlyExit && observerOperation.shouldComplete()) {
+        break;
+      }
+      observerOperation.postEnvCall();
+    }
+    return bypass;
+  }
+
+
+  /**
+   * Coprocessor classes can be configured in any order, based on that priority is set and
+   * chained in a sorted order. Should be used preStop*() hooks i.e. when master/regionserver is
+   * going down. This function first calls coprocessor methods (using ObserverOperation.call())
+   * and then shutdowns the environment in postEnvCall(). <br>
+   * Need to execute all coprocessor methods first then postEnvCall(), otherwise some coprocessors
+   * may remain shutdown if any exception occurs during next coprocessor execution which prevent
+   * master/regionserver stop or cluster shutdown. (Refer:
+   * <a href="https://issues.apache.org/jira/browse/HBASE-16663">HBASE-16663</a>
+   * @return true if bypaas coprocessor execution, false if not.
+   * @throws IOException
+   */
+  protected <O> boolean execShutdown(final ObserverOperation<O> observerOperation)
+      throws IOException {
+    if (observerOperation == null) return false;
+    boolean bypass = false;
+    List<E> envs = coprocEnvironments.get();
+    // Iterate the coprocessors and execute ObserverOperation's call()
+    for (E env : envs) {
+      observerOperation.prepare(env);
+      Thread currentThread = Thread.currentThread();
+      ClassLoader cl = currentThread.getContextClassLoader();
+      try {
+        currentThread.setContextClassLoader(env.getClassLoader());
+        observerOperation.callObserver();
+      } catch (Throwable e) {
+        handleCoprocessorThrowable(env, e);
+      } finally {
+        currentThread.setContextClassLoader(cl);
+      }
+      bypass |= observerOperation.shouldBypass();
+      if (observerOperation.shouldComplete()) {
+        break;
+      }
+    }
+
+    // Iterate the coprocessors and execute ObserverOperation's postEnvCall()
+    for (E env : envs) {
+      observerOperation.prepare(env);
+      observerOperation.postEnvCall();
+    }
+    return bypass;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorService.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorService.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorService.java
index efee64c..f610229 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorService.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorService.java
@@ -26,7 +26,9 @@ import org.apache.hadoop.hbase.HBaseInterfaceAudience;
 /**
  * Coprocessor endpoints providing protobuf services should implement this
  * interface and return the {@link Service} instance via {@link #getService()}.
+ * @deprecated Since 2.0. Will be removed in 3.0
  */
+@Deprecated
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
 public interface CoprocessorService {

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorServiceBackwardCompatiblity.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorServiceBackwardCompatiblity.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorServiceBackwardCompatiblity.java
new file mode 100644
index 0000000..c677d63
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorServiceBackwardCompatiblity.java
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.coprocessor;
+
+import com.google.protobuf.Service;
+import org.apache.yetus.audience.InterfaceAudience;
+
+import java.util.Optional;
+
+/**
+ * Classes to help maintain backward compatibility with now deprecated {@link CoprocessorService}
+ * and {@link SingletonCoprocessorService}.
+ * From 2.0 onwards, implementors of coprocessor service should also implement the relevant
+ * coprocessor class (For eg {@link MasterCoprocessor} for coprocessor service in master), and
+ * override get*Service() method to return the {@link com.google.protobuf.Service} object.
+ * To maintain backward compatibility with 1.0 implementation, we'll wrap implementation of
+ * CoprocessorService/SingletonCoprocessorService in the new
+ * {Master, Region, RegionServer}Coprocessor class.
+ * Since there is no backward compatibility guarantee for Observers, we leave get*Observer() to
+ * default which returns null.
+ * This approach to maintain backward compatibility seems cleaner and more explicit.
+ */
+@InterfaceAudience.Private
+@Deprecated
+public class CoprocessorServiceBackwardCompatiblity {
+
+  static public class MasterCoprocessorService implements MasterCoprocessor {
+
+    CoprocessorService service;
+
+    public MasterCoprocessorService(CoprocessorService service) {
+      this.service = service;
+    }
+
+    @Override
+    public Optional<Service> getService() {
+      return Optional.of(service.getService());
+    }
+  }
+
+  static public class RegionCoprocessorService implements RegionCoprocessor {
+
+    CoprocessorService service;
+
+    public RegionCoprocessorService(CoprocessorService service) {
+      this.service = service;
+    }
+
+    @Override
+    public Optional<Service> getService() {
+      return Optional.of(service.getService());
+    }
+  }
+
+  static public class RegionServerCoprocessorService implements RegionServerCoprocessor {
+
+    SingletonCoprocessorService service;
+
+    public RegionServerCoprocessorService(SingletonCoprocessorService service) {
+      this.service = service;
+    }
+
+    @Override
+    public Optional<Service> getService() {
+      return Optional.of(service.getService());
+    }
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/EndpointObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/EndpointObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/EndpointObserver.java
index fc0e666..096247c 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/EndpointObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/EndpointObserver.java
@@ -50,7 +50,7 @@ import com.google.protobuf.Service;
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface EndpointObserver extends Coprocessor {
+public interface EndpointObserver {
 
   /**
    * Called before an Endpoint service method is invoked.

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessor.java
new file mode 100644
index 0000000..d940385
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessor.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.coprocessor;
+
+import org.apache.hadoop.hbase.Coprocessor;
+import org.apache.hadoop.hbase.HBaseInterfaceAudience;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+
+import java.util.Optional;
+
+@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
+@InterfaceStability.Evolving
+public interface MasterCoprocessor extends Coprocessor {
+  default Optional<MasterObserver> getMasterObserver() {
+    return Optional.empty();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java
index adab32f..1668b69 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java
@@ -28,7 +28,7 @@ import org.apache.hadoop.hbase.metrics.MetricRegistry;
 
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface MasterCoprocessorEnvironment extends CoprocessorEnvironment {
+public interface MasterCoprocessorEnvironment extends CoprocessorEnvironment<MasterCoprocessor> {
   /** @return reference to the HMaster services */
   MasterServices getMasterServices();
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
index 87b9679..bfa88e6 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
@@ -77,7 +77,7 @@ import org.apache.yetus.audience.InterfaceStability;
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface MasterObserver extends Coprocessor {
+public interface MasterObserver {
   /**
    * Called before a new table is created by
    * {@link org.apache.hadoop.hbase.master.HMaster}.  Called as part of create

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MultiRowMutationEndpoint.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MultiRowMutationEndpoint.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MultiRowMutationEndpoint.java
index a4dcae0..c4fb440 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MultiRowMutationEndpoint.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MultiRowMutationEndpoint.java
@@ -20,12 +20,12 @@ package org.apache.hadoop.hbase.coprocessor;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
 import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.yetus.audience.InterfaceStability;
-import org.apache.hadoop.hbase.Coprocessor;
 import org.apache.hadoop.hbase.CoprocessorEnvironment;
 import org.apache.hadoop.hbase.HBaseInterfaceAudience;
 import org.apache.hadoop.hbase.HConstants;
@@ -77,8 +77,7 @@ import com.google.protobuf.Service;
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public class MultiRowMutationEndpoint extends MultiRowMutationService implements
-CoprocessorService, Coprocessor {
+public class MultiRowMutationEndpoint extends MultiRowMutationService implements RegionCoprocessor {
   private RegionCoprocessorEnvironment env;
   @Override
   public void mutateRows(RpcController controller, MutateRowsRequest request,
@@ -120,10 +119,9 @@ CoprocessorService, Coprocessor {
     done.run(response);
   }
 
-
   @Override
-  public Service getService() {
-    return this;
+  public Optional<Service> getService() {
+    return Optional.of(this);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/ObserverContext.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/ObserverContext.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/ObserverContext.java
index ba71129..0192ea3 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/ObserverContext.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/ObserverContext.java
@@ -116,13 +116,13 @@ public class ObserverContext<E extends CoprocessorEnvironment> {
    * @param env The coprocessor environment to set
    * @param context An existing ObserverContext instance to use, or <code>null</code>
    *     to create a new instance
-   * @param <T> The environment type for the context
+   * @param <E> The environment type for the context
    * @return An instance of <code>ObserverContext</code> with the environment set
    */
   @Deprecated
   // TODO: Remove this method, ObserverContext should not depend on RpcServer
-  public static <T extends CoprocessorEnvironment> ObserverContext<T> createAndPrepare(
-      T env, ObserverContext<T> context) {
+  public static <E extends CoprocessorEnvironment> ObserverContext<E> createAndPrepare(
+      E env, ObserverContext< E> context) {
     if (context == null) {
       context = new ObserverContext<>(RpcServer.getRequestUser());
     }
@@ -140,11 +140,11 @@ public class ObserverContext<E extends CoprocessorEnvironment> {
    * @param context An existing ObserverContext instance to use, or <code>null</code>
    *     to create a new instance
    * @param user The requesting caller for the execution context
-   * @param <T> The environment type for the context
+   * @param <E> The environment type for the context
    * @return An instance of <code>ObserverContext</code> with the environment set
    */
-  public static <T extends CoprocessorEnvironment> ObserverContext<T> createAndPrepare(
-      T env, ObserverContext<T> context, User user) {
+  public static <E extends CoprocessorEnvironment> ObserverContext<E> createAndPrepare(
+      E env, ObserverContext<E> context, User user) {
     if (context == null) {
       context = new ObserverContext<>(user);
     }

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessor.java
new file mode 100644
index 0000000..16c6d39
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessor.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.coprocessor;
+
+import org.apache.hadoop.hbase.Coprocessor;
+import org.apache.hadoop.hbase.HBaseInterfaceAudience;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+
+import java.util.Optional;
+
+@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
+@InterfaceStability.Evolving
+public interface RegionCoprocessor extends Coprocessor {
+
+  default Optional<RegionObserver> getRegionObserver() {
+    return Optional.empty();
+  }
+
+  default Optional<EndpointObserver> getEndpointObserver() {
+    return Optional.empty();
+  }
+
+  default Optional<BulkLoadObserver> getBulkLoadObserver() {
+    return Optional.empty();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java
index dceb3d4..b29cd28 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java
@@ -32,7 +32,7 @@ import org.apache.yetus.audience.InterfaceStability;
 
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface RegionCoprocessorEnvironment extends CoprocessorEnvironment {
+public interface RegionCoprocessorEnvironment extends CoprocessorEnvironment<RegionCoprocessor> {
   /** @return the region associated with this coprocessor */
   Region getRegion();
 
@@ -61,6 +61,4 @@ public interface RegionCoprocessorEnvironment extends CoprocessorEnvironment {
   // so we do not want to allow coprocessors to export metrics at the region level. We can allow
   // getMetricRegistryForTable() to allow coprocessors to track metrics per-table, per-regionserver.
   MetricRegistry getMetricRegistryForRegionServer();
-
-
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
index 60e5f40..75c1da9 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
@@ -99,7 +99,7 @@ import org.apache.yetus.audience.InterfaceStability;
 // TODO as method signatures need to break, update to
 // ObserverContext<? extends RegionCoprocessorEnvironment>
 // so we can use additional environment state that isn't exposed to coprocessors.
-public interface RegionObserver extends Coprocessor {
+public interface RegionObserver {
   /** Mutation type for postMutationBeforeWAL hook */
   enum MutationType {
     APPEND, INCREMENT

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessor.java
new file mode 100644
index 0000000..66d8113
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessor.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.coprocessor;
+
+import org.apache.hadoop.hbase.Coprocessor;
+import org.apache.hadoop.hbase.HBaseInterfaceAudience;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+
+import java.util.Optional;
+
+@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
+@InterfaceStability.Evolving
+public interface RegionServerCoprocessor extends Coprocessor {
+  default Optional<RegionServerObserver> getRegionServerObserver() {
+    return Optional.empty();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java
index da3189f..ecd0f3e 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerCoprocessorEnvironment.java
@@ -27,7 +27,8 @@ import org.apache.yetus.audience.InterfaceStability;
 
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface RegionServerCoprocessorEnvironment extends CoprocessorEnvironment {
+public interface RegionServerCoprocessorEnvironment
+    extends CoprocessorEnvironment<RegionServerCoprocessor> {
   /**
    * Gets the region server services.
    *

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java
index 5d68eec..c1af3fb 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java
@@ -53,7 +53,7 @@ import org.apache.yetus.audience.InterfaceStability;
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface RegionServerObserver extends Coprocessor {
+public interface RegionServerObserver {
   /**
    * Called before stopping region server.
    * @param ctx the environment to interact with the framework and region server.

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/SingletonCoprocessorService.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/SingletonCoprocessorService.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/SingletonCoprocessorService.java
index c7131ff..719acf7 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/SingletonCoprocessorService.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/SingletonCoprocessorService.java
@@ -26,7 +26,9 @@ import org.apache.hadoop.hbase.HBaseInterfaceAudience;
 /**
  * Coprocessor endpoints registered once per server and providing protobuf services should implement
  * this interface and return the {@link Service} instance via {@link #getService()}.
+ * @deprecated Since 2.0. Will be removed in 3.0
  */
+@Deprecated
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
 public interface SingletonCoprocessorService {

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessor.java
new file mode 100644
index 0000000..d87c06d
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessor.java
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.coprocessor;
+
+import org.apache.hadoop.hbase.Coprocessor;
+import org.apache.hadoop.hbase.HBaseInterfaceAudience;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+
+import java.util.Optional;
+
+/**
+ * WALCoprocessor don't support loading services using {@link #getService()}.
+ */
+@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
+@InterfaceStability.Evolving
+public interface WALCoprocessor extends Coprocessor {
+  Optional<WALObserver> getWALObserver();
+
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessorEnvironment.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessorEnvironment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessorEnvironment.java
index 8ea399d..71c72a2 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessorEnvironment.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALCoprocessorEnvironment.java
@@ -28,7 +28,7 @@ import org.apache.hadoop.hbase.wal.WAL;
 
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface WALCoprocessorEnvironment extends CoprocessorEnvironment {
+public interface WALCoprocessorEnvironment extends CoprocessorEnvironment<WALCoprocessor> {
   /** @return reference to the region server's WAL */
   WAL getWAL();
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALObserver.java
index 52c27f7..2190abf 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/WALObserver.java
@@ -66,7 +66,7 @@ import org.apache.yetus.audience.InterfaceStability;
  */
 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
 @InterfaceStability.Evolving
-public interface WALObserver extends Coprocessor {
+public interface WALObserver {
   /**
    * Called before a {@link WALEdit}
    * is writen to WAL.

http://git-wip-us.apache.org/repos/asf/hbase/blob/97513466/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java
index 8a677ee..a6b5c4b 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java
@@ -181,9 +181,8 @@ To implement an Endpoint, you need to:
  <a href="https://developers.google.com/protocol-buffers/docs/proto#services">protocol buffer guide</a>
  for more details on defining services.</li>
  <li>Generate the Service and Message code using the protoc compiler</li>
- <li>Implement the generated Service interface in your coprocessor class and implement the
- <code>CoprocessorService</code> interface.  The <code>CoprocessorService.getService()</code>
- method should return a reference to the Endpoint's protocol buffer Service instance.
+ <li>Implement the generated Service interface and override get*Service() method in
+ relevant Coprocessor to return a reference to the Endpoint's protocol buffer Service instance.
 </ul>
 <p>
 For a more detailed discussion of how to implement a coprocessor Endpoint, along with some sample


Mime
View raw message