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.apache.hadoop.hbase.coprocessor.CoprocessorHost.COPROCESSORS_ENABLED_CONF_KEY; 021import static org.apache.hadoop.hbase.coprocessor.CoprocessorHost.REGION_COPROCESSOR_CONF_KEY; 022import static org.apache.hadoop.hbase.coprocessor.CoprocessorHost.SKIP_LOAD_DUPLICATE_TABLE_COPROCESSOR; 023import static org.apache.hadoop.hbase.coprocessor.CoprocessorHost.USER_COPROCESSORS_ENABLED_CONF_KEY; 024import static org.junit.Assert.assertEquals; 025import static org.junit.Assert.assertTrue; 026import static org.mockito.Mockito.mock; 027import static org.mockito.Mockito.when; 028 029import java.io.IOException; 030import org.apache.hadoop.conf.Configuration; 031import org.apache.hadoop.hbase.CellComparator; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HBaseConfiguration; 034import org.apache.hadoop.hbase.HConstants; 035import org.apache.hadoop.hbase.KeepDeletedCells; 036import org.apache.hadoop.hbase.TableName; 037import org.apache.hadoop.hbase.client.RegionInfo; 038import org.apache.hadoop.hbase.client.RegionInfoBuilder; 039import org.apache.hadoop.hbase.client.Scan; 040import org.apache.hadoop.hbase.client.TableDescriptor; 041import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 042import org.apache.hadoop.hbase.io.TimeRange; 043import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker; 044import org.apache.hadoop.hbase.regionserver.HRegion; 045import org.apache.hadoop.hbase.regionserver.HStore; 046import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; 047import org.apache.hadoop.hbase.regionserver.RegionServerServices; 048import org.apache.hadoop.hbase.regionserver.ScanInfo; 049import org.apache.hadoop.hbase.regionserver.ScanType; 050import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker; 051import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest; 052import org.apache.hadoop.hbase.security.User; 053import org.apache.hadoop.hbase.testclassification.SmallTests; 054import org.apache.hadoop.hbase.util.Bytes; 055import org.junit.Before; 056import org.junit.ClassRule; 057import org.junit.Rule; 058import org.junit.Test; 059import org.junit.experimental.categories.Category; 060import org.junit.rules.TestName; 061import java.io.IOException; 062 063@Category({SmallTests.class}) 064public class TestRegionCoprocessorHost { 065 private Configuration conf; 066 067 @ClassRule 068 public static final HBaseClassTestRule CLASS_RULE = 069 HBaseClassTestRule.forClass(TestRegionCoprocessorHost.class); 070 071 @Rule 072 public final TestName name = new TestName(); 073 private RegionInfo regionInfo; 074 private HRegion region; 075 private RegionServerServices rsServices; 076 public static final int MAX_VERSIONS = 3; 077 public static final int MIN_VERSIONS = 2; 078 public static final int TTL = 1000; 079 080 @Before 081 public void setup() throws IOException { 082 conf = HBaseConfiguration.create(); 083 conf.setBoolean(COPROCESSORS_ENABLED_CONF_KEY, true); 084 conf.setBoolean(USER_COPROCESSORS_ENABLED_CONF_KEY, true); 085 TableName tableName = TableName.valueOf(name.getMethodName()); 086 regionInfo = RegionInfoBuilder.newBuilder(tableName).build(); 087 // config a same coprocessor with system coprocessor 088 TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName) 089 .setCoprocessor(SimpleRegionObserver.class.getName()).build(); 090 region = mock(HRegion.class); 091 when(region.getRegionInfo()).thenReturn(regionInfo); 092 when(region.getTableDescriptor()).thenReturn(tableDesc); 093 rsServices = mock(RegionServerServices.class); 094 } 095 @Test 096 public void testLoadDuplicateCoprocessor() throws Exception { 097 conf.setBoolean(SKIP_LOAD_DUPLICATE_TABLE_COPROCESSOR, true); 098 conf.set(REGION_COPROCESSOR_CONF_KEY, SimpleRegionObserver.class.getName()); 099 RegionCoprocessorHost host = new RegionCoprocessorHost(region, rsServices, conf); 100 // Only one coprocessor SimpleRegionObserver loaded 101 assertEquals(1, host.coprocEnvironments.size()); 102 103 // Allow to load duplicate coprocessor 104 conf.setBoolean(SKIP_LOAD_DUPLICATE_TABLE_COPROCESSOR, false); 105 host = new RegionCoprocessorHost(region, rsServices, conf); 106 // Two duplicate coprocessors loaded 107 assertEquals(2, host.coprocEnvironments.size()); 108 } 109 110 @Test 111 public void testPreStoreScannerOpen() throws IOException { 112 113 RegionCoprocessorHost host = new RegionCoprocessorHost(region, rsServices, conf); 114 Scan scan = new Scan(); 115 scan.setTimeRange(TimeRange.INITIAL_MIN_TIMESTAMP, TimeRange.INITIAL_MAX_TIMESTAMP); 116 assertTrue("Scan is not for all time", scan.getTimeRange().isAllTime()); 117 //SimpleRegionObserver is set to update the ScanInfo parameters if the passed-in scan 118 //is for all time. this lets us exercise both that the Scan is wired up properly in the coproc 119 //and that we can customize the metadata 120 121 ScanInfo oldScanInfo = getScanInfo(); 122 123 HStore store = mock(HStore.class); 124 when(store.getScanInfo()).thenReturn(oldScanInfo); 125 ScanInfo newScanInfo = host.preStoreScannerOpen(store, scan); 126 127 verifyScanInfo(newScanInfo); 128 } 129 130 @Test 131 public void testPreCompactScannerOpen() throws IOException { 132 RegionCoprocessorHost host = new RegionCoprocessorHost(region, rsServices, conf); 133 ScanInfo oldScanInfo = getScanInfo(); 134 HStore store = mock(HStore.class); 135 when(store.getScanInfo()).thenReturn(oldScanInfo); 136 ScanInfo newScanInfo = host.preCompactScannerOpen(store, ScanType.COMPACT_DROP_DELETES, 137 mock(CompactionLifeCycleTracker.class), mock(CompactionRequest.class), mock(User.class)); 138 verifyScanInfo(newScanInfo); 139 } 140 141 @Test 142 public void testPreFlushScannerOpen() throws IOException { 143 RegionCoprocessorHost host = new RegionCoprocessorHost(region, rsServices, conf); 144 ScanInfo oldScanInfo = getScanInfo(); 145 HStore store = mock(HStore.class); 146 when(store.getScanInfo()).thenReturn(oldScanInfo); 147 ScanInfo newScanInfo = host.preFlushScannerOpen(store, mock(FlushLifeCycleTracker.class)); 148 verifyScanInfo(newScanInfo); 149 } 150 151 @Test 152 public void testPreMemStoreCompactionCompactScannerOpen() throws IOException { 153 RegionCoprocessorHost host = new RegionCoprocessorHost(region, rsServices, conf); 154 ScanInfo oldScanInfo = getScanInfo(); 155 HStore store = mock(HStore.class); 156 when(store.getScanInfo()).thenReturn(oldScanInfo); 157 ScanInfo newScanInfo = host.preMemStoreCompactionCompactScannerOpen(store); 158 verifyScanInfo(newScanInfo); 159 } 160 161 private void verifyScanInfo(ScanInfo newScanInfo) { 162 assertEquals(KeepDeletedCells.TRUE, newScanInfo.getKeepDeletedCells()); 163 assertEquals(MAX_VERSIONS, newScanInfo.getMaxVersions()); 164 assertEquals(MIN_VERSIONS, newScanInfo.getMinVersions()); 165 assertEquals(TTL, newScanInfo.getTtl()); 166 } 167 168 private ScanInfo getScanInfo() { 169 int oldMaxVersions = 1; 170 int oldMinVersions = 0; 171 long oldTTL = 10000; 172 173 return new ScanInfo(conf, Bytes.toBytes("cf"), oldMinVersions, oldMaxVersions, oldTTL, 174 KeepDeletedCells.FALSE, HConstants.FOREVER, 1000, 175 CellComparator.getInstance(), true); 176 } 177 178}