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.wal; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021 022import java.io.IOException; 023import java.util.List; 024import java.util.Random; 025import java.util.SortedMap; 026import java.util.TreeMap; 027import org.apache.hadoop.hbase.HBaseTestingUtil; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.client.Delete; 030import org.apache.hadoop.hbase.client.Put; 031import org.apache.hadoop.hbase.client.Table; 032import org.apache.hadoop.hbase.master.HMaster; 033import org.apache.hadoop.hbase.regionserver.HRegionServer; 034import org.apache.hadoop.hbase.regionserver.Region; 035import org.apache.hadoop.hbase.testclassification.MediumTests; 036import org.apache.hadoop.hbase.testclassification.RegionServerTests; 037import org.apache.hadoop.hbase.util.Bytes; 038import org.junit.jupiter.api.AfterEach; 039import org.junit.jupiter.api.BeforeEach; 040import org.junit.jupiter.api.Tag; 041import org.junit.jupiter.api.Test; 042 043import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 044import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 045 046import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; 047import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.FlushRegionRequest; 048import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdRequest; 049 050@Tag(RegionServerTests.TAG) 051@Tag(MediumTests.TAG) 052public class TestWALFiltering { 053 054 private static final int NUM_RS = 4; 055 056 private static final TableName TABLE_NAME = TableName.valueOf("TestWALFiltering"); 057 private static final byte[] CF1 = Bytes.toBytes("MyCF1"); 058 private static final byte[] CF2 = Bytes.toBytes("MyCF2"); 059 private static final byte[][] FAMILIES = { CF1, CF2 }; 060 061 private HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 062 063 @BeforeEach 064 public void setUp() throws Exception { 065 TEST_UTIL.startMiniCluster(NUM_RS); 066 fillTable(); 067 } 068 069 @AfterEach 070 public void tearDown() throws Exception { 071 TEST_UTIL.shutdownMiniCluster(); 072 } 073 074 private void fillTable() throws IOException, InterruptedException { 075 Table table = TEST_UTIL.createTable(TABLE_NAME, FAMILIES, 3, Bytes.toBytes("row0"), 076 Bytes.toBytes("row99"), NUM_RS); 077 Random rand = new Random(19387129L); 078 for (int iStoreFile = 0; iStoreFile < 4; ++iStoreFile) { 079 for (int iRow = 0; iRow < 100; ++iRow) { 080 final byte[] row = Bytes.toBytes("row" + iRow); 081 Put put = new Put(row); 082 Delete del = new Delete(row); 083 for (int iCol = 0; iCol < 10; ++iCol) { 084 final byte[] cf = rand.nextBoolean() ? CF1 : CF2; 085 final long ts = Math.abs(rand.nextInt()); 086 final byte[] qual = Bytes.toBytes("col" + iCol); 087 if (rand.nextBoolean()) { 088 final byte[] value = 089 Bytes.toBytes("value_for_row_" + iRow + "_cf_" + Bytes.toStringBinary(cf) + "_col_" 090 + iCol + "_ts_" + ts + "_random_" + rand.nextLong()); 091 put.addColumn(cf, qual, ts, value); 092 } else if (rand.nextDouble() < 0.8) { 093 del.addColumn(cf, qual, ts); 094 } else { 095 del.addColumn(cf, qual, ts); 096 } 097 } 098 table.put(put); 099 table.delete(del); 100 } 101 } 102 TEST_UTIL.waitUntilAllRegionsAssigned(TABLE_NAME); 103 } 104 105 @Test 106 public void testFlushedSequenceIdsSentToHMaster() throws IOException, InterruptedException, 107 org.apache.hbase.thirdparty.com.google.protobuf.ServiceException, ServiceException { 108 SortedMap<byte[], Long> allFlushedSequenceIds = new TreeMap<>(Bytes.BYTES_COMPARATOR); 109 for (int i = 0; i < NUM_RS; ++i) { 110 flushAllRegions(i); 111 } 112 Thread.sleep(10000); 113 HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster(); 114 for (int i = 0; i < NUM_RS; ++i) { 115 for (byte[] regionName : getRegionsByServer(i)) { 116 if (allFlushedSequenceIds.containsKey(regionName)) { 117 GetLastFlushedSequenceIdRequest req = 118 RequestConverter.buildGetLastFlushedSequenceIdRequest(regionName); 119 120 assertEquals((long) allFlushedSequenceIds.get(regionName), master.getMasterRpcServices() 121 .getLastFlushedSequenceId(null, req).getLastFlushedSequenceId()); 122 } 123 } 124 } 125 } 126 127 private List<byte[]> getRegionsByServer(int rsId) throws IOException { 128 List<byte[]> regionNames = Lists.newArrayList(); 129 HRegionServer hrs = getRegionServer(rsId); 130 for (Region r : hrs.getRegions(TABLE_NAME)) { 131 regionNames.add(r.getRegionInfo().getRegionName()); 132 } 133 return regionNames; 134 } 135 136 private HRegionServer getRegionServer(int rsId) { 137 return TEST_UTIL.getMiniHBaseCluster().getRegionServer(rsId); 138 } 139 140 private void flushAllRegions(int rsId) throws ServiceException, 141 org.apache.hbase.thirdparty.com.google.protobuf.ServiceException, IOException { 142 HRegionServer hrs = getRegionServer(rsId); 143 for (byte[] regionName : getRegionsByServer(rsId)) { 144 FlushRegionRequest request = RequestConverter.buildFlushRegionRequest(regionName); 145 hrs.getRSRpcServices().flushRegion(null, request); 146 } 147 } 148 149}