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.client; 019 020import static org.awaitility.Awaitility.await; 021import static org.junit.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertNotNull; 023 024import java.io.IOException; 025import java.time.Duration; 026import java.util.List; 027import org.apache.hadoop.hbase.MetaTableAccessor; 028import org.apache.hadoop.hbase.TableName; 029import org.apache.hadoop.hbase.master.RegionState; 030import org.apache.hadoop.hbase.master.assignment.RegionStates; 031import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils; 032import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 033import org.junit.jupiter.api.TestTemplate; 034 035public class CloneSnapshotFromClientAfterSplittingRegionTestBase 036 extends CloneSnapshotFromClientTestBase { 037 038 protected CloneSnapshotFromClientAfterSplittingRegionTestBase(int numReplicas) { 039 super(numReplicas); 040 } 041 042 private void splitRegion() throws IOException { 043 int numRegions = admin.getRegions(tableName).size(); 044 try (Table k = TEST_UTIL.getConnection().getTable(tableName); 045 ResultScanner scanner = k.getScanner(new Scan())) { 046 // Split on the second row to make sure that the snapshot contains reference files. 047 // We also disable the compaction so that the reference files are not compacted away. 048 scanner.next(); 049 admin.split(tableName, scanner.next().getRow()); 050 } 051 await().atMost(Duration.ofSeconds(30)).untilAsserted( 052 () -> assertEquals(numRegions + numReplicas, admin.getRegions(tableName).size())); 053 } 054 055 @TestTemplate 056 public void testCloneSnapshotAfterSplittingRegion() throws IOException, InterruptedException { 057 // Turn off the CatalogJanitor 058 admin.catalogJanitorSwitch(false); 059 060 TableName clonedTableName = 061 TableName.valueOf(getValidMethodName() + "-" + EnvironmentEdgeManager.currentTime()); 062 try { 063 List<RegionInfo> regionInfos = admin.getRegions(tableName); 064 RegionReplicaUtil.removeNonDefaultRegions(regionInfos); 065 066 // Split a region 067 splitRegion(); 068 069 // Take a snapshot 070 admin.snapshot(snapshotName2, tableName); 071 // Clone the snapshot to another table 072 admin.cloneSnapshot(snapshotName2, clonedTableName); 073 SnapshotTestingUtils.waitForTableToBeOnline(TEST_UTIL, clonedTableName); 074 075 verifyRowCount(TEST_UTIL, clonedTableName, snapshot1Rows); 076 077 RegionStates regionStates = 078 TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStates(); 079 080 // The region count of the cloned table should be the same as the one of the original table 081 int openRegionCountOfOriginalTable = 082 regionStates.getRegionByStateOfTable(tableName).get(RegionState.State.OPEN).size(); 083 int openRegionCountOfClonedTable = 084 regionStates.getRegionByStateOfTable(clonedTableName).get(RegionState.State.OPEN).size(); 085 assertEquals(openRegionCountOfOriginalTable, openRegionCountOfClonedTable); 086 087 int splitRegionCountOfOriginalTable = 088 regionStates.getRegionByStateOfTable(tableName).get(RegionState.State.SPLIT).size(); 089 List<RegionInfo> splitParents = 090 regionStates.getRegionByStateOfTable(clonedTableName).get(RegionState.State.SPLIT); 091 int splitRegionCountOfClonedTable = splitParents.size(); 092 assertEquals(splitRegionCountOfOriginalTable, splitRegionCountOfClonedTable); 093 094 // Make sure that the meta table was updated with the correct split information 095 for (RegionInfo splitParent : splitParents) { 096 Result result = MetaTableAccessor.getRegionResult(TEST_UTIL.getConnection(), splitParent); 097 for (RegionInfo daughter : MetaTableAccessor.getDaughterRegions(result)) { 098 assertNotNull(daughter); 099 } 100 } 101 } finally { 102 if (admin.tableExists(clonedTableName)) { 103 TEST_UTIL.deleteTable(clonedTableName); 104 } 105 admin.catalogJanitorSwitch(true); 106 } 107 } 108 109 @TestTemplate 110 public void testCloneSnapshotBeforeSplittingRegionAndDroppingTable() 111 throws IOException, InterruptedException { 112 // Turn off the CatalogJanitor 113 admin.catalogJanitorSwitch(false); 114 TableName clonedTableName = 115 TableName.valueOf(getValidMethodName() + "-" + EnvironmentEdgeManager.currentTime()); 116 try { 117 // Take a snapshot 118 admin.snapshot(snapshotName2, tableName); 119 120 // Clone the snapshot to another table 121 admin.cloneSnapshot(snapshotName2, clonedTableName); 122 SnapshotTestingUtils.waitForTableToBeOnline(TEST_UTIL, clonedTableName); 123 124 // Split a region of the original table 125 List<RegionInfo> regionInfos = admin.getRegions(tableName); 126 RegionReplicaUtil.removeNonDefaultRegions(regionInfos); 127 splitRegion(); 128 129 // Drop the original table 130 admin.disableTable(tableName); 131 admin.deleteTable(tableName); 132 133 // Disable and enable the cloned table. This should be successful 134 admin.disableTable(clonedTableName); 135 admin.enableTable(clonedTableName); 136 SnapshotTestingUtils.waitForTableToBeOnline(TEST_UTIL, clonedTableName); 137 138 verifyRowCount(TEST_UTIL, clonedTableName, snapshot1Rows); 139 } finally { 140 if (admin.tableExists(clonedTableName)) { 141 TEST_UTIL.deleteTable(clonedTableName); 142 } 143 admin.catalogJanitorSwitch(true); 144 } 145 } 146}