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.regionserver; 019 020import static org.mockito.Mockito.verify; 021 022import java.io.IOException; 023import org.apache.hadoop.conf.Configuration; 024import org.apache.hadoop.hbase.HBaseClassTestRule; 025import org.apache.hadoop.hbase.HBaseTestingUtility; 026import org.apache.hadoop.hbase.TableName; 027import org.apache.hadoop.hbase.testclassification.MediumTests; 028import org.apache.hadoop.hbase.util.Bytes; 029import org.junit.Before; 030import org.junit.BeforeClass; 031import org.junit.ClassRule; 032import org.junit.Test; 033import org.junit.experimental.categories.Category; 034import org.mockito.Mockito; 035 036import org.apache.hbase.thirdparty.com.google.protobuf.RpcController; 037import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 038 039import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; 040import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.Action; 041import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MultiRequest; 042import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.RegionAction; 043import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 044 045/** 046 * Tests logging of large batch commands via Multi. Tests are fast, but uses a mini-cluster (to test 047 * via "Multi" commands) so classified as MediumTests 048 */ 049@Category(MediumTests.class) 050public class TestMultiLogThreshold { 051 052 @ClassRule 053 public static final HBaseClassTestRule CLASS_RULE = 054 HBaseClassTestRule.forClass(TestMultiLogThreshold.class); 055 056 private static RSRpcServices SERVICES; 057 058 private static HBaseTestingUtility TEST_UTIL; 059 private static Configuration CONF; 060 private static final byte[] TEST_FAM = Bytes.toBytes("fam"); 061 private static RSRpcServices.LogDelegate LD; 062 private static HRegionServer RS; 063 private static int THRESHOLD; 064 065 @BeforeClass 066 public static void setup() throws Exception { 067 final TableName tableName = TableName.valueOf("tableName"); 068 TEST_UTIL = HBaseTestingUtility.createLocalHTU(); 069 CONF = TEST_UTIL.getConfiguration(); 070 THRESHOLD = CONF.getInt(RSRpcServices.BATCH_ROWS_THRESHOLD_NAME, 071 RSRpcServices.BATCH_ROWS_THRESHOLD_DEFAULT); 072 TEST_UTIL.startMiniCluster(); 073 TEST_UTIL.createTable(tableName, TEST_FAM); 074 RS = TEST_UTIL.getRSForFirstRegionInTable(tableName); 075 } 076 077 @Before 078 public void setupTest() throws Exception { 079 LD = Mockito.mock(RSRpcServices.LogDelegate.class); 080 SERVICES = new RSRpcServices(RS, LD); 081 } 082 083 private enum ActionType { 084 REGION_ACTIONS, ACTIONS; 085 } 086 087 /** 088 * Sends a multi request with a certain amount of rows, will populate Multi command with either 089 * "rows" number of RegionActions with one Action each or one RegionAction with "rows" number of 090 * Actions 091 */ 092 private void sendMultiRequest(int rows, ActionType actionType) throws ServiceException { 093 RpcController rpcc = Mockito.mock(RpcController.class); 094 MultiRequest.Builder builder = MultiRequest.newBuilder(); 095 int numRAs = 1; 096 int numAs = 1; 097 switch (actionType) { 098 case REGION_ACTIONS: 099 numRAs = rows; 100 break; 101 case ACTIONS: 102 numAs = rows; 103 break; 104 } 105 for (int i = 0; i < numRAs; i++) { 106 RegionAction.Builder rab = RegionAction.newBuilder(); 107 rab.setRegion(RequestConverter.buildRegionSpecifier( 108 HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME, 109 new String("someStuff" + i).getBytes())); 110 for (int j = 0; j < numAs; j++) { 111 Action.Builder ab = Action.newBuilder(); 112 rab.addAction(ab.build()); 113 } 114 builder.addRegionAction(rab.build()); 115 } 116 try { 117 SERVICES.multi(rpcc, builder.build()); 118 } catch (ClassCastException e) { 119 // swallow expected exception due to mocked RpcController 120 } 121 } 122 123 @Test 124 public void testMultiLogThresholdRegionActions() throws ServiceException, IOException { 125 sendMultiRequest(THRESHOLD + 1, ActionType.REGION_ACTIONS); 126 verify(LD, Mockito.times(1)).logBatchWarning(Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt()); 127 } 128 129 @Test 130 public void testMultiNoLogThresholdRegionActions() throws ServiceException, IOException { 131 sendMultiRequest(THRESHOLD, ActionType.REGION_ACTIONS); 132 verify(LD, Mockito.never()).logBatchWarning(Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt()); 133 } 134 135 @Test 136 public void testMultiLogThresholdActions() throws ServiceException, IOException { 137 sendMultiRequest(THRESHOLD + 1, ActionType.ACTIONS); 138 verify(LD, Mockito.times(1)).logBatchWarning(Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt()); 139 } 140 141 @Test 142 public void testMultiNoLogThresholdAction() throws ServiceException, IOException { 143 sendMultiRequest(THRESHOLD, ActionType.ACTIONS); 144 verify(LD, Mockito.never()).logBatchWarning(Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt()); 145 } 146 147}