001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.coprocessor; 019 020import static org.junit.Assert.assertTrue; 021 022import java.io.IOException; 023import java.util.Optional; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.fs.Path; 026import org.apache.hadoop.hbase.Coprocessor; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.HBaseTestingUtility; 029import org.apache.hadoop.hbase.HColumnDescriptor; 030import org.apache.hadoop.hbase.HRegionInfo; 031import org.apache.hadoop.hbase.HTableDescriptor; 032import org.apache.hadoop.hbase.TableName; 033import org.apache.hadoop.hbase.client.Durability; 034import org.apache.hadoop.hbase.client.Put; 035import org.apache.hadoop.hbase.regionserver.ChunkCreator; 036import org.apache.hadoop.hbase.regionserver.HRegion; 037import org.apache.hadoop.hbase.regionserver.MemStoreLAB; 038import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; 039import org.apache.hadoop.hbase.regionserver.RegionServerServices; 040import org.apache.hadoop.hbase.testclassification.CoprocessorTests; 041import org.apache.hadoop.hbase.testclassification.SmallTests; 042import org.apache.hadoop.hbase.util.Bytes; 043import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 044import org.apache.hadoop.hbase.util.Threads; 045import org.apache.hadoop.hbase.wal.WALEdit; 046import org.junit.ClassRule; 047import org.junit.Test; 048import org.junit.experimental.categories.Category; 049import org.mockito.Mockito; 050 051@Category({ CoprocessorTests.class, SmallTests.class }) 052public class TestRegionObserverStacking { 053 054 @ClassRule 055 public static final HBaseClassTestRule CLASS_RULE = 056 HBaseClassTestRule.forClass(TestRegionObserverStacking.class); 057 058 private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 059 static final Path DIR = TEST_UTIL.getDataTestDir(); 060 061 public static class ObserverA implements RegionCoprocessor, RegionObserver { 062 long id; 063 064 @Override 065 public Optional<RegionObserver> getRegionObserver() { 066 return Optional.of(this); 067 } 068 069 @Override 070 public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c, final Put put, 071 final WALEdit edit, final Durability durability) throws IOException { 072 id = EnvironmentEdgeManager.currentTime(); 073 Threads.sleepWithoutInterrupt(10); 074 } 075 } 076 077 public static class ObserverB implements RegionCoprocessor, RegionObserver { 078 long id; 079 080 @Override 081 public Optional<RegionObserver> getRegionObserver() { 082 return Optional.of(this); 083 } 084 085 @Override 086 public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c, final Put put, 087 final WALEdit edit, final Durability durability) throws IOException { 088 id = EnvironmentEdgeManager.currentTime(); 089 Threads.sleepWithoutInterrupt(10); 090 } 091 } 092 093 public static class ObserverC implements RegionCoprocessor, RegionObserver { 094 long id; 095 096 @Override 097 public Optional<RegionObserver> getRegionObserver() { 098 return Optional.of(this); 099 } 100 101 @Override 102 public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c, final Put put, 103 final WALEdit edit, final Durability durability) throws IOException { 104 id = EnvironmentEdgeManager.currentTime(); 105 Threads.sleepWithoutInterrupt(10); 106 } 107 } 108 109 HRegion initHRegion(byte[] tableName, String callingMethod, Configuration conf, 110 byte[]... families) throws IOException { 111 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName)); 112 for (byte[] family : families) { 113 htd.addFamily(new HColumnDescriptor(family)); 114 } 115 ChunkCreator.initialize(MemStoreLAB.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, null, 116 MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT); 117 HRegionInfo info = new HRegionInfo(htd.getTableName(), null, null, false); 118 Path path = new Path(DIR + callingMethod); 119 HRegion r = HBaseTestingUtility.createRegionAndWAL(info, path, conf, htd); 120 // this following piece is a hack. currently a coprocessorHost 121 // is secretly loaded at OpenRegionHandler. we don't really 122 // start a region server here, so just manually create cphost 123 // and set it to region. 124 RegionCoprocessorHost host = 125 new RegionCoprocessorHost(r, Mockito.mock(RegionServerServices.class), conf); 126 r.setCoprocessorHost(host); 127 return r; 128 } 129 130 @Test 131 public void testRegionObserverStacking() throws Exception { 132 byte[] ROW = Bytes.toBytes("testRow"); 133 byte[] TABLE = Bytes.toBytes(this.getClass().getSimpleName()); 134 byte[] A = Bytes.toBytes("A"); 135 byte[][] FAMILIES = new byte[][] { A }; 136 137 Configuration conf = TEST_UTIL.getConfiguration(); 138 HRegion region = initHRegion(TABLE, getClass().getName(), conf, FAMILIES); 139 RegionCoprocessorHost h = region.getCoprocessorHost(); 140 h.load(ObserverA.class, Coprocessor.PRIORITY_HIGHEST, conf); 141 h.load(ObserverB.class, Coprocessor.PRIORITY_USER, conf); 142 h.load(ObserverC.class, Coprocessor.PRIORITY_LOWEST, conf); 143 144 Put put = new Put(ROW); 145 put.addColumn(A, A, A); 146 region.put(put); 147 148 Coprocessor c = h.findCoprocessor(ObserverA.class.getName()); 149 long idA = ((ObserverA) c).id; 150 c = h.findCoprocessor(ObserverB.class.getName()); 151 long idB = ((ObserverB) c).id; 152 c = h.findCoprocessor(ObserverC.class.getName()); 153 long idC = ((ObserverC) c).id; 154 155 assertTrue(idA < idB); 156 assertTrue(idB < idC); 157 HBaseTestingUtility.closeRegionAndWAL(region); 158 } 159}