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.snapshot; 019 020import java.io.IOException; 021import org.apache.hadoop.conf.Configuration; 022import org.apache.hadoop.hbase.HBaseClassTestRule; 023import org.apache.hadoop.hbase.HBaseTestingUtility; 024import org.apache.hadoop.hbase.HConstants; 025import org.apache.hadoop.hbase.TableName; 026import org.apache.hadoop.hbase.client.Admin; 027import org.apache.hadoop.hbase.client.SnapshotType; 028import org.apache.hadoop.hbase.client.Table; 029import org.apache.hadoop.hbase.master.snapshot.SnapshotManager; 030import org.apache.hadoop.hbase.regionserver.snapshot.RegionServerSnapshotManager; 031import org.apache.hadoop.hbase.testclassification.MediumTests; 032import org.apache.hadoop.hbase.testclassification.RegionServerTests; 033import org.apache.hadoop.hbase.util.Bytes; 034import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 035import org.junit.After; 036import org.junit.AfterClass; 037import org.junit.Before; 038import org.junit.BeforeClass; 039import org.junit.ClassRule; 040import org.junit.Test; 041import org.junit.experimental.categories.Category; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044 045/** 046 * Test clone/restore snapshots from the client TODO This is essentially a clone of 047 * TestRestoreSnapshotFromClient. This is worth refactoring this because there will be a few more 048 * flavors of snapshots that need to run these tests. 049 */ 050@Category({ RegionServerTests.class, MediumTests.class }) 051public class TestRestoreFlushSnapshotFromClient { 052 053 @ClassRule 054 public static final HBaseClassTestRule CLASS_RULE = 055 HBaseClassTestRule.forClass(TestRestoreFlushSnapshotFromClient.class); 056 057 private static final Logger LOG = 058 LoggerFactory.getLogger(TestRestoreFlushSnapshotFromClient.class); 059 060 protected final static HBaseTestingUtility UTIL = new HBaseTestingUtility(); 061 062 protected final byte[] FAMILY = Bytes.toBytes("cf"); 063 064 protected byte[] snapshotName0; 065 protected byte[] snapshotName1; 066 protected byte[] snapshotName2; 067 protected int snapshot0Rows; 068 protected int snapshot1Rows; 069 protected TableName tableName; 070 protected Admin admin; 071 072 @BeforeClass 073 public static void setupCluster() throws Exception { 074 setupConf(UTIL.getConfiguration()); 075 UTIL.startMiniCluster(3); 076 } 077 078 protected static void setupConf(Configuration conf) { 079 UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100); 080 UTIL.getConfiguration().setInt("hbase.client.pause", 250); 081 UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 6); 082 UTIL.getConfiguration().setBoolean("hbase.master.enabletable.roundrobin", true); 083 084 // Enable snapshot 085 UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true); 086 UTIL.getConfiguration().setLong(RegionServerSnapshotManager.SNAPSHOT_TIMEOUT_MILLIS_KEY, 087 RegionServerSnapshotManager.SNAPSHOT_TIMEOUT_MILLIS_DEFAULT * 2); 088 } 089 090 @AfterClass 091 public static void tearDownAfterClass() throws Exception { 092 UTIL.shutdownMiniCluster(); 093 } 094 095 protected void createTable() throws Exception { 096 SnapshotTestingUtils.createTable(UTIL, tableName, FAMILY); 097 } 098 099 /** 100 * Initialize the tests with a table filled with some data and two snapshots (snapshotName0, 101 * snapshotName1) of different states. The tableName, snapshotNames and the number of rows in the 102 * snapshot are initialized. 103 */ 104 @Before 105 public void setup() throws Exception { 106 this.admin = UTIL.getAdmin(); 107 108 long tid = EnvironmentEdgeManager.currentTime(); 109 tableName = TableName.valueOf("testtb-" + tid); 110 snapshotName0 = Bytes.toBytes("snaptb0-" + tid); 111 snapshotName1 = Bytes.toBytes("snaptb1-" + tid); 112 snapshotName2 = Bytes.toBytes("snaptb2-" + tid); 113 114 // create Table and disable it 115 createTable(); 116 SnapshotTestingUtils.loadData(UTIL, tableName, 500, FAMILY); 117 Table table = UTIL.getConnection().getTable(tableName); 118 snapshot0Rows = countRows(table); 119 LOG.info("=== before snapshot with 500 rows"); 120 logFSTree(); 121 122 // take a snapshot 123 admin.snapshot(Bytes.toString(snapshotName0), tableName, SnapshotType.FLUSH); 124 125 LOG.info("=== after snapshot with 500 rows"); 126 logFSTree(); 127 128 // insert more data 129 SnapshotTestingUtils.loadData(UTIL, tableName, 500, FAMILY); 130 snapshot1Rows = countRows(table); 131 LOG.info("=== before snapshot with 1000 rows"); 132 logFSTree(); 133 134 // take a snapshot of the updated table 135 admin.snapshot(Bytes.toString(snapshotName1), tableName, SnapshotType.FLUSH); 136 LOG.info("=== after snapshot with 1000 rows"); 137 logFSTree(); 138 table.close(); 139 } 140 141 @After 142 public void tearDown() throws Exception { 143 SnapshotTestingUtils.deleteAllSnapshots(UTIL.getAdmin()); 144 SnapshotTestingUtils.deleteArchiveDirectory(UTIL); 145 } 146 147 @Test 148 public void testTakeFlushSnapshot() throws IOException { 149 // taking happens in setup. 150 } 151 152 @Test 153 public void testRestoreSnapshot() throws IOException { 154 verifyRowCount(UTIL, tableName, snapshot1Rows); 155 156 // Restore from snapshot-0 157 admin.disableTable(tableName); 158 admin.restoreSnapshot(snapshotName0); 159 logFSTree(); 160 admin.enableTable(tableName); 161 LOG.info("=== after restore with 500 row snapshot"); 162 logFSTree(); 163 verifyRowCount(UTIL, tableName, snapshot0Rows); 164 165 // Restore from snapshot-1 166 admin.disableTable(tableName); 167 admin.restoreSnapshot(snapshotName1); 168 admin.enableTable(tableName); 169 verifyRowCount(UTIL, tableName, snapshot1Rows); 170 } 171 172 @Test(expected = SnapshotDoesNotExistException.class) 173 public void testCloneNonExistentSnapshot() throws IOException, InterruptedException { 174 String snapshotName = "random-snapshot-" + EnvironmentEdgeManager.currentTime(); 175 TableName tableName = TableName.valueOf("random-table-" + EnvironmentEdgeManager.currentTime()); 176 admin.cloneSnapshot(snapshotName, tableName); 177 } 178 179 @Test 180 public void testCloneSnapshot() throws IOException, InterruptedException { 181 TableName clonedTableName = 182 TableName.valueOf("clonedtb-" + EnvironmentEdgeManager.currentTime()); 183 testCloneSnapshot(clonedTableName, snapshotName0, snapshot0Rows); 184 testCloneSnapshot(clonedTableName, snapshotName1, snapshot1Rows); 185 } 186 187 private void testCloneSnapshot(final TableName tableName, final byte[] snapshotName, 188 int snapshotRows) throws IOException, InterruptedException { 189 // create a new table from snapshot 190 admin.cloneSnapshot(snapshotName, tableName); 191 verifyRowCount(UTIL, tableName, snapshotRows); 192 193 UTIL.deleteTable(tableName); 194 } 195 196 @Test 197 public void testRestoreSnapshotOfCloned() throws IOException, InterruptedException { 198 TableName clonedTableName = 199 TableName.valueOf("clonedtb-" + EnvironmentEdgeManager.currentTime()); 200 admin.cloneSnapshot(snapshotName0, clonedTableName); 201 verifyRowCount(UTIL, clonedTableName, snapshot0Rows); 202 admin.snapshot(Bytes.toString(snapshotName2), clonedTableName, SnapshotType.FLUSH); 203 UTIL.deleteTable(clonedTableName); 204 205 admin.cloneSnapshot(snapshotName2, clonedTableName); 206 verifyRowCount(UTIL, clonedTableName, snapshot0Rows); 207 UTIL.deleteTable(clonedTableName); 208 } 209 210 // ========================================================================== 211 // Helpers 212 // ========================================================================== 213 private void logFSTree() throws IOException { 214 UTIL.getMiniHBaseCluster().getMaster().getMasterFileSystem().logFileSystemState(LOG); 215 } 216 217 protected void verifyRowCount(final HBaseTestingUtility util, final TableName tableName, 218 long expectedRows) throws IOException { 219 SnapshotTestingUtils.verifyRowCount(util, tableName, expectedRows); 220 } 221 222 protected int countRows(final Table table, final byte[]... families) throws IOException { 223 return UTIL.countRows(table, families); 224 } 225}