You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ga...@apache.org on 2010/12/21 21:39:37 UTC
svn commit: r1051639 [1/3] - in /hbase/trunk: ./
src/main/java/org/apache/hadoop/hbase/coprocessor/
src/main/java/org/apache/hadoop/hbase/master/
src/main/java/org/apache/hadoop/hbase/regionserver/ src/main/resources/
src/test/java/org/apache/hadoop/hb...
Author: garyh
Date: Tue Dec 21 20:39:26 2010
New Revision: 1051639
URL: http://svn.apache.org/viewvc?rev=1051639&view=rev
Log:
HBASE-3256: Add coprocessor host and observer for HMaster
Added:
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java
hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
Removed:
hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/CoprocessorHost.java
Modified:
hbase/trunk/CHANGES.txt
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorEnvironment.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
hbase/trunk/src/main/resources/hbase-default.xml
hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/ColumnAggregationEndpoint.java
hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java
hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestCoprocessorEndpoint.java
hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestCoprocessorInterface.java
hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java
hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverStacking.java
hbase/trunk/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
Modified: hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hbase/trunk/CHANGES.txt?rev=1051639&r1=1051638&r2=1051639&view=diff
==============================================================================
--- hbase/trunk/CHANGES.txt (original)
+++ hbase/trunk/CHANGES.txt Tue Dec 21 20:39:26 2010
@@ -46,6 +46,7 @@ Release 0.91.0 - Unreleased
HBASE-3287 Add option to cache blocks on hfile write and evict blocks on
hfile close
HBASE-3335 Add BitComparator for filtering (Nathaniel Cook via Stack)
+ HBASE-3256 Coprocessors: Coprocessor host and observer for HMaster
Release 0.90.0 - Unreleased
Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java?rev=1051639&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java (added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java Tue Dec 21 20:39:26 2010
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * 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.HColumnDescriptor;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.HServerInfo;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.UnknownRegionException;
+
+import java.io.IOException;
+
+public class BaseMasterObserver implements MasterObserver {
+ @Override
+ public void preCreateTable(MasterCoprocessorEnvironment env,
+ HTableDescriptor desc, byte[][] splitKeys) throws IOException {
+ }
+
+ @Override
+ public void postCreateTable(MasterCoprocessorEnvironment env,
+ HRegionInfo[] regions, boolean sync) throws IOException {
+ }
+
+ @Override
+ public void preDeleteTable(MasterCoprocessorEnvironment env, byte[] tableName)
+ throws IOException {
+ }
+
+ @Override
+ public void postDeleteTable(MasterCoprocessorEnvironment env, byte[] tableName)
+ throws IOException {
+ }
+
+ @Override
+ public void preModifyTable(MasterCoprocessorEnvironment env,
+ byte[] tableName, HTableDescriptor htd) throws IOException {
+ }
+
+ @Override
+ public void postModifyTable(MasterCoprocessorEnvironment env,
+ byte[] tableName, HTableDescriptor htd) throws IOException {
+ }
+
+ @Override
+ public void preAddColumn(MasterCoprocessorEnvironment env,
+ byte[] tableName, HColumnDescriptor column) throws IOException {
+ }
+
+ @Override
+ public void postAddColumn(MasterCoprocessorEnvironment env, byte[] tableName,
+ HColumnDescriptor column) throws IOException {
+ }
+
+ @Override
+ public void preModifyColumn(MasterCoprocessorEnvironment env,
+ byte[] tableName, HColumnDescriptor descriptor) throws IOException {
+ }
+
+ @Override
+ public void postModifyColumn(MasterCoprocessorEnvironment env,
+ byte[] tableName, HColumnDescriptor descriptor) throws IOException {
+ }
+
+ @Override
+ public void preDeleteColumn(MasterCoprocessorEnvironment env,
+ byte[] tableName, byte[] c) throws IOException {
+ }
+
+ @Override
+ public void postDeleteColumn(MasterCoprocessorEnvironment env,
+ byte[] tableName, byte[] c) throws IOException {
+ }
+
+ @Override
+ public void preEnableTable(MasterCoprocessorEnvironment env, byte[] tableName)
+ throws IOException {
+ }
+
+ @Override
+ public void postEnableTable(MasterCoprocessorEnvironment env,
+ byte[] tableName) throws IOException {
+ }
+
+ @Override
+ public void preDisableTable(MasterCoprocessorEnvironment env,
+ byte[] tableName) throws IOException {
+ }
+
+ @Override
+ public void postDisableTable(MasterCoprocessorEnvironment env,
+ byte[] tableName) throws IOException {
+ }
+
+ @Override
+ public void preMove(MasterCoprocessorEnvironment env, HRegionInfo region,
+ HServerInfo srcServer, HServerInfo destServer)
+ throws UnknownRegionException {
+ }
+
+ @Override
+ public void postMove(MasterCoprocessorEnvironment env, HRegionInfo region,
+ HServerInfo srcServer, HServerInfo destServer)
+ throws UnknownRegionException {
+ }
+
+ @Override
+ public void preAssign(MasterCoprocessorEnvironment env, byte[] regionName,
+ boolean force) throws IOException {
+ }
+
+ @Override
+ public void postAssign(MasterCoprocessorEnvironment env,
+ HRegionInfo regionInfo) throws IOException {
+ }
+
+ @Override
+ public void preUnassign(MasterCoprocessorEnvironment env, byte[] regionName,
+ boolean force) throws IOException {
+ }
+
+ @Override
+ public void postUnassign(MasterCoprocessorEnvironment env,
+ HRegionInfo regionInfo, boolean force) throws IOException {
+ }
+
+ @Override
+ public void preBalance(MasterCoprocessorEnvironment env) throws IOException {
+ }
+
+ @Override
+ public void postBalance(MasterCoprocessorEnvironment env) throws IOException {
+ }
+
+ @Override
+ public boolean preBalanceSwitch(MasterCoprocessorEnvironment env, boolean b)
+ throws IOException {
+ return b;
+ }
+
+ @Override
+ public void postBalanceSwitch(MasterCoprocessorEnvironment env,
+ boolean oldValue, boolean newValue) throws IOException {
+ }
+
+ @Override
+ public void preShutdown(MasterCoprocessorEnvironment env) throws IOException {
+ }
+
+ @Override
+ public void preStopMaster(MasterCoprocessorEnvironment env)
+ throws IOException {
+ }
+
+ @Override
+ public void start(CoprocessorEnvironment env) throws IOException {
+ }
+
+ @Override
+ public void stop(CoprocessorEnvironment env) throws IOException {
+ }
+}
Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java?rev=1051639&r1=1051638&r2=1051639&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserverCoprocessor.java Tue Dec 21 20:39:26 2010
@@ -36,8 +36,7 @@ import java.io.IOException;
* By extending it, you can create you own region observer without
* overriding all abstract methods of Coprocessor and RegionObserver.
*/
-public abstract class BaseRegionObserverCoprocessor implements Coprocessor,
- RegionObserver {
+public abstract class BaseRegionObserverCoprocessor implements RegionObserver {
@Override
public void start(CoprocessorEnvironment e) { }
@@ -45,94 +44,94 @@ public abstract class BaseRegionObserver
public void stop(CoprocessorEnvironment e) { }
@Override
- public void preOpen(CoprocessorEnvironment e) { }
+ public void preOpen(RegionCoprocessorEnvironment e) { }
@Override
- public void postOpen(CoprocessorEnvironment e) { }
+ public void postOpen(RegionCoprocessorEnvironment e) { }
@Override
- public void preClose(CoprocessorEnvironment e, boolean abortRequested)
+ public void preClose(RegionCoprocessorEnvironment e, boolean abortRequested)
{ }
@Override
- public void postClose(CoprocessorEnvironment e, boolean abortRequested)
+ public void postClose(RegionCoprocessorEnvironment e, boolean abortRequested)
{ }
@Override
- public void preFlush(CoprocessorEnvironment e) { }
+ public void preFlush(RegionCoprocessorEnvironment e) { }
@Override
- public void postFlush(CoprocessorEnvironment e) { }
+ public void postFlush(RegionCoprocessorEnvironment e) { }
@Override
- public void preSplit(CoprocessorEnvironment e) { }
+ public void preSplit(RegionCoprocessorEnvironment e) { }
@Override
- public void postSplit(CoprocessorEnvironment e, HRegion l, HRegion r) { }
+ public void postSplit(RegionCoprocessorEnvironment e, HRegion l, HRegion r) { }
@Override
- public void preCompact(CoprocessorEnvironment e, boolean willSplit) { }
+ public void preCompact(RegionCoprocessorEnvironment e, boolean willSplit) { }
@Override
- public void postCompact(CoprocessorEnvironment e, boolean willSplit) { }
+ public void postCompact(RegionCoprocessorEnvironment e, boolean willSplit) { }
@Override
- public void preGetClosestRowBefore(final CoprocessorEnvironment e,
+ public void preGetClosestRowBefore(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final Result result)
throws IOException {
}
@Override
- public void postGetClosestRowBefore(final CoprocessorEnvironment e,
+ public void postGetClosestRowBefore(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final Result result)
throws IOException {
}
@Override
- public void preGet(final CoprocessorEnvironment e, final Get get,
+ public void preGet(final RegionCoprocessorEnvironment e, final Get get,
final List<KeyValue> results) throws IOException {
}
@Override
- public void postGet(final CoprocessorEnvironment e, final Get get,
+ public void postGet(final RegionCoprocessorEnvironment e, final Get get,
final List<KeyValue> results) throws IOException {
}
@Override
- public boolean preExists(final CoprocessorEnvironment e, final Get get,
+ public boolean preExists(final RegionCoprocessorEnvironment e, final Get get,
final boolean exists) throws IOException {
return exists;
}
@Override
- public boolean postExists(final CoprocessorEnvironment e, final Get get,
+ public boolean postExists(final RegionCoprocessorEnvironment e, final Get get,
boolean exists) throws IOException {
return exists;
}
@Override
- public void prePut(final CoprocessorEnvironment e, final Map<byte[],
+ public void prePut(final RegionCoprocessorEnvironment e, final Map<byte[],
List<KeyValue>> familyMap, final boolean writeToWAL) throws IOException {
}
@Override
- public void postPut(final CoprocessorEnvironment e, final Map<byte[],
+ public void postPut(final RegionCoprocessorEnvironment e, final Map<byte[],
List<KeyValue>> familyMap, final boolean writeToWAL) throws IOException {
}
@Override
- public void preDelete(final CoprocessorEnvironment e, final Map<byte[],
+ public void preDelete(final RegionCoprocessorEnvironment e, final Map<byte[],
List<KeyValue>> familyMap, final boolean writeToWAL) throws IOException {
}
@Override
- public void postDelete(final CoprocessorEnvironment e,
+ public void postDelete(final RegionCoprocessorEnvironment e,
final Map<byte[], List<KeyValue>> familyMap, final boolean writeToWAL)
throws IOException {
}
@Override
- public boolean preCheckAndPut(final CoprocessorEnvironment e,
+ public boolean preCheckAndPut(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Put put, final boolean result)
throws IOException {
@@ -140,7 +139,7 @@ public abstract class BaseRegionObserver
}
@Override
- public boolean postCheckAndPut(final CoprocessorEnvironment e,
+ public boolean postCheckAndPut(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Put put, final boolean result)
throws IOException {
@@ -148,7 +147,7 @@ public abstract class BaseRegionObserver
}
@Override
- public boolean preCheckAndDelete(final CoprocessorEnvironment e,
+ public boolean preCheckAndDelete(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Delete delete, final boolean result)
throws IOException {
@@ -156,7 +155,7 @@ public abstract class BaseRegionObserver
}
@Override
- public boolean postCheckAndDelete(final CoprocessorEnvironment e,
+ public boolean postCheckAndDelete(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Delete delete, final boolean result)
throws IOException {
@@ -164,14 +163,14 @@ public abstract class BaseRegionObserver
}
@Override
- public long preIncrementColumnValue(final CoprocessorEnvironment e,
+ public long preIncrementColumnValue(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final long amount, final boolean writeToWAL) throws IOException {
return amount;
}
@Override
- public long postIncrementColumnValue(final CoprocessorEnvironment e,
+ public long postIncrementColumnValue(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final long amount, final boolean writeToWAL, long result)
throws IOException {
@@ -179,48 +178,48 @@ public abstract class BaseRegionObserver
}
@Override
- public void preIncrement(final CoprocessorEnvironment e,
+ public void preIncrement(final RegionCoprocessorEnvironment e,
final Increment increment, final Result result) throws IOException {
}
@Override
- public void postIncrement(final CoprocessorEnvironment e,
+ public void postIncrement(final RegionCoprocessorEnvironment e,
final Increment increment, final Result result) throws IOException {
}
@Override
- public InternalScanner preScannerOpen(final CoprocessorEnvironment e,
+ public InternalScanner preScannerOpen(final RegionCoprocessorEnvironment e,
final Scan scan, final InternalScanner s) throws IOException {
return s;
}
@Override
- public InternalScanner postScannerOpen(final CoprocessorEnvironment e,
+ public InternalScanner postScannerOpen(final RegionCoprocessorEnvironment e,
final Scan scan, final InternalScanner s) throws IOException {
return s;
}
@Override
- public boolean preScannerNext(final CoprocessorEnvironment e,
+ public boolean preScannerNext(final RegionCoprocessorEnvironment e,
final InternalScanner s, final List<KeyValue> results,
final int limit, final boolean hasMore) throws IOException {
return hasMore;
}
@Override
- public boolean postScannerNext(final CoprocessorEnvironment e,
+ public boolean postScannerNext(final RegionCoprocessorEnvironment e,
final InternalScanner s, final List<KeyValue> results, final int limit,
final boolean hasMore) throws IOException {
return hasMore;
}
@Override
- public void preScannerClose(final CoprocessorEnvironment e,
+ public void preScannerClose(final RegionCoprocessorEnvironment e,
final InternalScanner s) throws IOException {
}
@Override
- public void postScannerClose(final CoprocessorEnvironment e,
+ public void postScannerClose(final RegionCoprocessorEnvironment e,
final InternalScanner s) throws IOException {
}
}
Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorEnvironment.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorEnvironment.java?rev=1051639&r1=1051638&r2=1051639&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorEnvironment.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorEnvironment.java Tue Dec 21 20:39:26 2010
@@ -33,11 +33,11 @@ public interface CoprocessorEnvironment
/** @return the HBase version as a string (e.g. "0.21.0") */
public String getHBaseVersion();
- /** @return the region associated with this coprocessor */
- public HRegion getRegion();
+ /** @return the loaded coprocessor instance */
+ public Coprocessor getInstance();
- /** @return reference to the region server services */
- public RegionServerServices getRegionServerServices();
+ /** @return the priority assigned to the loaded coprocessor */
+ public Coprocessor.Priority getPriority();
/**
* @return an interface for accessing the given table
Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java?rev=1051639&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java (added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java Tue Dec 21 20:39:26 2010
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * 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.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.*;
+import org.apache.hadoop.hbase.client.coprocessor.Batch;
+import org.apache.hadoop.hbase.ipc.CoprocessorProtocol;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.VersionInfo;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.*;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Provides the common setup framework and runtime services for coprocessor
+ * invocation from HBase services.
+ * @param <E> the specific environment extension that a concrete implementation
+ * provides
+ */
+public abstract class CoprocessorHost<E extends CoprocessorEnvironment> {
+ public static final String REGION_COPROCESSOR_CONF_KEY =
+ "hbase.coprocessor.region.classes";
+ public static final String MASTER_COPROCESSOR_CONF_KEY =
+ "hbase.coprocessor.master.classes";
+ private static final Log LOG = LogFactory.getLog(CoprocessorHost.class);
+ /** Ordered set of loaded coprocessors with lock */
+ protected final ReentrantReadWriteLock coprocessorLock = new ReentrantReadWriteLock();
+ protected Set<E> coprocessors =
+ new TreeSet<E>(new EnvironmentPriorityComparator());
+ // unique file prefix to use for local copies of jars when classloading
+ protected String pathPrefix;
+
+ public CoprocessorHost() {
+ pathPrefix = UUID.randomUUID().toString();
+ }
+
+ /**
+ * Load system coprocessors. Read the class names from configuration.
+ * Called by constructor.
+ */
+ protected void loadSystemCoprocessors(Configuration conf, String confKey) {
+ Class<?> implClass = null;
+
+ // load default coprocessors from configure file
+ String defaultCPClasses = conf.get(confKey);
+ if (defaultCPClasses == null || defaultCPClasses.length() == 0)
+ return;
+ StringTokenizer st = new StringTokenizer(defaultCPClasses, ",");
+ int priority = Coprocessor.Priority.SYSTEM.intValue();
+ while (st.hasMoreTokens()) {
+ String className = st.nextToken();
+ if (findCoprocessor(className) != null) {
+ continue;
+ }
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ Thread.currentThread().setContextClassLoader(cl);
+ try {
+ implClass = cl.loadClass(className);
+ load(implClass, Coprocessor.Priority.SYSTEM);
+ LOG.info("System coprocessor " + className + " was loaded " +
+ "successfully with priority (" + priority++ + ").");
+ } catch (ClassNotFoundException e) {
+ LOG.warn("Class " + className + " cannot be found. " +
+ e.getMessage());
+ } catch (IOException e) {
+ LOG.warn("Load coprocessor " + className + " failed. " +
+ e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Load a coprocessor implementation into the host
+ * @param path path to implementation jar
+ * @param className the main class name
+ * @param priority chaining priority
+ * @throws java.io.IOException Exception
+ */
+ @SuppressWarnings("deprecation")
+ public void load(Path path, String className, Coprocessor.Priority priority)
+ throws IOException {
+ Class<?> implClass = null;
+
+ // Have we already loaded the class, perhaps from an earlier region open
+ // for the same table?
+ try {
+ implClass = getClass().getClassLoader().loadClass(className);
+ } catch (ClassNotFoundException e) {
+ LOG.info("Class " + className + " needs to be loaded from a file - " +
+ path.toString() + ".");
+ // go ahead to load from file system.
+ }
+
+ // If not, load
+ if (implClass == null) {
+ // copy the jar to the local filesystem
+ if (!path.toString().endsWith(".jar")) {
+ throw new IOException(path.toString() + ": not a jar file?");
+ }
+ FileSystem fs = path.getFileSystem(HBaseConfiguration.create());
+ Path dst = new Path("/tmp/." + pathPrefix +
+ "." + className + "." + System.currentTimeMillis() + ".jar");
+ fs.copyToLocalFile(path, dst);
+ fs.deleteOnExit(dst);
+
+ // TODO: code weaving goes here
+
+ // TODO: wrap heap allocations and enforce maximum usage limits
+
+ /* TODO: inject code into loop headers that monitors CPU use and
+ aborts runaway user code */
+
+ // load the jar and get the implementation main class
+ String cp = System.getProperty("java.class.path");
+ // NOTE: Path.toURL is deprecated (toURI instead) but the URLClassLoader
+ // unsuprisingly wants URLs, not URIs; so we will use the deprecated
+ // method which returns URLs for as long as it is available
+ List<URL> paths = new ArrayList<URL>();
+ paths.add(new File(dst.toString()).getCanonicalFile().toURL());
+ StringTokenizer st = new StringTokenizer(cp, File.pathSeparator);
+ while (st.hasMoreTokens()) {
+ paths.add((new File(st.nextToken())).getCanonicalFile().toURL());
+ }
+ ClassLoader cl = new URLClassLoader(paths.toArray(new URL[]{}),
+ ClassLoader.getSystemClassLoader());
+ Thread.currentThread().setContextClassLoader(cl);
+ try {
+ implClass = cl.loadClass(className);
+ } catch (ClassNotFoundException e) {
+ throw new IOException(e);
+ }
+ }
+
+ load(implClass, priority);
+ }
+
+ /**
+ * @param implClass Implementation class
+ * @param priority priority
+ * @throws java.io.IOException Exception
+ */
+ public void load(Class<?> implClass, Coprocessor.Priority priority)
+ throws IOException {
+ // create the instance
+ Coprocessor impl;
+ Object o = null;
+ try {
+ o = implClass.newInstance();
+ impl = (Coprocessor)o;
+ } catch (InstantiationException e) {
+ throw new IOException(e);
+ } catch (IllegalAccessException e) {
+ throw new IOException(e);
+ }
+ // create the environment
+ E env = createEnvironment(implClass, impl, priority);
+ if (env instanceof Environment) {
+ ((Environment)env).startup();
+ }
+
+ try {
+ coprocessorLock.writeLock().lock();
+ coprocessors.add(env);
+ } finally {
+ coprocessorLock.writeLock().unlock();
+ }
+ }
+
+ /**
+ * Called when a new Coprocessor class is loaded
+ */
+ public abstract E createEnvironment(Class<?> implClass, Coprocessor instance,
+ Coprocessor.Priority priority);
+
+ public void shutdown(CoprocessorEnvironment e) {
+ if (e instanceof Environment) {
+ ((Environment)e).shutdown();
+ } else {
+ LOG.warn("Shutdown called on unknown environment: "+
+ e.getClass().getName());
+ }
+ }
+
+ /**
+ * Find a coprocessor implementation by class name
+ * @param className the class name
+ * @return the coprocessor, or null if not found
+ */
+ public Coprocessor findCoprocessor(String className) {
+ // initialize the coprocessors
+ try {
+ coprocessorLock.readLock().lock();
+ for (E env: coprocessors) {
+ if (env.getInstance().getClass().getName().equals(className) ||
+ env.getInstance().getClass().getSimpleName().equals(className)) {
+ return env.getInstance();
+ }
+ }
+ return null;
+ } finally {
+ coprocessorLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Environment priority comparator.
+ * Coprocessors are chained in sorted order.
+ */
+ static class EnvironmentPriorityComparator implements Comparator<CoprocessorEnvironment> {
+ public int compare(CoprocessorEnvironment env1, CoprocessorEnvironment env2) {
+ if (env1.getPriority().intValue() < env2.getPriority().intValue()) {
+ return -1;
+ } else if (env1.getPriority().intValue() > env2.getPriority().intValue()) {
+ return 1;
+ }
+ return 0;
+ }
+ }
+
+ /**
+ * Encapsulation of the environment of each coprocessor
+ */
+ public static class Environment implements CoprocessorEnvironment {
+
+ /**
+ * A wrapper for HTable. Can be used to restrict privilege.
+ *
+ * Currently it just helps to track tables opened by a Coprocessor and
+ * facilitate close of them if it is aborted.
+ *
+ * We also disallow row locking.
+ *
+ * There is nothing now that will stop a coprocessor from using HTable
+ * objects directly instead of this API, but in the future we intend to
+ * analyze coprocessor implementations as they are loaded and reject those
+ * which attempt to use objects and methods outside the Environment
+ * sandbox.
+ */
+ class HTableWrapper implements HTableInterface {
+
+ private byte[] tableName;
+ private HTable table;
+
+ public HTableWrapper(byte[] tableName) throws IOException {
+ this.tableName = tableName;
+ this.table = new HTable(tableName);
+ openTables.add(this);
+ }
+
+ void internalClose() throws IOException {
+ table.close();
+ }
+
+ public Configuration getConfiguration() {
+ return table.getConfiguration();
+ }
+
+ public void close() throws IOException {
+ try {
+ internalClose();
+ } finally {
+ openTables.remove(this);
+ }
+ }
+
+ public Result getRowOrBefore(byte[] row, byte[] family)
+ throws IOException {
+ return table.getRowOrBefore(row, family);
+ }
+
+ public Result get(Get get) throws IOException {
+ return table.get(get);
+ }
+
+ public boolean exists(Get get) throws IOException {
+ return table.exists(get);
+ }
+
+ public void put(Put put) throws IOException {
+ table.put(put);
+ }
+
+ public void put(List<Put> puts) throws IOException {
+ table.put(puts);
+ }
+
+ public void delete(Delete delete) throws IOException {
+ table.delete(delete);
+ }
+
+ public void delete(List<Delete> deletes) throws IOException {
+ table.delete(deletes);
+ }
+
+ public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier,
+ byte[] value, Put put) throws IOException {
+ return table.checkAndPut(row, family, qualifier, value, put);
+ }
+
+ public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier,
+ byte[] value, Delete delete) throws IOException {
+ return table.checkAndDelete(row, family, qualifier, value, delete);
+ }
+
+ public long incrementColumnValue(byte[] row, byte[] family,
+ byte[] qualifier, long amount) throws IOException {
+ return table.incrementColumnValue(row, family, qualifier, amount);
+ }
+
+ public long incrementColumnValue(byte[] row, byte[] family,
+ byte[] qualifier, long amount, boolean writeToWAL)
+ throws IOException {
+ return table.incrementColumnValue(row, family, qualifier, amount,
+ writeToWAL);
+ }
+
+ @Override
+ public Result increment(Increment increment) throws IOException {
+ return table.increment(increment);
+ }
+
+ public void flushCommits() throws IOException {
+ table.flushCommits();
+ }
+
+ public boolean isAutoFlush() {
+ return table.isAutoFlush();
+ }
+
+ public ResultScanner getScanner(Scan scan) throws IOException {
+ return table.getScanner(scan);
+ }
+
+ public ResultScanner getScanner(byte[] family) throws IOException {
+ return table.getScanner(family);
+ }
+
+ public ResultScanner getScanner(byte[] family, byte[] qualifier)
+ throws IOException {
+ return table.getScanner(family, qualifier);
+ }
+
+ public HTableDescriptor getTableDescriptor() throws IOException {
+ return table.getTableDescriptor();
+ }
+
+ public byte[] getTableName() {
+ return tableName;
+ }
+
+ public RowLock lockRow(byte[] row) throws IOException {
+ throw new RuntimeException(
+ "row locking is not allowed within the coprocessor environment");
+ }
+
+ public void unlockRow(RowLock rl) throws IOException {
+ throw new RuntimeException(
+ "row locking is not allowed within the coprocessor environment");
+ }
+
+ @Override
+ public void batch(List<Row> actions, Object[] results)
+ throws IOException, InterruptedException {
+ table.batch(actions, results);
+ }
+
+ @Override
+ public Object[] batch(List<Row> actions)
+ throws IOException, InterruptedException {
+ return table.batch(actions);
+ }
+
+ @Override
+ public Result[] get(List<Get> gets) throws IOException {
+ return table.get(gets);
+ }
+
+ @Override
+ public <T extends CoprocessorProtocol, R> void coprocessorExec(Class<T> protocol,
+ byte[] startKey, byte[] endKey, Batch.Call<T, R> callable,
+ Batch.Callback<R> callback) throws IOException, Throwable {
+ table.coprocessorExec(protocol, startKey, endKey, callable, callback);
+ }
+
+ @Override
+ public <T extends CoprocessorProtocol, R> Map<byte[], R> coprocessorExec(
+ Class<T> protocol, byte[] startKey, byte[] endKey, Batch.Call<T, R> callable)
+ throws IOException, Throwable {
+ return table.coprocessorExec(protocol, startKey, endKey, callable);
+ }
+
+ @Override
+ public <T extends CoprocessorProtocol> T coprocessorProxy(Class<T> protocol,
+ byte[] row) {
+ return table.coprocessorProxy(protocol, row);
+ }
+ }
+
+ /** The coprocessor */
+ public Coprocessor impl;
+ /** Chaining priority */
+ protected Coprocessor.Priority priority = Coprocessor.Priority.USER;
+ /** Current coprocessor state */
+ Coprocessor.State state = Coprocessor.State.UNINSTALLED;
+ /** Accounting for tables opened by the coprocessor */
+ protected List<HTableInterface> openTables =
+ Collections.synchronizedList(new ArrayList<HTableInterface>());
+ static final ThreadLocal<Boolean> bypass = new ThreadLocal<Boolean>() {
+ @Override protected Boolean initialValue() {
+ return Boolean.FALSE;
+ }
+ };
+ static final ThreadLocal<Boolean> complete = new ThreadLocal<Boolean>() {
+ @Override protected Boolean initialValue() {
+ return Boolean.FALSE;
+ }
+ };
+
+ /**
+ * Constructor
+ * @param impl the coprocessor instance
+ * @param priority chaining priority
+ */
+ public Environment(final Coprocessor impl, Coprocessor.Priority priority) {
+ this.impl = impl;
+ this.priority = priority;
+ this.state = Coprocessor.State.INSTALLED;
+ }
+
+ /** Initialize the environment */
+ public void startup() {
+ if (state == Coprocessor.State.INSTALLED ||
+ state == Coprocessor.State.STOPPED) {
+ state = Coprocessor.State.STARTING;
+ try {
+ impl.start(this);
+ state = Coprocessor.State.ACTIVE;
+ } catch (IOException ioe) {
+ LOG.error("Error starting coprocessor "+impl.getClass().getName(), ioe);
+ }
+ } 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;
+ try {
+ impl.stop(this);
+ state = Coprocessor.State.STOPPED;
+ } catch (IOException ioe) {
+ LOG.error("Error stopping coprocessor "+impl.getClass().getName(), ioe);
+ }
+ } else {
+ LOG.warn("Not stopping coprocessor "+impl.getClass().getName()+
+ " because not active (state="+state.toString()+")");
+ }
+ // clean up any table references
+ for (HTableInterface table: openTables) {
+ try {
+ ((HTableWrapper)table).internalClose();
+ } catch (IOException e) {
+ // nothing can be done here
+ LOG.warn("Failed to close " +
+ Bytes.toStringBinary(table.getTableName()), e);
+ }
+ }
+ }
+
+ public boolean shouldBypass() {
+ boolean current = bypass.get();
+ bypass.set(false);
+ return current;
+ }
+
+ public boolean shouldComplete() {
+ boolean current = complete.get();
+ complete.set(false);
+ return current;
+ }
+
+ @Override
+ public Coprocessor getInstance() {
+ return impl;
+ }
+
+ @Override
+ public Coprocessor.Priority getPriority() {
+ return priority;
+ }
+
+ /** @return the coprocessor environment version */
+ @Override
+ public int getVersion() {
+ return Coprocessor.VERSION;
+ }
+
+ /** @return the HBase release */
+ @Override
+ public String getHBaseVersion() {
+ return VersionInfo.getVersion();
+ }
+
+ /**
+ * 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 HTableInterface getTable(byte[] tableName) throws IOException {
+ return new HTableWrapper(tableName);
+ }
+
+ @Override
+ public void complete() {
+ complete.set(true);
+ }
+
+ @Override
+ public void bypass() {
+ bypass.set(true);
+ }
+ }}
Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java?rev=1051639&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java (added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterCoprocessorEnvironment.java Tue Dec 21 20:39:26 2010
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * 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.master.MasterServices;
+
+public interface MasterCoprocessorEnvironment extends CoprocessorEnvironment {
+ /** @return reference to the HMaster services */
+ MasterServices getMasterServices();
+}
Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java?rev=1051639&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java (added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java Tue Dec 21 20:39:26 2010
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * 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.*;
+
+import java.io.IOException;
+
+/**
+ * Defines coprocessor hooks for interacting with operations on the
+ * {@link org.apache.hadoop.hbase.master.HMaster} process.
+ */
+public interface MasterObserver extends Coprocessor {
+
+ /**
+ * Called before a new table is created by
+ * {@link org.apache.hadoop.hbase.master.HMaster}.
+ */
+ void preCreateTable(MasterCoprocessorEnvironment env,
+ HTableDescriptor desc, byte[][] splitKeys) throws IOException;
+
+ /**
+ * Called after the initial table regions have been created.
+ * @param env the environment to interact with the framework and master
+ * @param regions the initial regions created for the table
+ * @param sync whether the client call is waiting for region assignment to
+ * complete before returning
+ * @throws IOException
+ */
+ void postCreateTable(MasterCoprocessorEnvironment env,
+ HRegionInfo[] regions, boolean sync) throws IOException;
+
+ /**
+ * Called before {@link org.apache.hadoop.hbase.master.HMaster} deletes a
+ * table
+ */
+ void preDeleteTable(MasterCoprocessorEnvironment env, byte[] tableName)
+ throws IOException;
+
+ /**
+ * Called after the table has been deleted, before returning to the client.
+ */
+ void postDeleteTable(MasterCoprocessorEnvironment env, byte[] tableName)
+ throws IOException;
+
+ /**
+ * Called prior to modifying a table's properties.
+ */
+ void preModifyTable(MasterCoprocessorEnvironment env, final byte[] tableName,
+ HTableDescriptor htd) throws IOException;
+
+ /**
+ * Called after {@link org.apache.hadoop.hbase.master.HMaster} has modified
+ * the table's properties in all the table regions.
+ */
+ void postModifyTable(MasterCoprocessorEnvironment env, final byte[] tableName,
+ HTableDescriptor htd) throws IOException;
+
+ /**
+ * Called prior to adding a new column family to the table.
+ */
+ void preAddColumn(MasterCoprocessorEnvironment env, byte[] tableName,
+ HColumnDescriptor column) throws IOException;
+
+ /**
+ * Called after the new column family has been created.
+ */
+ void postAddColumn(MasterCoprocessorEnvironment env, byte[] tableName,
+ HColumnDescriptor column) throws IOException;
+
+ /**
+ * Called prior to modifying a column family's attributes.
+ */
+ void preModifyColumn(MasterCoprocessorEnvironment env,
+ byte [] tableName, HColumnDescriptor descriptor) throws IOException;
+
+ /**
+ * Called after the column family has been updated.
+ */
+ void postModifyColumn(MasterCoprocessorEnvironment env, byte[] tableName,
+ HColumnDescriptor descriptor) throws IOException;
+
+ /**
+ * Called prior to deleting the entire column family.
+ */
+ void preDeleteColumn(MasterCoprocessorEnvironment env,
+ final byte [] tableName, final byte[] c) throws IOException;
+
+ /**
+ * Called after the column family has been deleted.
+ */
+ void postDeleteColumn(MasterCoprocessorEnvironment env,
+ final byte [] tableName, final byte[] c) throws IOException;
+
+ /**
+ * Called prior to enabling a table.
+ */
+ void preEnableTable(MasterCoprocessorEnvironment env, final byte[] tableName)
+ throws IOException;
+
+ /**
+ * Called after the table has been enabled.
+ */
+ void postEnableTable(MasterCoprocessorEnvironment env, final byte[] tableName)
+ throws IOException;
+
+ /**
+ * Called prior to disabling a table.
+ */
+ void preDisableTable(MasterCoprocessorEnvironment env, final byte[] tableName)
+ throws IOException;
+
+ /**
+ * Called after the table has been disabled.
+ */
+ void postDisableTable(MasterCoprocessorEnvironment env, final byte[] tableName)
+ throws IOException;
+
+ /**
+ * Called prior to moving a given region from one region server to another.
+ */
+ void preMove(MasterCoprocessorEnvironment env, final HRegionInfo region,
+ final HServerInfo srcServer, final HServerInfo destServer)
+ throws UnknownRegionException;
+
+ /**
+ * Called after the region move has been requested.
+ */
+ void postMove(MasterCoprocessorEnvironment env, final HRegionInfo region,
+ final HServerInfo srcServer, final HServerInfo destServer)
+ throws UnknownRegionException;
+
+ /**
+ * Called prior to assigning a specific region.
+ */
+ void preAssign(MasterCoprocessorEnvironment env, final byte [] regionName,
+ final boolean force) throws IOException;
+
+ /**
+ * Called after the region assignment has been requested.
+ */
+ void postAssign(MasterCoprocessorEnvironment env, final HRegionInfo regionInfo)
+ throws IOException;
+
+ /**
+ * Called prior to unassigning a given region.
+ */
+ void preUnassign(MasterCoprocessorEnvironment env, final byte [] regionName,
+ final boolean force) throws IOException;
+
+ /**
+ * Called after the region unassignment has been requested.
+ */
+ void postUnassign(MasterCoprocessorEnvironment env,
+ final HRegionInfo regionInfo, final boolean force) throws IOException;
+
+ /**
+ * Called prior to requesting rebalancing of the cluster regions, though after
+ * the initial checks for regions in transition and the balance switch flag.
+ */
+ void preBalance(MasterCoprocessorEnvironment env) throws IOException;
+
+ /**
+ * Called after the balancing plan has been submitted.
+ */
+ void postBalance(MasterCoprocessorEnvironment env) throws IOException;
+
+ /**
+ * Called prior to modifying the flag used to enable/disable region balancing.
+ * @param env the coprocessor instance's environment
+ * @param newValue the new flag value submitted in the call
+ */
+ boolean preBalanceSwitch(MasterCoprocessorEnvironment env,
+ final boolean newValue) throws IOException;
+
+ /**
+ * Called after the flag to enable/disable balancing has changed.
+ * @param env the coprocessor instance's environment
+ * @param oldValue the previously set balanceSwitch value
+ * @param newValue the newly set balanceSwitch value
+ */
+ void postBalanceSwitch(MasterCoprocessorEnvironment env,
+ final boolean oldValue, final boolean newValue) throws IOException;
+
+ /**
+ * Called prior to shutting down the full HBase cluster, including this
+ * {@link org.apache.hadoop.hbase.master.HMaster} process.
+ */
+ void preShutdown(MasterCoprocessorEnvironment env) throws IOException;
+
+
+ /**
+ * Called immediatly prior to stopping this
+ * {@link org.apache.hadoop.hbase.master.HMaster} process.
+ */
+ void preStopMaster(MasterCoprocessorEnvironment env) throws IOException;
+}
Added: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java?rev=1051639&view=auto
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java (added)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionCoprocessorEnvironment.java Tue Dec 21 20:39:26 2010
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * 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.regionserver.HRegion;
+import org.apache.hadoop.hbase.regionserver.RegionServerServices;
+
+public interface RegionCoprocessorEnvironment extends CoprocessorEnvironment {
+ /** @return the region associated with this coprocessor */
+ public HRegion getRegion();
+
+ /** @return reference to the region server services */
+ public RegionServerServices getRegionServerServices();
+
+}
Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java?rev=1051639&r1=1051638&r2=1051639&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java Tue Dec 21 20:39:26 2010
@@ -42,25 +42,25 @@ public interface RegionObserver extends
* Called before the region is reported as open to the master.
* @param e the environment provided by the region server
*/
- public void preOpen(final CoprocessorEnvironment e);
+ public void preOpen(final RegionCoprocessorEnvironment e);
/**
* Called after the region is reported as open to the master.
* @param e the environment provided by the region server
*/
- public void postOpen(final CoprocessorEnvironment e);
+ public void postOpen(final RegionCoprocessorEnvironment e);
/**
* Called before the memstore is flushed to disk.
* @param e the environment provided by the region server
*/
- public void preFlush(final CoprocessorEnvironment e);
+ public void preFlush(final RegionCoprocessorEnvironment e);
/**
* Called after the memstore is flushed to disk.
* @param e the environment provided by the region server
*/
- public void postFlush(final CoprocessorEnvironment e);
+ public void postFlush(final RegionCoprocessorEnvironment e);
/**
* Called before compaction.
@@ -68,7 +68,7 @@ public interface RegionObserver extends
* @param willSplit true if compaction will result in a split, false
* otherwise
*/
- public void preCompact(final CoprocessorEnvironment e,
+ public void preCompact(final RegionCoprocessorEnvironment e,
final boolean willSplit);
/**
@@ -77,7 +77,7 @@ public interface RegionObserver extends
* @param willSplit true if compaction will result in a split, false
* otherwise
*/
- public void postCompact(final CoprocessorEnvironment e,
+ public void postCompact(final RegionCoprocessorEnvironment e,
final boolean willSplit);
/**
@@ -85,7 +85,7 @@ public interface RegionObserver extends
* @param e the environment provided by the region server
* (e.getRegion() returns the parent region)
*/
- public void preSplit(final CoprocessorEnvironment e);
+ public void preSplit(final RegionCoprocessorEnvironment e);
/**
* Called after the region is split.
@@ -94,7 +94,7 @@ public interface RegionObserver extends
* @param l the left daughter region
* @param r the right daughter region
*/
- public void postSplit(final CoprocessorEnvironment e, final HRegion l,
+ public void postSplit(final RegionCoprocessorEnvironment e, final HRegion l,
final HRegion r);
/**
@@ -102,14 +102,16 @@ public interface RegionObserver extends
* @param e the environment provided by the region server
* @param abortRequested true if the region server is aborting
*/
- public void preClose(final CoprocessorEnvironment e, boolean abortRequested);
+ public void preClose(final RegionCoprocessorEnvironment e,
+ boolean abortRequested);
/**
* Called after the region is reported as closed to the master.
* @param e the environment provided by the region server
* @param abortRequested true if the region server is aborting
*/
- public void postClose(final CoprocessorEnvironment e, boolean abortRequested);
+ public void postClose(final RegionCoprocessorEnvironment e,
+ boolean abortRequested);
/**
* Called before a client makes a GetClosestRowBefore request.
@@ -126,7 +128,7 @@ public interface RegionObserver extends
* is not bypassed.
* @throws IOException if an error occurred on the coprocessor
*/
- public void preGetClosestRowBefore(final CoprocessorEnvironment e,
+ public void preGetClosestRowBefore(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final Result result)
throws IOException;
@@ -141,7 +143,7 @@ public interface RegionObserver extends
* @param result the result to return to the client, modify as necessary
* @throws IOException if an error occurred on the coprocessor
*/
- public void postGetClosestRowBefore(final CoprocessorEnvironment e,
+ public void postGetClosestRowBefore(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final Result result)
throws IOException;
@@ -159,7 +161,7 @@ public interface RegionObserver extends
* is not bypassed.
* @throws IOException if an error occurred on the coprocessor
*/
- public void preGet(final CoprocessorEnvironment e, final Get get,
+ public void preGet(final RegionCoprocessorEnvironment e, final Get get,
final List<KeyValue> result)
throws IOException;
@@ -173,7 +175,7 @@ public interface RegionObserver extends
* @param result the result to return to the client, modify as necessary
* @throws IOException if an error occurred on the coprocessor
*/
- public void postGet(final CoprocessorEnvironment e, final Get get,
+ public void postGet(final RegionCoprocessorEnvironment e, final Get get,
final List<KeyValue> result)
throws IOException;
@@ -190,7 +192,7 @@ public interface RegionObserver extends
* @return the value to return to the client if bypassing default processing
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean preExists(final CoprocessorEnvironment e, final Get get,
+ public boolean preExists(final RegionCoprocessorEnvironment e, final Get get,
final boolean exists)
throws IOException;
@@ -205,7 +207,7 @@ public interface RegionObserver extends
* @return the result to return to the client
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean postExists(final CoprocessorEnvironment e, final Get get,
+ public boolean postExists(final RegionCoprocessorEnvironment e, final Get get,
final boolean exists)
throws IOException;
@@ -221,7 +223,7 @@ public interface RegionObserver extends
* @param writeToWAL true if the change should be written to the WAL
* @throws IOException if an error occurred on the coprocessor
*/
- public void prePut(final CoprocessorEnvironment e, final Map<byte[],
+ public void prePut(final RegionCoprocessorEnvironment e, final Map<byte[],
List<KeyValue>> familyMap, final boolean writeToWAL)
throws IOException;
@@ -235,7 +237,7 @@ public interface RegionObserver extends
* @param writeToWAL true if the change should be written to the WAL
* @throws IOException if an error occurred on the coprocessor
*/
- public void postPut(final CoprocessorEnvironment e, final Map<byte[],
+ public void postPut(final RegionCoprocessorEnvironment e, final Map<byte[],
List<KeyValue>> familyMap, final boolean writeToWAL)
throws IOException;
@@ -251,7 +253,7 @@ public interface RegionObserver extends
* @param writeToWAL true if the change should be written to the WAL
* @throws IOException if an error occurred on the coprocessor
*/
- public void preDelete(final CoprocessorEnvironment e, final Map<byte[],
+ public void preDelete(final RegionCoprocessorEnvironment e, final Map<byte[],
List<KeyValue>> familyMap, final boolean writeToWAL)
throws IOException;
@@ -265,7 +267,7 @@ public interface RegionObserver extends
* @param writeToWAL true if the change should be written to the WAL
* @throws IOException if an error occurred on the coprocessor
*/
- public void postDelete(final CoprocessorEnvironment e,
+ public void postDelete(final RegionCoprocessorEnvironment e,
final Map<byte[], List<KeyValue>> familyMap, final boolean writeToWAL)
throws IOException;
@@ -287,7 +289,7 @@ public interface RegionObserver extends
* processing
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean preCheckAndPut(final CoprocessorEnvironment e,
+ public boolean preCheckAndPut(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Put put, final boolean result)
throws IOException;
@@ -307,7 +309,7 @@ public interface RegionObserver extends
* @return the possibly transformed return value to return to client
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean postCheckAndPut(final CoprocessorEnvironment e,
+ public boolean postCheckAndPut(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Put put, final boolean result)
throws IOException;
@@ -329,7 +331,7 @@ public interface RegionObserver extends
* @return the value to return to client if bypassing default processing
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean preCheckAndDelete(final CoprocessorEnvironment e,
+ public boolean preCheckAndDelete(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Delete delete, final boolean result)
throws IOException;
@@ -349,7 +351,7 @@ public interface RegionObserver extends
* @return the possibly transformed returned value to return to client
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean postCheckAndDelete(final CoprocessorEnvironment e,
+ public boolean postCheckAndDelete(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final byte [] value, final Delete delete, final boolean result)
throws IOException;
@@ -370,7 +372,7 @@ public interface RegionObserver extends
* @return value to return to the client if bypassing default processing
* @throws IOException if an error occurred on the coprocessor
*/
- public long preIncrementColumnValue(final CoprocessorEnvironment e,
+ public long preIncrementColumnValue(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final long amount, final boolean writeToWAL)
throws IOException;
@@ -390,7 +392,7 @@ public interface RegionObserver extends
* @return the result to return to the client
* @throws IOException if an error occurred on the coprocessor
*/
- public long postIncrementColumnValue(final CoprocessorEnvironment e,
+ public long postIncrementColumnValue(final RegionCoprocessorEnvironment e,
final byte [] row, final byte [] family, final byte [] qualifier,
final long amount, final boolean writeToWAL, final long result)
throws IOException;
@@ -407,10 +409,9 @@ public interface RegionObserver extends
* @param result The result to return to the client if default processing
* is bypassed. Can be modified. Will not be used if default processing
* is not bypassed.
- * @param writeToWAL true if the change should be written to the WAL
* @throws IOException if an error occurred on the coprocessor
*/
- public void preIncrement(final CoprocessorEnvironment e,
+ public void preIncrement(final RegionCoprocessorEnvironment e,
final Increment increment, final Result result)
throws IOException;
@@ -421,11 +422,10 @@ public interface RegionObserver extends
* coprocessors
* @param e the environment provided by the region server
* @param increment increment object
- * @param writeToWAL true if the change should be written to the WAL
* @param result the result returned by increment, can be modified
* @throws IOException if an error occurred on the coprocessor
*/
- public void postIncrement(final CoprocessorEnvironment e,
+ public void postIncrement(final RegionCoprocessorEnvironment e,
final Increment increment, final Result result)
throws IOException;
@@ -443,7 +443,7 @@ public interface RegionObserver extends
* overriding default behavior, null otherwise
* @throws IOException if an error occurred on the coprocessor
*/
- public InternalScanner preScannerOpen(final CoprocessorEnvironment e,
+ public InternalScanner preScannerOpen(final RegionCoprocessorEnvironment e,
final Scan scan, final InternalScanner s)
throws IOException;
@@ -458,7 +458,7 @@ public interface RegionObserver extends
* @return the scanner instance to use
* @throws IOException if an error occurred on the coprocessor
*/
- public InternalScanner postScannerOpen(final CoprocessorEnvironment e,
+ public InternalScanner postScannerOpen(final RegionCoprocessorEnvironment e,
final Scan scan, final InternalScanner s)
throws IOException;
@@ -479,7 +479,7 @@ public interface RegionObserver extends
* @return 'has more' indication that should be sent to client
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean preScannerNext(final CoprocessorEnvironment e,
+ public boolean preScannerNext(final RegionCoprocessorEnvironment e,
final InternalScanner s, final List<KeyValue> result,
final int limit, final boolean hasNext)
throws IOException;
@@ -497,7 +497,7 @@ public interface RegionObserver extends
* @return 'has more' indication that should be sent to client
* @throws IOException if an error occurred on the coprocessor
*/
- public boolean postScannerNext(final CoprocessorEnvironment e,
+ public boolean postScannerNext(final RegionCoprocessorEnvironment e,
final InternalScanner s, final List<KeyValue> result, final int limit,
final boolean hasNext)
throws IOException;
@@ -513,7 +513,7 @@ public interface RegionObserver extends
* @param s the scanner
* @throws IOException if an error occurred on the coprocessor
*/
- public void preScannerClose(final CoprocessorEnvironment e,
+ public void preScannerClose(final RegionCoprocessorEnvironment e,
final InternalScanner s)
throws IOException;
@@ -526,7 +526,7 @@ public interface RegionObserver extends
* @param s the scanner
* @throws IOException if an error occurred on the coprocessor
*/
- public void postScannerClose(final CoprocessorEnvironment e,
+ public void postScannerClose(final RegionCoprocessorEnvironment e,
final InternalScanner s)
throws IOException;
}
Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java?rev=1051639&r1=1051638&r2=1051639&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/coprocessor/package-info.java Tue Dec 21 20:39:26 2010
@@ -286,7 +286,7 @@ or by <code>HTableDescriptor</code> for
opened regions.)
<h3>Load from configuration</h3>
Whenever a region is opened, it will read coprocessor class names from
-<code>hbase.coprocessor.default.classes</code> from <code>Configuration</code>.
+<code>hbase.coprocessor.region.classes</code> from <code>Configuration</code>.
Coprocessor framework will automatically load the configured classes as
default coprocessors. The classes must be included in the classpath already.
@@ -294,7 +294,7 @@ default coprocessors. The classes must b
<div style="background-color: #cccccc; padding: 2px">
<blockquote><pre>
<property>
- <name>hbase.coprocessor.default.classes</name>
+ <name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AccessControllCoprocessor, org.apache.hadoop.hbase.coprocessor.ColumnAggregationProtocol</value>
<description>A comma-separated list of Coprocessors that are loaded by
default. For any override coprocessor method from RegionObservor or
Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java?rev=1051639&r1=1051638&r2=1051639&view=diff
==============================================================================
--- hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (original)
+++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/master/HMaster.java Tue Dec 21 20:39:26 2010
@@ -170,6 +170,8 @@ implements HMasterInterface, HMasterRegi
private Thread catalogJanitorChore;
private LogCleaner logCleaner;
+ private MasterCoprocessorHost cpHost;
+
/**
* Initializes the HMaster. The steps are as follows:
* <p>
@@ -369,6 +371,9 @@ implements HMasterInterface, HMasterRegi
Long.toHexString(this.zooKeeper.getZooKeeper().getSessionId()) +
", cluster-up flag was=" + wasUp);
+ // initialize master side coprocessors before we start handling requests
+ this.cpHost = new MasterCoprocessorHost(this, this.conf);
+
// start up all service threads.
startServiceThreads();
@@ -675,6 +680,19 @@ implements HMasterInterface, HMasterRegi
this.serverManager.getDeadServers());
return false;
}
+
+ if (this.cpHost != null) {
+ try {
+ if (this.cpHost.preBalance()) {
+ LOG.debug("Coprocessor bypassing balancer request");
+ return false;
+ }
+ } catch (IOException ioe) {
+ LOG.error("Error invoking master coprocessor preBalance()", ioe);
+ return false;
+ }
+ }
+
Map<HServerInfo, List<HRegionInfo>> assignments =
this.assignmentManager.getAssignments();
// Returned Map from AM does not include mention of servers w/o assignments.
@@ -692,6 +710,14 @@ implements HMasterInterface, HMasterRegi
this.assignmentManager.balance(plan);
}
}
+ if (this.cpHost != null) {
+ try {
+ this.cpHost.postBalance();
+ } catch (IOException ioe) {
+ // balancing already succeeded so don't change the result
+ LOG.error("Error invoking master coprocessor postBalance()", ioe);
+ }
+ }
}
return true;
}
@@ -699,8 +725,19 @@ implements HMasterInterface, HMasterRegi
@Override
public boolean balanceSwitch(final boolean b) {
boolean oldValue = this.balanceSwitch;
- this.balanceSwitch = b;
- LOG.info("Balance=" + b);
+ boolean newValue = b;
+ try {
+ if (this.cpHost != null) {
+ newValue = this.cpHost.preBalanceSwitch(newValue);
+ }
+ this.balanceSwitch = newValue;
+ LOG.info("Balance=" + newValue);
+ if (this.cpHost != null) {
+ this.cpHost.postBalanceSwitch(oldValue, newValue);
+ }
+ } catch (IOException ioe) {
+ LOG.warn("Error flipping balance switch", ioe);
+ }
return oldValue;
}
@@ -721,8 +758,15 @@ implements HMasterInterface, HMasterRegi
this.assignmentManager.unassign(hri);
} else {
dest = this.serverManager.getServerInfo(new String(destServerName));
+
+ if (this.cpHost != null) {
+ this.cpHost.preMove(p.getFirst(), p.getSecond(), dest);
+ }
RegionPlan rp = new RegionPlan(p.getFirst(), p.getSecond(), dest);
this.assignmentManager.balance(rp);
+ if (this.cpHost != null) {
+ this.cpHost.postMove(p.getFirst(), p.getSecond(), dest);
+ }
}
}
@@ -737,6 +781,9 @@ implements HMasterInterface, HMasterRegi
if (!isMasterRunning()) {
throw new MasterNotRunningException();
}
+ if (cpHost != null) {
+ cpHost.preCreateTable(desc, splitKeys);
+ }
HRegionInfo [] newRegions = null;
if(splitKeys == null || splitKeys.length == 0) {
newRegions = new HRegionInfo [] { new HRegionInfo(desc, null, null) };
@@ -810,6 +857,10 @@ implements HMasterInterface, HMasterRegi
}
}
}
+
+ if (cpHost != null) {
+ cpHost.postCreateTable(newRegions, sync);
+ }
}
private static boolean isCatalogTable(final byte [] tableName) {
@@ -818,32 +869,68 @@ implements HMasterInterface, HMasterRegi
}
public void deleteTable(final byte [] tableName) throws IOException {
+ if (cpHost != null) {
+ cpHost.preDeleteTable(tableName);
+ }
this.executorService.submit(new DeleteTableHandler(tableName, this, this));
+ if (cpHost != null) {
+ cpHost.postDeleteTable(tableName);
+ }
}
public void addColumn(byte [] tableName, HColumnDescriptor column)
throws IOException {
+ if (cpHost != null) {
+ cpHost.preAddColumn(tableName, column);
+ }
new TableAddFamilyHandler(tableName, column, this, this).process();
+ if (cpHost != null) {
+ cpHost.postAddColumn(tableName, column);
+ }
}
public void modifyColumn(byte [] tableName, HColumnDescriptor descriptor)
throws IOException {
+ if (cpHost != null) {
+ cpHost.preModifyColumn(tableName, descriptor);
+ }
new TableModifyFamilyHandler(tableName, descriptor, this, this).process();
+ if (cpHost != null) {
+ cpHost.postModifyColumn(tableName, descriptor);
+ }
}
public void deleteColumn(final byte [] tableName, final byte [] c)
throws IOException {
+ if (cpHost != null) {
+ cpHost.preDeleteColumn(tableName, c);
+ }
new TableDeleteFamilyHandler(tableName, c, this, this).process();
+ if (cpHost != null) {
+ cpHost.postDeleteColumn(tableName, c);
+ }
}
public void enableTable(final byte [] tableName) throws IOException {
+ if (cpHost != null) {
+ cpHost.preEnableTable(tableName);
+ }
this.executorService.submit(new EnableTableHandler(this, tableName,
catalogTracker, assignmentManager));
+ if (cpHost != null) {
+ cpHost.postEnableTable(tableName);
+ }
}
public void disableTable(final byte [] tableName) throws IOException {
+ if (cpHost != null) {
+ cpHost.preDisableTable(tableName);
+ }
this.executorService.submit(new DisableTableHandler(this, tableName,
catalogTracker, assignmentManager));
+ if (cpHost != null) {
+ cpHost.postDisableTable(tableName);
+ }
}
/**
@@ -886,7 +973,13 @@ implements HMasterInterface, HMasterRegi
@Override
public void modifyTable(final byte[] tableName, HTableDescriptor htd)
throws IOException {
+ if (cpHost != null) {
+ cpHost.preModifyTable(tableName, htd);
+ }
this.executorService.submit(new ModifyTableHandler(tableName, htd, this, this));
+ if (cpHost != null) {
+ cpHost.postModifyTable(tableName, htd);
+ }
}
@Override
@@ -935,6 +1028,10 @@ implements HMasterInterface, HMasterRegi
return zooKeeper;
}
+ public MasterCoprocessorHost getCoprocessorHost() {
+ return cpHost;
+ }
+
@Override
public String getServerName() {
return address.toString();
@@ -952,6 +1049,13 @@ implements HMasterInterface, HMasterRegi
@Override
public void shutdown() {
+ if (cpHost != null) {
+ try {
+ cpHost.preShutdown();
+ } catch (IOException ioe) {
+ LOG.error("Error call master coprocessor preShutdown()", ioe);
+ }
+ }
this.serverManager.shutdownCluster();
try {
this.clusterStatusTracker.setClusterDown();
@@ -962,6 +1066,13 @@ implements HMasterInterface, HMasterRegi
@Override
public void stopMaster() {
+ if (cpHost != null) {
+ try {
+ cpHost.preStopMaster();
+ } catch (IOException ioe) {
+ LOG.error("Error call master coprocessor preStopMaster()", ioe);
+ }
+ }
stop("Stopped by " + Thread.currentThread().getName());
}
@@ -1008,10 +1119,18 @@ implements HMasterInterface, HMasterRegi
@Override
public void assign(final byte [] regionName, final boolean force)
throws IOException {
+ if (cpHost != null) {
+ if (cpHost.preAssign(regionName, force)) {
+ return;
+ }
+ }
Pair<HRegionInfo, HServerAddress> pair =
MetaReader.getRegion(this.catalogTracker, regionName);
if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
assignRegion(pair.getFirst());
+ if (cpHost != null) {
+ cpHost.postAssign(pair.getFirst());
+ }
}
public void assignRegion(HRegionInfo hri) {
@@ -1021,12 +1140,20 @@ implements HMasterInterface, HMasterRegi
@Override
public void unassign(final byte [] regionName, final boolean force)
throws IOException {
+ if (cpHost != null) {
+ if (cpHost.preUnassign(regionName, force)) {
+ return;
+ }
+ }
Pair<HRegionInfo, HServerAddress> pair =
MetaReader.getRegion(this.catalogTracker, regionName);
if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
HRegionInfo hri = pair.getFirst();
if (force) this.assignmentManager.clearRegionFromTransition(hri);
this.assignmentManager.unassign(hri, force);
+ if (cpHost != null) {
+ cpHost.postUnassign(hri, force);
+ }
}
/**