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 static org.apache.hadoop.util.ToolRunner.run; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertFalse; 023import static org.junit.Assert.assertTrue; 024 025import java.io.IOException; 026import java.util.ArrayList; 027import java.util.HashMap; 028import java.util.HashSet; 029import java.util.List; 030import java.util.Map; 031import java.util.Objects; 032import java.util.Optional; 033import java.util.Set; 034import java.util.stream.Collectors; 035import org.apache.hadoop.conf.Configuration; 036import org.apache.hadoop.fs.FileStatus; 037import org.apache.hadoop.fs.FileSystem; 038import org.apache.hadoop.fs.Path; 039import org.apache.hadoop.hbase.HBaseClassTestRule; 040import org.apache.hadoop.hbase.HBaseTestingUtil; 041import org.apache.hadoop.hbase.HConstants; 042import org.apache.hadoop.hbase.TableName; 043import org.apache.hadoop.hbase.client.Admin; 044import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 045import org.apache.hadoop.hbase.client.Put; 046import org.apache.hadoop.hbase.client.RegionInfo; 047import org.apache.hadoop.hbase.client.SnapshotType; 048import org.apache.hadoop.hbase.client.Table; 049import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 050import org.apache.hadoop.hbase.master.snapshot.SnapshotManager; 051import org.apache.hadoop.hbase.regionserver.StoreFileInfo; 052import org.apache.hadoop.hbase.testclassification.LargeTests; 053import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests; 054import org.apache.hadoop.hbase.tool.BulkLoadHFilesTool; 055import org.apache.hadoop.hbase.util.AbstractHBaseTool; 056import org.apache.hadoop.hbase.util.Bytes; 057import org.apache.hadoop.hbase.util.CommonFSUtils; 058import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 059import org.apache.hadoop.hbase.util.HFileTestUtil; 060import org.apache.hadoop.hbase.util.Pair; 061import org.junit.After; 062import org.junit.AfterClass; 063import org.junit.Before; 064import org.junit.BeforeClass; 065import org.junit.ClassRule; 066import org.junit.Ignore; 067import org.junit.Rule; 068import org.junit.Test; 069import org.junit.experimental.categories.Category; 070import org.junit.rules.TestName; 071import org.slf4j.Logger; 072import org.slf4j.LoggerFactory; 073 074import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 075 076import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription; 077import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest; 078 079/** 080 * Test Export Snapshot Tool 081 */ 082@Ignore // HBASE-24493 083@Category({ VerySlowMapReduceTests.class, LargeTests.class }) 084public class TestExportSnapshot { 085 086 @ClassRule 087 public static final HBaseClassTestRule CLASS_RULE = 088 HBaseClassTestRule.forClass(TestExportSnapshot.class); 089 090 private static final Logger LOG = LoggerFactory.getLogger(TestExportSnapshot.class); 091 092 protected final static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 093 094 protected final static byte[] FAMILY = Bytes.toBytes("cf"); 095 096 @Rule 097 public final TestName testName = new TestName(); 098 099 protected TableName tableName; 100 private String emptySnapshotName; 101 private String snapshotName; 102 private int tableNumFiles; 103 private Admin admin; 104 105 public static void setUpBaseConf(Configuration conf) { 106 conf.setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true); 107 conf.setInt("hbase.regionserver.msginterval", 100); 108 // If a single node has enough failures (default 3), resource manager will blacklist it. 109 // With only 2 nodes and tests injecting faults, we don't want that. 110 conf.setInt("mapreduce.job.maxtaskfailures.per.tracker", 100); 111 } 112 113 @BeforeClass 114 public static void setUpBeforeClass() throws Exception { 115 setUpBaseConf(TEST_UTIL.getConfiguration()); 116 TEST_UTIL.startMiniCluster(1); 117 TEST_UTIL.startMiniMapReduceCluster(); 118 } 119 120 @AfterClass 121 public static void tearDownAfterClass() throws Exception { 122 TEST_UTIL.shutdownMiniMapReduceCluster(); 123 TEST_UTIL.shutdownMiniCluster(); 124 } 125 126 /** 127 * Create a table and take a snapshot of the table used by the export test. 128 */ 129 @Before 130 public void setUp() throws Exception { 131 this.admin = TEST_UTIL.getAdmin(); 132 133 tableName = TableName.valueOf("testtb-" + testName.getMethodName()); 134 snapshotName = "snaptb0-" + testName.getMethodName(); 135 emptySnapshotName = "emptySnaptb0-" + testName.getMethodName(); 136 137 // create Table 138 createTable(this.tableName); 139 140 // Take an empty snapshot 141 admin.snapshot(emptySnapshotName, tableName); 142 143 // Add some rows 144 SnapshotTestingUtils.loadData(TEST_UTIL, tableName, 50, FAMILY); 145 tableNumFiles = admin.getRegions(tableName).size(); 146 147 // take a snapshot 148 admin.snapshot(snapshotName, tableName); 149 } 150 151 protected void createTable(TableName tableName) throws Exception { 152 SnapshotTestingUtils.createPreSplitTable(TEST_UTIL, tableName, 2, FAMILY); 153 } 154 155 protected interface RegionPredicate { 156 boolean evaluate(final RegionInfo regionInfo); 157 } 158 159 protected RegionPredicate getBypassRegionPredicate() { 160 return null; 161 } 162 163 @After 164 public void tearDown() throws Exception { 165 TEST_UTIL.deleteTable(tableName); 166 SnapshotTestingUtils.deleteAllSnapshots(TEST_UTIL.getAdmin()); 167 SnapshotTestingUtils.deleteArchiveDirectory(TEST_UTIL); 168 } 169 170 /** 171 * Verify if exported snapshot and copied files matches the original one. 172 */ 173 @Test 174 public void testExportFileSystemState() throws Exception { 175 testExportFileSystemState(tableName, snapshotName, snapshotName, tableNumFiles); 176 } 177 178 @Test 179 public void testExportFileSystemStateWithMergeRegion() throws Exception { 180 // disable compaction 181 admin.compactionSwitch(false, 182 admin.getRegionServers().stream().map(a -> a.getServerName()).collect(Collectors.toList())); 183 // create Table 184 TableName tableName0 = TableName.valueOf("testtb-" + testName.getMethodName() + "-1"); 185 String snapshotName0 = "snaptb0-" + testName.getMethodName() + "-1"; 186 admin.createTable( 187 TableDescriptorBuilder.newBuilder(tableName0) 188 .setColumnFamilies( 189 Lists.newArrayList(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build())) 190 .build(), 191 new byte[][] { Bytes.toBytes("2") }); 192 // put some data 193 try (Table table = admin.getConnection().getTable(tableName0)) { 194 table.put(new Put(Bytes.toBytes("1")).addColumn(FAMILY, null, Bytes.toBytes("1"))); 195 table.put(new Put(Bytes.toBytes("2")).addColumn(FAMILY, null, Bytes.toBytes("2"))); 196 } 197 List<RegionInfo> regions = admin.getRegions(tableName0); 198 assertEquals(2, regions.size()); 199 tableNumFiles = regions.size(); 200 // merge region 201 admin.mergeRegionsAsync(new byte[][] { regions.get(0).getEncodedNameAsBytes(), 202 regions.get(1).getEncodedNameAsBytes() }, true).get(); 203 // take a snapshot 204 admin.snapshot(snapshotName0, tableName0); 205 // export snapshot and verify 206 testExportFileSystemState(tableName0, snapshotName0, snapshotName0, tableNumFiles); 207 // delete table 208 TEST_UTIL.deleteTable(tableName0); 209 } 210 211 @Test 212 public void testExportFileSystemStateWithSplitRegion() throws Exception { 213 // disable compaction 214 admin.compactionSwitch(false, 215 admin.getRegionServers().stream().map(a -> a.getServerName()).collect(Collectors.toList())); 216 // create Table 217 TableName splitTableName = TableName.valueOf(testName.getMethodName()); 218 String splitTableSnap = "snapshot-" + testName.getMethodName(); 219 admin.createTable(TableDescriptorBuilder.newBuilder(splitTableName).setColumnFamilies( 220 Lists.newArrayList(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build())).build()); 221 222 Path output = TEST_UTIL.getDataTestDir("output/cf"); 223 TEST_UTIL.getTestFileSystem().mkdirs(output); 224 // Create and load a large hfile to ensure the execution time of MR job. 225 HFileTestUtil.createHFile(TEST_UTIL.getConfiguration(), TEST_UTIL.getTestFileSystem(), 226 new Path(output, "test_file"), FAMILY, Bytes.toBytes("q"), Bytes.toBytes("1"), 227 Bytes.toBytes("9"), 9999999); 228 BulkLoadHFilesTool tool = new BulkLoadHFilesTool(TEST_UTIL.getConfiguration()); 229 tool.run(new String[] { output.getParent().toString(), splitTableName.getNameAsString() }); 230 231 List<RegionInfo> regions = admin.getRegions(splitTableName); 232 assertEquals(1, regions.size()); 233 tableNumFiles = regions.size(); 234 235 // split region 236 admin.split(splitTableName, Bytes.toBytes("5")); 237 regions = admin.getRegions(splitTableName); 238 assertEquals(2, regions.size()); 239 240 // take a snapshot 241 admin.snapshot(splitTableSnap, splitTableName); 242 // export snapshot and verify 243 Configuration tmpConf = TEST_UTIL.getConfiguration(); 244 // Decrease the buffer size of copier to avoid the export task finished shortly 245 tmpConf.setInt("snapshot.export.buffer.size", 1); 246 // Decrease the maximum files of each mapper to ensure the three files(1 hfile + 2 reference 247 // files) 248 // copied in different mappers concurrently. 249 tmpConf.setInt("snapshot.export.default.map.group", 1); 250 testExportFileSystemState(tmpConf, splitTableName, splitTableSnap, splitTableSnap, 251 tableNumFiles, TEST_UTIL.getDefaultRootDirPath(), getHdfsDestinationDir(), false, false, 252 getBypassRegionPredicate(), true, false); 253 // delete table 254 TEST_UTIL.deleteTable(splitTableName); 255 } 256 257 @Test 258 public void testExportFileSystemStateWithSkipTmp() throws Exception { 259 TEST_UTIL.getConfiguration().setBoolean(ExportSnapshot.CONF_SKIP_TMP, true); 260 try { 261 testExportFileSystemState(tableName, snapshotName, snapshotName, tableNumFiles); 262 } finally { 263 TEST_UTIL.getConfiguration().setBoolean(ExportSnapshot.CONF_SKIP_TMP, false); 264 } 265 } 266 267 @Test 268 public void testEmptyExportFileSystemState() throws Exception { 269 testExportFileSystemState(tableName, emptySnapshotName, emptySnapshotName, 0); 270 } 271 272 @Test 273 public void testConsecutiveExports() throws Exception { 274 Path copyDir = getLocalDestinationDir(TEST_UTIL); 275 testExportFileSystemState(tableName, snapshotName, snapshotName, tableNumFiles, copyDir, false); 276 testExportFileSystemState(tableName, snapshotName, snapshotName, tableNumFiles, copyDir, true); 277 removeExportDir(copyDir); 278 } 279 280 @Test 281 public void testExportWithChecksum() throws Exception { 282 // Test different schemes: input scheme is hdfs:// and output scheme is file:// 283 // The checksum verification will fail 284 Path copyLocalDir = getLocalDestinationDir(TEST_UTIL); 285 testExportFileSystemState(TEST_UTIL.getConfiguration(), tableName, snapshotName, snapshotName, 286 tableNumFiles, TEST_UTIL.getDefaultRootDirPath(), copyLocalDir, false, false, 287 getBypassRegionPredicate(), false, true); 288 289 // Test same schemes: input scheme is hdfs:// and output scheme is hdfs:// 290 // The checksum verification will success 291 Path copyHdfsDir = getHdfsDestinationDir(); 292 testExportFileSystemState(TEST_UTIL.getConfiguration(), tableName, snapshotName, snapshotName, 293 tableNumFiles, TEST_UTIL.getDefaultRootDirPath(), copyHdfsDir, false, false, 294 getBypassRegionPredicate(), true, true); 295 } 296 297 @Test 298 public void testExportWithTargetName() throws Exception { 299 final String targetName = "testExportWithTargetName"; 300 testExportFileSystemState(tableName, snapshotName, targetName, tableNumFiles); 301 } 302 303 @Test 304 public void testExportWithResetTtl() throws Exception { 305 String name = "testExportWithResetTtl"; 306 TableName tableName = TableName.valueOf(name); 307 String snapshotName = "snaptb-" + name; 308 Long ttl = 100000L; 309 310 try { 311 // create Table 312 createTable(tableName); 313 SnapshotTestingUtils.loadData(TEST_UTIL, tableName, 50, FAMILY); 314 int tableNumFiles = admin.getRegions(tableName).size(); 315 // take a snapshot with TTL 316 Map<String, Object> props = new HashMap<>(); 317 props.put("TTL", ttl); 318 admin.snapshot(snapshotName, tableName, props); 319 Optional<Long> ttlOpt = 320 admin.listSnapshots().stream().filter(s -> s.getName().equals(snapshotName)) 321 .map(org.apache.hadoop.hbase.client.SnapshotDescription::getTtl).findAny(); 322 assertTrue(ttlOpt.isPresent()); 323 assertEquals(ttl, ttlOpt.get()); 324 325 testExportFileSystemState(tableName, snapshotName, snapshotName, tableNumFiles, 326 getHdfsDestinationDir(), false, true); 327 } catch (Exception e) { 328 throw e; 329 } finally { 330 TEST_UTIL.deleteTable(tableName); 331 } 332 } 333 334 @Test 335 public void testExportExpiredSnapshot() throws Exception { 336 String name = "testExportExpiredSnapshot"; 337 TableName tableName = TableName.valueOf(name); 338 String snapshotName = "snapshot-" + name; 339 createTable(tableName); 340 SnapshotTestingUtils.loadData(TEST_UTIL, tableName, 50, FAMILY); 341 Map<String, Object> properties = new HashMap<>(); 342 properties.put("TTL", 10); 343 org.apache.hadoop.hbase.client.SnapshotDescription snapshotDescription = 344 new org.apache.hadoop.hbase.client.SnapshotDescription(snapshotName, tableName, 345 SnapshotType.FLUSH, null, EnvironmentEdgeManager.currentTime(), -1, properties); 346 admin.snapshot(snapshotDescription); 347 boolean isExist = 348 admin.listSnapshots().stream().anyMatch(ele -> snapshotName.equals(ele.getName())); 349 assertTrue(isExist); 350 int retry = 6; 351 while ( 352 !SnapshotDescriptionUtils.isExpiredSnapshot(snapshotDescription.getTtl(), 353 snapshotDescription.getCreationTime(), EnvironmentEdgeManager.currentTime()) && retry > 0 354 ) { 355 retry--; 356 Thread.sleep(10 * 1000); 357 } 358 boolean isExpiredSnapshot = 359 SnapshotDescriptionUtils.isExpiredSnapshot(snapshotDescription.getTtl(), 360 snapshotDescription.getCreationTime(), EnvironmentEdgeManager.currentTime()); 361 assertTrue(isExpiredSnapshot); 362 int res = runExportSnapshot(TEST_UTIL.getConfiguration(), snapshotName, snapshotName, 363 TEST_UTIL.getDefaultRootDirPath(), getHdfsDestinationDir(), false, false, false, true, true); 364 assertTrue(res == AbstractHBaseTool.EXIT_FAILURE); 365 } 366 367 private void testExportFileSystemState(final TableName tableName, final String snapshotName, 368 final String targetName, int filesExpected) throws Exception { 369 testExportFileSystemState(tableName, snapshotName, targetName, filesExpected, 370 getHdfsDestinationDir(), false); 371 } 372 373 protected void testExportFileSystemState(final TableName tableName, final String snapshotName, 374 final String targetName, int filesExpected, Path copyDir, boolean overwrite) throws Exception { 375 testExportFileSystemState(tableName, snapshotName, targetName, filesExpected, copyDir, 376 overwrite, false); 377 } 378 379 protected void testExportFileSystemState(final TableName tableName, final String snapshotName, 380 final String targetName, int filesExpected, Path copyDir, boolean overwrite, boolean resetTtl) 381 throws Exception { 382 testExportFileSystemState(TEST_UTIL.getConfiguration(), tableName, snapshotName, targetName, 383 filesExpected, TEST_UTIL.getDefaultRootDirPath(), copyDir, overwrite, resetTtl, 384 getBypassRegionPredicate(), true, false); 385 } 386 387 /** 388 * Creates destination directory, runs ExportSnapshot() tool, and runs some verifications. 389 */ 390 protected static void testExportFileSystemState(final Configuration conf, 391 final TableName tableName, final String snapshotName, final String targetName, 392 final int filesExpected, final Path srcDir, Path rawTgtDir, final boolean overwrite, 393 final boolean resetTtl, final RegionPredicate bypassregionPredicate, final boolean success, 394 final boolean checksumVerify) throws Exception { 395 FileSystem tgtFs = rawTgtDir.getFileSystem(conf); 396 FileSystem srcFs = srcDir.getFileSystem(conf); 397 Path tgtDir = rawTgtDir.makeQualified(tgtFs.getUri(), tgtFs.getWorkingDirectory()); 398 399 // Export Snapshot 400 int res = runExportSnapshot(conf, snapshotName, targetName, srcDir, rawTgtDir, overwrite, 401 resetTtl, checksumVerify, true, true); 402 assertEquals("success " + success + ", res=" + res, success ? 0 : 1, res); 403 if (!success) { 404 final Path targetDir = new Path(HConstants.SNAPSHOT_DIR_NAME, targetName); 405 assertFalse(tgtDir.toString() + " " + targetDir.toString(), 406 tgtFs.exists(new Path(tgtDir, targetDir))); 407 return; 408 } 409 LOG.info("Exported snapshot"); 410 411 // Verify File-System state 412 FileStatus[] rootFiles = tgtFs.listStatus(tgtDir); 413 assertEquals(filesExpected > 0 ? 2 : 1, rootFiles.length); 414 for (FileStatus fileStatus : rootFiles) { 415 String name = fileStatus.getPath().getName(); 416 assertTrue(fileStatus.toString(), fileStatus.isDirectory()); 417 assertTrue(name.toString(), name.equals(HConstants.SNAPSHOT_DIR_NAME) 418 || name.equals(HConstants.HFILE_ARCHIVE_DIRECTORY)); 419 } 420 LOG.info("Verified filesystem state"); 421 422 // Compare the snapshot metadata and verify the hfiles 423 final Path snapshotDir = new Path(HConstants.SNAPSHOT_DIR_NAME, snapshotName); 424 final Path targetDir = new Path(HConstants.SNAPSHOT_DIR_NAME, targetName); 425 verifySnapshotDir(srcFs, new Path(srcDir, snapshotDir), tgtFs, new Path(tgtDir, targetDir)); 426 Set<String> snapshotFiles = 427 verifySnapshot(conf, tgtFs, tgtDir, tableName, targetName, resetTtl, bypassregionPredicate); 428 assertEquals(filesExpected, snapshotFiles.size()); 429 } 430 431 /* 432 * verify if the snapshot folder on file-system 1 match the one on file-system 2 433 */ 434 protected static void verifySnapshotDir(final FileSystem fs1, final Path root1, 435 final FileSystem fs2, final Path root2) throws IOException { 436 assertEquals(listFiles(fs1, root1, root1), listFiles(fs2, root2, root2)); 437 } 438 439 /* 440 * Verify if the files exists 441 */ 442 protected static Set<String> verifySnapshot(final Configuration conf, final FileSystem fs, 443 final Path rootDir, final TableName tableName, final String snapshotName, 444 final boolean resetTtl, final RegionPredicate bypassregionPredicate) throws IOException { 445 final Path exportedSnapshot = 446 new Path(rootDir, new Path(HConstants.SNAPSHOT_DIR_NAME, snapshotName)); 447 final Set<String> snapshotFiles = new HashSet<>(); 448 final Path exportedArchive = new Path(rootDir, HConstants.HFILE_ARCHIVE_DIRECTORY); 449 SnapshotReferenceUtil.visitReferencedFiles(conf, fs, exportedSnapshot, 450 new SnapshotReferenceUtil.SnapshotVisitor() { 451 @Override 452 public void storeFile(final RegionInfo regionInfo, final String family, 453 final SnapshotRegionManifest.StoreFile storeFile) throws IOException { 454 if (bypassregionPredicate != null && bypassregionPredicate.evaluate(regionInfo)) { 455 return; 456 } 457 458 if (!storeFile.hasReference() && !StoreFileInfo.isReference(storeFile.getName())) { 459 String hfile = storeFile.getName(); 460 snapshotFiles.add(hfile); 461 verifyNonEmptyFile(new Path(exportedArchive, 462 new Path(CommonFSUtils.getTableDir(new Path("./"), tableName), 463 new Path(regionInfo.getEncodedName(), new Path(family, hfile))))); 464 } else { 465 Pair<String, String> referredToRegionAndFile = 466 StoreFileInfo.getReferredToRegionAndFile(storeFile.getName()); 467 String region = referredToRegionAndFile.getFirst(); 468 String hfile = referredToRegionAndFile.getSecond(); 469 snapshotFiles.add(hfile); 470 verifyNonEmptyFile(new Path(exportedArchive, 471 new Path(CommonFSUtils.getTableDir(new Path("./"), tableName), 472 new Path(region, new Path(family, hfile))))); 473 } 474 } 475 476 private void verifyNonEmptyFile(final Path path) throws IOException { 477 assertTrue(path + " should exists", fs.exists(path)); 478 assertTrue(path + " should not be empty", fs.getFileStatus(path).getLen() > 0); 479 } 480 }); 481 482 // Verify Snapshot description 483 SnapshotDescription desc = SnapshotDescriptionUtils.readSnapshotInfo(fs, exportedSnapshot); 484 assertTrue(desc.getName().equals(snapshotName)); 485 assertTrue(desc.getTable().equals(tableName.getNameAsString())); 486 if (resetTtl) { 487 assertEquals(HConstants.DEFAULT_SNAPSHOT_TTL, desc.getTtl()); 488 } 489 return snapshotFiles; 490 } 491 492 private static Set<String> listFiles(final FileSystem fs, final Path root, final Path dir) 493 throws IOException { 494 Set<String> files = new HashSet<>(); 495 LOG.debug("List files in {} in root {} at {}", fs, root, dir); 496 int rootPrefix = root.makeQualified(fs.getUri(), fs.getWorkingDirectory()).toString().length(); 497 FileStatus[] list = CommonFSUtils.listStatus(fs, dir); 498 if (list != null) { 499 for (FileStatus fstat : list) { 500 LOG.debug(Objects.toString(fstat.getPath())); 501 if (fstat.isDirectory()) { 502 files.addAll(listFiles(fs, root, fstat.getPath())); 503 } else { 504 files.add(fstat.getPath().makeQualified(fs).toString().substring(rootPrefix)); 505 } 506 } 507 } 508 return files; 509 } 510 511 private Path getHdfsDestinationDir() { 512 Path rootDir = TEST_UTIL.getHBaseCluster().getMaster().getMasterFileSystem().getRootDir(); 513 Path path = 514 new Path(new Path(rootDir, "export-test"), "export-" + EnvironmentEdgeManager.currentTime()); 515 LOG.info("HDFS export destination path: " + path); 516 return path; 517 } 518 519 static Path getLocalDestinationDir(HBaseTestingUtil htu) { 520 Path path = htu.getDataTestDir("local-export-" + EnvironmentEdgeManager.currentTime()); 521 try { 522 FileSystem fs = FileSystem.getLocal(htu.getConfiguration()); 523 LOG.info("Local export destination path: " + path); 524 return path.makeQualified(fs.getUri(), fs.getWorkingDirectory()); 525 } catch (IOException ioe) { 526 throw new RuntimeException(ioe); 527 } 528 } 529 530 private static void removeExportDir(final Path path) throws IOException { 531 FileSystem fs = FileSystem.get(path.toUri(), new Configuration()); 532 fs.delete(path, true); 533 } 534 535 private static int runExportSnapshot(final Configuration conf, final String sourceSnapshotName, 536 final String targetSnapshotName, final Path srcDir, Path rawTgtDir, final boolean overwrite, 537 final boolean resetTtl, final boolean checksumVerify, final boolean noSourceVerify, 538 final boolean noTargetVerify) throws Exception { 539 FileSystem tgtFs = rawTgtDir.getFileSystem(conf); 540 FileSystem srcFs = srcDir.getFileSystem(conf); 541 Path tgtDir = rawTgtDir.makeQualified(tgtFs.getUri(), tgtFs.getWorkingDirectory()); 542 LOG.info("tgtFsUri={}, tgtDir={}, rawTgtDir={}, srcFsUri={}, srcDir={}", tgtFs.getUri(), tgtDir, 543 rawTgtDir, srcFs.getUri(), srcDir); 544 List<String> opts = new ArrayList<>(); 545 opts.add("--snapshot"); 546 opts.add(sourceSnapshotName); 547 opts.add("--copy-to"); 548 opts.add(tgtDir.toString()); 549 if (!targetSnapshotName.equals(sourceSnapshotName)) { 550 opts.add("--target"); 551 opts.add(targetSnapshotName); 552 } 553 if (overwrite) { 554 opts.add("--overwrite"); 555 } 556 if (resetTtl) { 557 opts.add("--reset-ttl"); 558 } 559 if (!checksumVerify) { 560 opts.add("--no-checksum-verify"); 561 } 562 if (!noSourceVerify) { 563 opts.add("--no-source-verify"); 564 } 565 if (!noTargetVerify) { 566 opts.add("--no-target-verify"); 567 } 568 569 // Export Snapshot 570 return run(conf, new ExportSnapshot(), opts.toArray(new String[opts.size()])); 571 } 572}