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.regionreplication; 019 020import static org.junit.Assert.assertNotNull; 021import static org.junit.Assert.assertTrue; 022 023import java.io.IOException; 024import java.util.Arrays; 025import java.util.List; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.HBaseTestingUtil; 029import org.apache.hadoop.hbase.StartTestingClusterOption; 030import org.apache.hadoop.hbase.TableName; 031import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 032import org.apache.hadoop.hbase.client.Consistency; 033import org.apache.hadoop.hbase.client.Durability; 034import org.apache.hadoop.hbase.client.Get; 035import org.apache.hadoop.hbase.client.Mutation; 036import org.apache.hadoop.hbase.client.Put; 037import org.apache.hadoop.hbase.client.RegionReplicaUtil; 038import org.apache.hadoop.hbase.client.Result; 039import org.apache.hadoop.hbase.client.Table; 040import org.apache.hadoop.hbase.client.TableDescriptor; 041import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 042import org.apache.hadoop.hbase.regionserver.HRegion; 043import org.apache.hadoop.hbase.regionserver.HRegionServer; 044import org.apache.hadoop.hbase.regionserver.Region; 045import org.apache.hadoop.hbase.testclassification.LargeTests; 046import org.apache.hadoop.hbase.testclassification.RegionServerTests; 047import org.apache.hadoop.hbase.util.Bytes; 048import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil; 049import org.junit.AfterClass; 050import org.junit.BeforeClass; 051import org.junit.ClassRule; 052import org.junit.Test; 053import org.junit.experimental.categories.Category; 054 055@Category({ RegionServerTests.class, LargeTests.class }) 056public class TestRegionReplicationForSkipWAL { 057 058 @ClassRule 059 public static final HBaseClassTestRule CLASS_RULE = 060 HBaseClassTestRule.forClass(TestRegionReplicationForSkipWAL.class); 061 062 private static final byte[] FAM1 = Bytes.toBytes("family_test1"); 063 064 private static final byte[] QUAL1 = Bytes.toBytes("qualifier_test1"); 065 066 private static final byte[] FAM2 = Bytes.toBytes("family_test2"); 067 068 private static final byte[] QUAL2 = Bytes.toBytes("qualifier_test2"); 069 070 private static final byte[] FAM3 = Bytes.toBytes("family_test3"); 071 072 private static final byte[] QUAL3 = Bytes.toBytes("qualifier_test3"); 073 074 private static final byte[] FAM4 = Bytes.toBytes("family_test4"); 075 076 private static final byte[] QUAL4 = Bytes.toBytes("qualifier_test4"); 077 078 private static final byte[] FAM5 = Bytes.toBytes("family_test5"); 079 080 private static final byte[] QUAL5 = Bytes.toBytes("qualifier_test5"); 081 082 private static final byte[] FAM6 = Bytes.toBytes("family_test6"); 083 084 private static final byte[] QUAL6 = Bytes.toBytes("qualifier_test6"); 085 086 private static final HBaseTestingUtil HTU = new HBaseTestingUtil(); 087 private static final int NB_SERVERS = 2; 088 089 private static final String strTableName = "TestRegionReplicationForSkipWAL"; 090 091 @BeforeClass 092 public static void setUp() throws Exception { 093 Configuration conf = HTU.getConfiguration(); 094 conf.setBoolean(ServerRegionReplicaUtil.REGION_REPLICA_REPLICATION_CONF_KEY, true); 095 conf.setBoolean(RegionReplicaUtil.REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH_CONF_KEY, false); 096 HTU.startMiniCluster(StartTestingClusterOption.builder().numRegionServers(NB_SERVERS).build()); 097 } 098 099 @AfterClass 100 public static void tearDown() throws Exception { 101 HTU.shutdownMiniCluster(); 102 } 103 104 /** 105 * This test is for HBASE-26933,make the new region replication framework introduced by 106 * HBASE-26233 work for table which DURABILITY is Durability.SKIP_WAL. 107 */ 108 @Test 109 public void testReplicateToReplicaWhenSkipWAL() throws Exception { 110 final HRegion[] skipWALRegions = this.createTable(true); 111 byte[] rowKey1 = Bytes.toBytes(1); 112 byte[] value1 = Bytes.toBytes(2); 113 114 byte[] rowKey2 = Bytes.toBytes(2); 115 byte[] value2 = Bytes.toBytes(4); 116 117 // Test the table is skipWAL 118 skipWALRegions[0].batchMutate(new Mutation[] { new Put(rowKey1).addColumn(FAM1, QUAL1, value1), 119 new Put(rowKey2).addColumn(FAM2, QUAL2, value2) }); 120 121 try (Table skipWALTable = HTU.getConnection().getTable(getTableName(true))) { 122 HTU.waitFor(30000, () -> checkReplica(skipWALTable, FAM1, QUAL1, rowKey1, value1) 123 && checkReplica(skipWALTable, FAM2, QUAL2, rowKey2, value2)); 124 } 125 126 byte[] rowKey3 = Bytes.toBytes(3); 127 byte[] value3 = Bytes.toBytes(6); 128 byte[] rowKey4 = Bytes.toBytes(4); 129 byte[] value4 = Bytes.toBytes(8); 130 byte[] rowKey5 = Bytes.toBytes(5); 131 byte[] value5 = Bytes.toBytes(10); 132 byte[] rowKey6 = Bytes.toBytes(6); 133 byte[] value6 = Bytes.toBytes(12); 134 135 // Test the table is normal,but the Put is skipWAL 136 final HRegion[] normalRegions = this.createTable(false); 137 normalRegions[0].batchMutate(new Mutation[] { new Put(rowKey3).addColumn(FAM3, QUAL3, value3), 138 new Put(rowKey4).addColumn(FAM4, QUAL4, value4).setDurability(Durability.SKIP_WAL), 139 new Put(rowKey5).addColumn(FAM5, QUAL5, value5).setDurability(Durability.SKIP_WAL), 140 new Put(rowKey6).addColumn(FAM6, QUAL6, value6) }); 141 142 try (Table normalTable = HTU.getConnection().getTable(getTableName(false))) { 143 HTU.waitFor(30000, 144 () -> checkReplica(normalTable, FAM3, QUAL3, rowKey3, value3) 145 && checkReplica(normalTable, FAM4, QUAL4, rowKey4, value4) 146 && checkReplica(normalTable, FAM5, QUAL5, rowKey5, value5) 147 && checkReplica(normalTable, FAM6, QUAL6, rowKey6, value6)); 148 } 149 } 150 151 private static boolean checkReplica(Table table, byte[] fam, byte[] qual, byte[] rowKey, 152 byte[] expectValue) throws IOException { 153 Get get = new Get(rowKey).setConsistency(Consistency.TIMELINE).setReplicaId(1); 154 Result result = table.get(get); 155 byte[] value = result.getValue(fam, qual); 156 return value != null && value.length > 0 && Arrays.equals(expectValue, value); 157 } 158 159 private TableName getTableName(boolean skipWAL) { 160 return TableName.valueOf(strTableName + (skipWAL ? "_skipWAL" : "")); 161 } 162 163 private HRegion[] createTable(boolean skipWAL) throws Exception { 164 TableName tableName = getTableName(skipWAL); 165 TableDescriptorBuilder builder = 166 TableDescriptorBuilder.newBuilder(tableName).setRegionReplication(NB_SERVERS) 167 .setColumnFamilies(Arrays.asList(ColumnFamilyDescriptorBuilder.of(FAM1), 168 ColumnFamilyDescriptorBuilder.of(FAM2), ColumnFamilyDescriptorBuilder.of(FAM3), 169 ColumnFamilyDescriptorBuilder.of(FAM4), ColumnFamilyDescriptorBuilder.of(FAM5), 170 ColumnFamilyDescriptorBuilder.of(FAM6))); 171 if (skipWAL) { 172 builder.setDurability(Durability.SKIP_WAL); 173 174 } 175 TableDescriptor tableDescriptor = builder.build(); 176 177 HTU.getAdmin().createTable(tableDescriptor); 178 final HRegion[] regions = new HRegion[NB_SERVERS]; 179 for (int i = 0; i < NB_SERVERS; i++) { 180 HRegionServer rs = HTU.getMiniHBaseCluster().getRegionServer(i); 181 List<HRegion> onlineRegions = rs.getRegions(tableName); 182 for (HRegion region : onlineRegions) { 183 int replicaId = region.getRegionInfo().getReplicaId(); 184 assertTrue(regions[replicaId] == null); 185 regions[region.getRegionInfo().getReplicaId()] = region; 186 } 187 } 188 for (Region region : regions) { 189 assertNotNull(region); 190 } 191 return regions; 192 } 193}