Return-Path: Delivered-To: apmail-hbase-commits-archive@www.apache.org Received: (qmail 91912 invoked from network); 24 Mar 2011 06:27:55 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 24 Mar 2011 06:27:55 -0000 Received: (qmail 92398 invoked by uid 500); 24 Mar 2011 06:27:55 -0000 Delivered-To: apmail-hbase-commits-archive@hbase.apache.org Received: (qmail 92365 invoked by uid 500); 24 Mar 2011 06:27:55 -0000 Mailing-List: contact commits-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hbase.apache.org Delivered-To: mailing list commits@hbase.apache.org Received: (qmail 92358 invoked by uid 99); 24 Mar 2011 06:27:54 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Mar 2011 06:27:54 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Mar 2011 06:27:49 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 5F3262388ABB; Thu, 24 Mar 2011 06:27:24 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1084854 - in /hbase/trunk: ./ src/main/java/org/apache/hadoop/hbase/coprocessor/ src/main/java/org/apache/hadoop/hbase/regionserver/ src/test/java/org/apache/hadoop/hbase/coprocessor/ Date: Thu, 24 Mar 2011 06:27:24 -0000 To: commits@hbase.apache.org From: apurtell@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110324062724.5F3262388ABB@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: apurtell Date: Thu Mar 24 06:27:23 2011 New Revision: 1084854 URL: http://svn.apache.org/viewvc?rev=1084854&view=rev Log: HBASE-3583 Coprocessors: scannerNext and scannerClose hooks are called when HRegionInterface#get is invoked 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/RegionObserver.java hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java Modified: hbase/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/hbase/trunk/CHANGES.txt?rev=1084854&r1=1084853&r2=1084854&view=diff ============================================================================== --- hbase/trunk/CHANGES.txt (original) +++ hbase/trunk/CHANGES.txt Thu Mar 24 06:27:23 2011 @@ -46,6 +46,9 @@ Release 0.91.0 - Unreleased HBASE-3532 HRegion#equals is broken (Ted Yu via Stack) HBASE-3697 Admin actions that use MetaReader to iterate regions need to skip offline ones + HBASE-3583 Coprocessors: scannerNext and scannerClose hooks are called + when HRegionInterface#get is invoked (Mingjie Lai via + Andrew Purtell) IMPROVEMENTS HBASE-3290 Max Compaction Size (Nicolas Spiegelberg via Stack) 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=1084854&r1=1084853&r2=1084854&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 Thu Mar 24 06:27:23 2011 @@ -206,14 +206,14 @@ public abstract class BaseRegionObserver @Override public boolean preScannerNext(final RegionCoprocessorEnvironment e, - final InternalScanner s, final List results, + final InternalScanner s, final List results, final int limit, final boolean hasMore) throws IOException { return hasMore; } @Override public boolean postScannerNext(final RegionCoprocessorEnvironment e, - final InternalScanner s, final List results, final int limit, + final InternalScanner s, final List results, final int limit, final boolean hasMore) throws IOException { return hasMore; } 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=1084854&r1=1084853&r2=1084854&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 Thu Mar 24 06:27:23 2011 @@ -492,7 +492,7 @@ public interface RegionObserver extends * @throws IOException if an error occurred on the coprocessor */ public boolean preScannerNext(final RegionCoprocessorEnvironment e, - final InternalScanner s, final List result, + final InternalScanner s, final List result, final int limit, final boolean hasNext) throws IOException; @@ -510,7 +510,7 @@ public interface RegionObserver extends * @throws IOException if an error occurred on the coprocessor */ public boolean postScannerNext(final RegionCoprocessorEnvironment e, - final InternalScanner s, final List result, final int limit, + final InternalScanner s, final List result, final int limit, final boolean hasNext) throws IOException; Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=1084854&r1=1084853&r2=1084854&view=diff ============================================================================== --- hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (original) +++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java Thu Mar 24 06:27:23 2011 @@ -2461,14 +2461,6 @@ public class HRegion implements HeapSize public synchronized boolean next(List outResults, int limit) throws IOException { - if (coprocessorHost != null) { - Boolean result = coprocessorHost.preScannerNext((InternalScanner)this, - outResults, limit); - if (result != null) { - return result.booleanValue(); - } - } - if (this.filterClosed) { throw new UnknownScannerException("Scanner was closed (timed out?) " + "after we renewed it. Could be caused by a very slow scanner " + @@ -2484,11 +2476,6 @@ public class HRegion implements HeapSize boolean returnResult = nextInternal(limit); - if (coprocessorHost != null) { - returnResult = coprocessorHost.postScannerNext((InternalScanner)this, - results, limit, returnResult); - } - outResults.addAll(results); resetFilters(); if (isFilterDone()) { @@ -2596,20 +2583,12 @@ public class HRegion implements HeapSize currentRow, 0, currentRow.length) <= isScan); } - public synchronized void close() throws IOException { - if (coprocessorHost != null) { - if (coprocessorHost.preScannerClose((InternalScanner)this)) { - return; - } - } + public synchronized void close() { if (storeHeap != null) { storeHeap.close(); storeHeap = null; } this.filterClosed = true; - if (coprocessorHost != null) { - coprocessorHost.postScannerClose((InternalScanner)this); - } } } Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java?rev=1084854&r1=1084853&r2=1084854&view=diff ============================================================================== --- hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (original) +++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java Thu Mar 24 06:27:23 2011 @@ -1929,6 +1929,32 @@ public class HRegionServer implements HR List results = new ArrayList(nbRows); long currentScanResultSize = 0; List values = new ArrayList(); + + // Call coprocessor. Get region info from scanner. + HRegion region = null; + if (s instanceof HRegion.RegionScanner) { + HRegion.RegionScanner rs = (HRegion.RegionScanner) s; + region = getRegion(rs.getRegionName().getRegionName()); + } else { + throw new IOException("InternalScanner implementation is expected " + + "to be HRegion.RegionScanner."); + } + if (region != null && region.getCoprocessorHost() != null) { + Boolean bypass = region.getCoprocessorHost().preScannerNext(s, + results, nbRows); + if (!results.isEmpty()) { + for (Result r : results) { + for (KeyValue kv : r.raw()) { + currentScanResultSize += kv.heapSize(); + } + } + } + if (bypass != null) { + return ((HRegion.RegionScanner) s).isFilterDone() && results.isEmpty() ? null + : results.toArray(new Result[0]); + } + } + for (int i = 0; i < nbRows && currentScanResultSize < maxScannerResultSize; i++) { requestCount.incrementAndGet(); @@ -1945,6 +1971,12 @@ public class HRegionServer implements HR } values.clear(); } + + // coprocessor postNext hook + if (region != null && region.getCoprocessorHost() != null) { + region.getCoprocessorHost().postScannerNext(s, results, nbRows, true); + } + // Below is an ugly hack where we cast the InternalScanner to be a // HRegion.RegionScanner. The alternative is to change InternalScanner // interface but its used everywhere whereas we just need a bit of info @@ -1967,10 +1999,33 @@ public class HRegionServer implements HR checkOpen(); requestCount.incrementAndGet(); String scannerName = String.valueOf(scannerId); - InternalScanner s = scanners.remove(scannerName); + InternalScanner s = scanners.get(scannerName); + + HRegion region = null; + if (s != null) { + // call coprocessor. + if (s instanceof HRegion.RegionScanner) { + HRegion.RegionScanner rs = (HRegion.RegionScanner) s; + region = getRegion(rs.getRegionName().getRegionName()); + } else { + throw new IOException("InternalScanner implementation is expected " + + "to be HRegion.RegionScanner."); + } + if (region != null && region.getCoprocessorHost() != null) { + if (region.getCoprocessorHost().preScannerClose(s)) { + return; // bypass + } + } + } + + s = scanners.remove(scannerName); if (s != null) { s.close(); this.leases.cancelLease(scannerName); + + if (region != null && region.getCoprocessorHost() != null) { + region.getCoprocessorHost().postScannerClose(s); + } } } catch (Throwable t) { throw convertThrowableToIOE(cleanup(t)); Modified: hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java URL: http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java?rev=1084854&r1=1084853&r2=1084854&view=diff ============================================================================== --- hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java (original) +++ hbase/trunk/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java Thu Mar 24 06:27:23 2011 @@ -911,7 +911,7 @@ public class RegionCoprocessorHost * @exception IOException Exception */ public Boolean preScannerNext(final InternalScanner s, - final List results, int limit) throws IOException { + final List results, int limit) throws IOException { try { boolean bypass = false; boolean hasNext = false; @@ -941,7 +941,7 @@ public class RegionCoprocessorHost * @exception IOException Exception */ public boolean postScannerNext(final InternalScanner s, - final List results, final int limit, boolean hasMore) + final List results, final int limit, boolean hasMore) throws IOException { try { coprocessorLock.readLock().lock(); Modified: hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java URL: http://svn.apache.org/viewvc/hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java?rev=1084854&r1=1084853&r2=1084854&view=diff ============================================================================== --- hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java (original) +++ hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java Thu Mar 24 06:27:23 2011 @@ -35,6 +35,7 @@ import org.apache.hadoop.hbase.client.Ge import org.apache.hadoop.hbase.client.Increment; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.regionserver.HRegion; +import org.apache.hadoop.hbase.regionserver.InternalScanner; import org.apache.hadoop.hbase.util.Bytes; /** @@ -68,6 +69,10 @@ public class SimpleRegionObserver extend boolean hadPostIncrement = false; boolean hadPreWALRestored = false; boolean hadPostWALRestored = false; + boolean hadPreScannerNext = false; + boolean hadPostScannerNext = false; + boolean hadPreScannerClose = false; + boolean hadPostScannerClose = false; @Override public void preOpen(RegionCoprocessorEnvironment e) { @@ -135,6 +140,35 @@ public class SimpleRegionObserver extend hadPostCompact = true; } + + @Override + public boolean preScannerNext(final RegionCoprocessorEnvironment e, + final InternalScanner s, final List results, + final int limit, final boolean hasMore) throws IOException { + hadPreScannerNext = true; + return hasMore; + } + + @Override + public boolean postScannerNext(final RegionCoprocessorEnvironment e, + final InternalScanner s, final List results, final int limit, + final boolean hasMore) throws IOException { + hadPostScannerNext = true; + return hasMore; + } + + @Override + public void preScannerClose(final RegionCoprocessorEnvironment e, + final InternalScanner s) throws IOException { + hadPreScannerClose = true; + } + + @Override + public void postScannerClose(final RegionCoprocessorEnvironment e, + final InternalScanner s) throws IOException { + hadPostScannerClose = true; + } + public boolean wasCompacted() { return hadPreCompact && hadPostCompact; } @@ -146,10 +180,7 @@ public class SimpleRegionObserver extend assertNotNull(e.getRegion()); assertNotNull(get); assertNotNull(results); - if (Arrays.equals(e.getRegion().getTableDesc().getName(), - TestRegionObserverInterface.TEST_TABLE)) { - hadPreGet = true; - } + hadPreGet = true; } @Override @@ -178,8 +209,8 @@ public class SimpleRegionObserver extend assertTrue(foundA); assertTrue(foundB); assertTrue(foundC); - hadPostGet = true; } + hadPostGet = true; } @Override @@ -205,8 +236,8 @@ public class SimpleRegionObserver extend assertNotNull(kvs.get(0)); assertTrue(Bytes.equals(kvs.get(0).getQualifier(), TestRegionObserverInterface.C)); - hadPrePut = true; } + hadPrePut = true; } @Override @@ -232,8 +263,8 @@ public class SimpleRegionObserver extend assertNotNull(kvs.get(0)); assertTrue(Bytes.equals(kvs.get(0).getQualifier(), TestRegionObserverInterface.C)); - hadPostPut = true; } + hadPostPut = true; } @Override @@ -242,8 +273,7 @@ public class SimpleRegionObserver extend assertNotNull(e); assertNotNull(e.getRegion()); assertNotNull(familyMap); - if (beforeDelete && e.getRegion().getTableDesc().getName().equals( - TestRegionObserverInterface.TEST_TABLE)) { + if (beforeDelete) { hadPreDeleted = true; } } @@ -254,11 +284,8 @@ public class SimpleRegionObserver extend assertNotNull(e); assertNotNull(e.getRegion()); assertNotNull(familyMap); - if (Arrays.equals(e.getRegion().getTableDesc().getName(), - TestRegionObserverInterface.TEST_TABLE)) { - beforeDelete = false; - hadPostDeleted = true; - } + beforeDelete = false; + hadPostDeleted = true; } @Override @@ -269,8 +296,7 @@ public class SimpleRegionObserver extend assertNotNull(e.getRegion()); assertNotNull(row); assertNotNull(result); - if (beforeDelete && e.getRegion().getTableDesc().getName().equals( - TestRegionObserverInterface.TEST_TABLE)) { + if (beforeDelete) { hadPreGetClosestRowBefore = true; } } @@ -283,63 +309,59 @@ public class SimpleRegionObserver extend assertNotNull(e.getRegion()); assertNotNull(row); assertNotNull(result); - if (Arrays.equals(e.getRegion().getTableDesc().getName(), - TestRegionObserverInterface.TEST_TABLE)) { - hadPostGetClosestRowBefore = true; - } + hadPostGetClosestRowBefore = true; } @Override public void preIncrement(final RegionCoprocessorEnvironment e, final Increment increment, final Result result) throws IOException { - if (Arrays.equals(e.getRegion().getTableDesc().getName(), - TestRegionObserverInterface.TEST_TABLE_2)) { - hadPreIncrement = true; - } + hadPreIncrement = true; } @Override public void postIncrement(final RegionCoprocessorEnvironment e, final Increment increment, final Result result) throws IOException { - if (Arrays.equals(e.getRegion().getTableDesc().getName(), - TestRegionObserverInterface.TEST_TABLE_2)) { - hadPostIncrement = true; - } + hadPostIncrement = true; } - boolean hadPreGet() { + public boolean hadPreGet() { return hadPreGet; } - boolean hadPostGet() { + public boolean hadPostGet() { return hadPostGet; } - boolean hadPrePut() { + public boolean hadPrePut() { return hadPrePut; } - boolean hadPostPut() { + public boolean hadPostPut() { return hadPostPut; } - - boolean hadDelete() { + public boolean hadDelete() { return !beforeDelete; } - boolean hadPreIncrement() { + public boolean hadPreIncrement() { return hadPreIncrement; } - boolean hadPostIncrement() { + public boolean hadPostIncrement() { return hadPostIncrement; } - boolean hadPreWALRestored() { + public boolean hadPreWALRestored() { return hadPreWALRestored; } - boolean hadPostWALRestored() { + public boolean hadPostWALRestored() { return hadPostWALRestored; } + public boolean wasScannerNextCalled() { + return hadPreScannerNext && hadPostScannerNext; + } + public boolean wasScannerCloseCalled() { + return hadPreScannerClose && hadPostScannerClose; + } } Modified: hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java URL: http://svn.apache.org/viewvc/hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java?rev=1084854&r1=1084853&r2=1084854&view=diff ============================================================================== --- hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java (original) +++ hbase/trunk/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java Thu Mar 24 06:27:23 2011 @@ -21,6 +21,7 @@ package org.apache.hadoop.hbase.coprocessor; import java.io.IOException; +import java.lang.reflect.Method; import java.util.Arrays; import org.apache.commons.logging.Log; @@ -32,11 +33,7 @@ import org.apache.hadoop.hbase.HColumnDe import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.MiniHBaseCluster; -import org.apache.hadoop.hbase.client.Delete; -import org.apache.hadoop.hbase.client.Get; -import org.apache.hadoop.hbase.client.HTable; -import org.apache.hadoop.hbase.client.Increment; -import org.apache.hadoop.hbase.client.Put; +import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.coprocessor.Coprocessor.Priority; import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; import org.apache.hadoop.hbase.regionserver.HRegion; @@ -47,6 +44,8 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import javax.el.MethodNotFoundException; + import static org.junit.Assert.*; public class TestRegionObserverInterface { @@ -54,16 +53,10 @@ public class TestRegionObserverInterface static final String DIR = "test/build/data/TestRegionObserver/"; public static final byte[] TEST_TABLE = Bytes.toBytes("TestTable"); - public static final byte[] TEST_TABLE_2 = Bytes.toBytes("TestTable2"); - public static final byte[] TEST_FAMILY = Bytes.toBytes("TestFamily"); - public static final byte[] TEST_QUALIFIER = Bytes.toBytes("TestQualifier"); - public final static byte[] A = Bytes.toBytes("a"); public final static byte[] B = Bytes.toBytes("b"); public final static byte[] C = Bytes.toBytes("c"); public final static byte[] ROW = Bytes.toBytes("testrow"); - public final static byte[] ROW1 = Bytes.toBytes("testrow1"); - public final static byte[] ROW2 = Bytes.toBytes("testrow2"); private static final int ROWSIZE = 20; private static byte [][] ROWS = makeN(ROW, ROWSIZE); @@ -80,17 +73,6 @@ public class TestRegionObserverInterface util.startMiniCluster(2); cluster = util.getMiniHBaseCluster(); - - HTable table = util.createTable(TEST_TABLE_2, TEST_FAMILY); - - for(int i = 0; i < ROWSIZE; i++) { - Put put = new Put(ROWS[i]); - put.add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(i)); - table.put(put); - } - - // sleep here is an ugly hack to allow region transitions to finish - Thread.sleep(5000); } @AfterClass @@ -98,87 +80,157 @@ public class TestRegionObserverInterface util.shutdownMiniCluster(); } - HRegion initHRegion (byte [] tableName, String callingMethod, - Configuration conf, Class implClass, byte [] ... families) - throws IOException{ - HTableDescriptor htd = new HTableDescriptor(tableName); - for(byte [] family : families) { - htd.addFamily(new HColumnDescriptor(family)); - } - HRegionInfo info = new HRegionInfo(htd, null, null, false); - Path path = new Path(DIR + callingMethod); - // this following piece is a hack. currently a coprocessorHost - // is secretly loaded at OpenRegionHandler. we don't really - // start a region server here, so just manually create cphost - // and set it to region. - HRegion r = HRegion.createHRegion(info, path, conf); - RegionCoprocessorHost host = new RegionCoprocessorHost(r, null, conf); - r.setCoprocessorHost(host); - host.load(implClass, Priority.USER); - return r; - } - @Test public void testRegionObserver() throws IOException { - byte[] TABLE = Bytes.toBytes(getClass().getName()); - byte[][] FAMILIES = new byte[][] { A, B, C } ; + byte[] tableName = TEST_TABLE; + // recreate table every time in order to reset the status of the + // coproccessor. + HTable table = util.createTable(tableName, new byte[][] {A, B, C}); + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut", + "hadDelete"}, + TEST_TABLE, + new Boolean[] {false, false, false, false, false}); Put put = new Put(ROW); put.add(A, A, A); put.add(B, B, B); put.add(C, C, C); + table.put(put); + + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut", + "hadDelete"}, + TEST_TABLE, + new Boolean[] {false, false, true, true, false} + ); Get get = new Get(ROW); get.addColumn(A, A); get.addColumn(B, B); get.addColumn(C, C); + table.get(get); + + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut", + "hadDelete"}, + TEST_TABLE, + new Boolean[] {true, true, true, true, false} + ); Delete delete = new Delete(ROW); delete.deleteColumn(A, A); delete.deleteColumn(B, B); delete.deleteColumn(C, C); + table.delete(delete); - for (JVMClusterUtil.RegionServerThread t : cluster.getRegionServerThreads()) { - for (HRegionInfo r : t.getRegionServer().getOnlineRegions()) { - if (!Arrays.equals(r.getTableDesc().getName(), TEST_TABLE)) { - continue; - } - RegionCoprocessorHost cph = t.getRegionServer().getOnlineRegion(r.getRegionName()). - getCoprocessorHost(); - Coprocessor c = cph.findCoprocessor(SimpleRegionObserver.class.getName()); - assertNotNull(c); - assertTrue(((SimpleRegionObserver)c).hadPreGet()); - assertTrue(((SimpleRegionObserver)c).hadPostGet()); - assertTrue(((SimpleRegionObserver)c).hadPrePut()); - assertTrue(((SimpleRegionObserver)c).hadPostPut()); - assertTrue(((SimpleRegionObserver)c).hadDelete()); - } - } + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreGet", "hadPostGet", "hadPrePut", "hadPostPut", + "hadDelete"}, + TEST_TABLE, + new Boolean[] {true, true, true, true, true} + ); + util.deleteTable(tableName); } - // TODO: add tests for other methods which need to be tested - // at region servers. - @Test public void testIncrementHook() throws IOException { - HTable table = new HTable(util.getConfiguration(), TEST_TABLE_2); + byte[] tableName = TEST_TABLE; + HTable table = util.createTable(tableName, new byte[][] {A, B, C}); Increment inc = new Increment(Bytes.toBytes(0)); - inc.addColumn(TEST_FAMILY, TEST_QUALIFIER, 1); + inc.addColumn(A, A, 1); + + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreIncrement", "hadPostIncrement"}, + tableName, + new Boolean[] {false, false} + ); table.increment(inc); - for (JVMClusterUtil.RegionServerThread t : cluster.getRegionServerThreads()) { - for (HRegionInfo r : t.getRegionServer().getOnlineRegions()) { - if (!Arrays.equals(r.getTableDesc().getName(), TEST_TABLE_2)) { - continue; + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreIncrement", "hadPostIncrement"}, + tableName, + new Boolean[] {true, true} + ); + util.deleteTable(tableName); + } + + @Test + // HBase-3583 + public void testHBase3583() throws IOException { + byte[] tableName = Bytes.toBytes("testHBase3583"); + util.createTable(tableName, new byte[][] {A, B, C}); + + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled", + "wasScannerCloseCalled"}, + tableName, + new Boolean[] {false, false, false, false} + ); + + HTable table = new HTable(util.getConfiguration(), tableName); + Put put = new Put(ROW); + put.add(A, A, A); + table.put(put); + + Get get = new Get(ROW); + get.addColumn(A, A); + table.get(get); + + // verify that scannerNext and scannerClose upcalls won't be invoked + // when we perform get(). + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"hadPreGet", "hadPostGet", "wasScannerNextCalled", + "wasScannerCloseCalled"}, + tableName, + new Boolean[] {true, true, false, false} + ); + + Scan s = new Scan(); + ResultScanner scanner = table.getScanner(s); + try { + for (Result rr = scanner.next(); rr != null; rr = scanner.next()) { + } + } finally { + scanner.close(); + } + + // now scanner hooks should be invoked. + verifyMethodResult(SimpleRegionObserver.class, + new String[] {"wasScannerNextCalled", "wasScannerCloseCalled"}, + tableName, + new Boolean[] {true, true} + ); + util.deleteTable(tableName); + } + + // check each region whether the coprocessor upcalls are called or not. + private void verifyMethodResult(Class c, String methodName[], byte[] tableName, + Object value[]) throws IOException { + try { + for (JVMClusterUtil.RegionServerThread t : cluster.getRegionServerThreads()) { + for (HRegionInfo r : t.getRegionServer().getOnlineRegions()) { + if (!Arrays.equals(r.getTableDesc().getName(), tableName)) { + continue; + } + RegionCoprocessorHost cph = t.getRegionServer().getOnlineRegion(r.getRegionName()). + getCoprocessorHost(); + + Coprocessor cp = cph.findCoprocessor(c.getName()); + assertNotNull(cp); + for (int i = 0; i < methodName.length; ++i) { + Method m = c.getMethod(methodName[i]); + Object o = m.invoke(cp); + assertTrue("Result of " + c.getName() + "." + methodName[i] + + " is expected to be " + value[i].toString() + + ", while we get " + o.toString(), o.equals(value[i])); + } } - RegionCoprocessorHost cph = t.getRegionServer().getOnlineRegion(r.getRegionName()). - getCoprocessorHost(); - Coprocessor c = cph.findCoprocessor(SimpleRegionObserver.class.getName()); - assertTrue(((SimpleRegionObserver)c).hadPreIncrement()); - assertTrue(((SimpleRegionObserver)c).hadPostIncrement()); } + } catch (Exception e) { + throw new IOException(e.toString()); } }