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