HBASE-14302 TableSnapshotInputFormat should not create back references when restoring snapshot
This commit is contained in:
parent
d0873f5a8c
commit
44caba31e4
@ -321,9 +321,30 @@ public class HFileLink extends FileLink {
|
|||||||
public static boolean create(final Configuration conf, final FileSystem fs,
|
public static boolean create(final Configuration conf, final FileSystem fs,
|
||||||
final Path dstFamilyPath, final HRegionInfo hfileRegionInfo,
|
final Path dstFamilyPath, final HRegionInfo hfileRegionInfo,
|
||||||
final String hfileName) throws IOException {
|
final String hfileName) throws IOException {
|
||||||
|
return create(conf, fs, dstFamilyPath, hfileRegionInfo, hfileName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new HFileLink
|
||||||
|
*
|
||||||
|
* <p>It also adds a back-reference to the hfile back-reference directory
|
||||||
|
* to simplify the reference-count and the cleaning process.
|
||||||
|
*
|
||||||
|
* @param conf {@link Configuration} to read for the archive directory name
|
||||||
|
* @param fs {@link FileSystem} on which to write the HFileLink
|
||||||
|
* @param dstFamilyPath - Destination path (table/region/cf/)
|
||||||
|
* @param hfileRegionInfo - Linked HFile Region Info
|
||||||
|
* @param hfileName - Linked HFile name
|
||||||
|
* @param createBackRef - Whether back reference should be created. Defaults to true.
|
||||||
|
* @return true if the file is created, otherwise the file exists.
|
||||||
|
* @throws IOException on file or parent directory creation failure
|
||||||
|
*/
|
||||||
|
public static boolean create(final Configuration conf, final FileSystem fs,
|
||||||
|
final Path dstFamilyPath, final HRegionInfo hfileRegionInfo,
|
||||||
|
final String hfileName, final boolean createBackRef) throws IOException {
|
||||||
TableName linkedTable = hfileRegionInfo.getTable();
|
TableName linkedTable = hfileRegionInfo.getTable();
|
||||||
String linkedRegion = hfileRegionInfo.getEncodedName();
|
String linkedRegion = hfileRegionInfo.getEncodedName();
|
||||||
return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName);
|
return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName, createBackRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -344,6 +365,28 @@ public class HFileLink extends FileLink {
|
|||||||
public static boolean create(final Configuration conf, final FileSystem fs,
|
public static boolean create(final Configuration conf, final FileSystem fs,
|
||||||
final Path dstFamilyPath, final TableName linkedTable, final String linkedRegion,
|
final Path dstFamilyPath, final TableName linkedTable, final String linkedRegion,
|
||||||
final String hfileName) throws IOException {
|
final String hfileName) throws IOException {
|
||||||
|
return create(conf, fs, dstFamilyPath, linkedTable, linkedRegion, hfileName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new HFileLink
|
||||||
|
*
|
||||||
|
* <p>It also adds a back-reference to the hfile back-reference directory
|
||||||
|
* to simplify the reference-count and the cleaning process.
|
||||||
|
*
|
||||||
|
* @param conf {@link Configuration} to read for the archive directory name
|
||||||
|
* @param fs {@link FileSystem} on which to write the HFileLink
|
||||||
|
* @param dstFamilyPath - Destination path (table/region/cf/)
|
||||||
|
* @param linkedTable - Linked Table Name
|
||||||
|
* @param linkedRegion - Linked Region Name
|
||||||
|
* @param hfileName - Linked HFile name
|
||||||
|
* @param createBackRef - Whether back reference should be created. Defaults to true.
|
||||||
|
* @return true if the file is created, otherwise the file exists.
|
||||||
|
* @throws IOException on file or parent directory creation failure
|
||||||
|
*/
|
||||||
|
public static boolean create(final Configuration conf, final FileSystem fs,
|
||||||
|
final Path dstFamilyPath, final TableName linkedTable, final String linkedRegion,
|
||||||
|
final String hfileName, final boolean createBackRef) throws IOException {
|
||||||
String familyName = dstFamilyPath.getName();
|
String familyName = dstFamilyPath.getName();
|
||||||
String regionName = dstFamilyPath.getParent().getName();
|
String regionName = dstFamilyPath.getParent().getName();
|
||||||
String tableName = FSUtils.getTableName(dstFamilyPath.getParent().getParent())
|
String tableName = FSUtils.getTableName(dstFamilyPath.getParent().getParent())
|
||||||
@ -358,19 +401,24 @@ public class HFileLink extends FileLink {
|
|||||||
// Make sure the FileLink reference directory exists
|
// Make sure the FileLink reference directory exists
|
||||||
Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(conf,
|
Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(conf,
|
||||||
linkedTable, linkedRegion, familyName);
|
linkedTable, linkedRegion, familyName);
|
||||||
Path backRefssDir = getBackReferencesDir(archiveStoreDir, hfileName);
|
Path backRefPath = null;
|
||||||
fs.mkdirs(backRefssDir);
|
if (createBackRef) {
|
||||||
|
Path backRefssDir = getBackReferencesDir(archiveStoreDir, hfileName);
|
||||||
|
fs.mkdirs(backRefssDir);
|
||||||
|
|
||||||
// Create the reference for the link
|
// Create the reference for the link
|
||||||
Path backRefPath = new Path(backRefssDir, refName);
|
backRefPath = new Path(backRefssDir, refName);
|
||||||
fs.createNewFile(backRefPath);
|
fs.createNewFile(backRefPath);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// Create the link
|
// Create the link
|
||||||
return fs.createNewFile(new Path(dstFamilyPath, name));
|
return fs.createNewFile(new Path(dstFamilyPath, name));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("couldn't create the link=" + name + " for " + dstFamilyPath, e);
|
LOG.error("couldn't create the link=" + name + " for " + dstFamilyPath, e);
|
||||||
// Revert the reference if the link creation failed
|
// Revert the reference if the link creation failed
|
||||||
fs.delete(backRefPath, false);
|
if (createBackRef) {
|
||||||
|
fs.delete(backRefPath, false);
|
||||||
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -389,13 +437,34 @@ public class HFileLink extends FileLink {
|
|||||||
* @throws IOException on file or parent directory creation failure
|
* @throws IOException on file or parent directory creation failure
|
||||||
*/
|
*/
|
||||||
public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
|
public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
|
||||||
final Path dstFamilyPath, final String hfileLinkName) throws IOException {
|
final Path dstFamilyPath, final String hfileLinkName)
|
||||||
|
throws IOException {
|
||||||
|
return createFromHFileLink(conf, fs, dstFamilyPath, hfileLinkName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new HFileLink starting from a hfileLink name
|
||||||
|
*
|
||||||
|
* <p>It also adds a back-reference to the hfile back-reference directory
|
||||||
|
* to simplify the reference-count and the cleaning process.
|
||||||
|
*
|
||||||
|
* @param conf {@link Configuration} to read for the archive directory name
|
||||||
|
* @param fs {@link FileSystem} on which to write the HFileLink
|
||||||
|
* @param dstFamilyPath - Destination path (table/region/cf/)
|
||||||
|
* @param hfileLinkName - HFileLink name (it contains hfile-region-table)
|
||||||
|
* @param createBackRef - Whether back reference should be created. Defaults to true.
|
||||||
|
* @return true if the file is created, otherwise the file exists.
|
||||||
|
* @throws IOException on file or parent directory creation failure
|
||||||
|
*/
|
||||||
|
public static boolean createFromHFileLink(final Configuration conf, final FileSystem fs,
|
||||||
|
final Path dstFamilyPath, final String hfileLinkName, final boolean createBackRef)
|
||||||
|
throws IOException {
|
||||||
Matcher m = LINK_NAME_PATTERN.matcher(hfileLinkName);
|
Matcher m = LINK_NAME_PATTERN.matcher(hfileLinkName);
|
||||||
if (!m.matches()) {
|
if (!m.matches()) {
|
||||||
throw new IllegalArgumentException(hfileLinkName + " is not a valid HFileLink name!");
|
throw new IllegalArgumentException(hfileLinkName + " is not a valid HFileLink name!");
|
||||||
}
|
}
|
||||||
return create(conf, fs, dstFamilyPath, TableName.valueOf(m.group(1), m.group(2)),
|
return create(conf, fs, dstFamilyPath, TableName.valueOf(m.group(1), m.group(2)),
|
||||||
m.group(3), m.group(4));
|
m.group(3), m.group(4), createBackRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,6 +127,7 @@ public class RestoreSnapshotHelper {
|
|||||||
|
|
||||||
private final Configuration conf;
|
private final Configuration conf;
|
||||||
private final FileSystem fs;
|
private final FileSystem fs;
|
||||||
|
private final boolean createBackRefs;
|
||||||
|
|
||||||
public RestoreSnapshotHelper(final Configuration conf,
|
public RestoreSnapshotHelper(final Configuration conf,
|
||||||
final FileSystem fs,
|
final FileSystem fs,
|
||||||
@ -134,7 +135,18 @@ public class RestoreSnapshotHelper {
|
|||||||
final HTableDescriptor tableDescriptor,
|
final HTableDescriptor tableDescriptor,
|
||||||
final Path rootDir,
|
final Path rootDir,
|
||||||
final ForeignExceptionDispatcher monitor,
|
final ForeignExceptionDispatcher monitor,
|
||||||
final MonitoredTask status)
|
final MonitoredTask status) {
|
||||||
|
this(conf, fs, manifest, tableDescriptor, rootDir, monitor, status, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RestoreSnapshotHelper(final Configuration conf,
|
||||||
|
final FileSystem fs,
|
||||||
|
final SnapshotManifest manifest,
|
||||||
|
final HTableDescriptor tableDescriptor,
|
||||||
|
final Path rootDir,
|
||||||
|
final ForeignExceptionDispatcher monitor,
|
||||||
|
final MonitoredTask status,
|
||||||
|
final boolean createBackRefs)
|
||||||
{
|
{
|
||||||
this.fs = fs;
|
this.fs = fs;
|
||||||
this.conf = conf;
|
this.conf = conf;
|
||||||
@ -146,6 +158,7 @@ public class RestoreSnapshotHelper {
|
|||||||
this.tableDir = FSUtils.getTableDir(rootDir, tableDesc.getTableName());
|
this.tableDir = FSUtils.getTableDir(rootDir, tableDesc.getTableName());
|
||||||
this.monitor = monitor;
|
this.monitor = monitor;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
this.createBackRefs = createBackRefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -484,7 +497,7 @@ public class RestoreSnapshotHelper {
|
|||||||
for (SnapshotRegionManifest.StoreFile storeFile: hfilesToAdd) {
|
for (SnapshotRegionManifest.StoreFile storeFile: hfilesToAdd) {
|
||||||
LOG.debug("Adding HFileLink " + storeFile.getName() +
|
LOG.debug("Adding HFileLink " + storeFile.getName() +
|
||||||
" to region=" + regionInfo.getEncodedName() + " table=" + tableName);
|
" to region=" + regionInfo.getEncodedName() + " table=" + tableName);
|
||||||
restoreStoreFile(familyDir, regionInfo, storeFile);
|
restoreStoreFile(familyDir, regionInfo, storeFile, createBackRefs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Family doesn't exists in the snapshot
|
// Family doesn't exists in the snapshot
|
||||||
@ -505,7 +518,7 @@ public class RestoreSnapshotHelper {
|
|||||||
|
|
||||||
for (SnapshotRegionManifest.StoreFile storeFile: familyEntry.getValue()) {
|
for (SnapshotRegionManifest.StoreFile storeFile: familyEntry.getValue()) {
|
||||||
LOG.trace("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
|
LOG.trace("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
|
||||||
restoreStoreFile(familyDir, regionInfo, storeFile);
|
restoreStoreFile(familyDir, regionInfo, storeFile, createBackRefs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,7 +611,7 @@ public class RestoreSnapshotHelper {
|
|||||||
Path familyDir = new Path(regionDir, familyFiles.getFamilyName().toStringUtf8());
|
Path familyDir = new Path(regionDir, familyFiles.getFamilyName().toStringUtf8());
|
||||||
for (SnapshotRegionManifest.StoreFile storeFile: familyFiles.getStoreFilesList()) {
|
for (SnapshotRegionManifest.StoreFile storeFile: familyFiles.getStoreFilesList()) {
|
||||||
LOG.info("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
|
LOG.info("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
|
||||||
restoreStoreFile(familyDir, snapshotRegionInfo, storeFile);
|
restoreStoreFile(familyDir, snapshotRegionInfo, storeFile, createBackRefs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -630,17 +643,19 @@ public class RestoreSnapshotHelper {
|
|||||||
* </ul>
|
* </ul>
|
||||||
* @param familyDir destination directory for the store file
|
* @param familyDir destination directory for the store file
|
||||||
* @param regionInfo destination region info for the table
|
* @param regionInfo destination region info for the table
|
||||||
|
* @param createBackRef - Whether back reference should be created. Defaults to true.
|
||||||
* @param storeFile store file name (can be a Reference, HFileLink or simple HFile)
|
* @param storeFile store file name (can be a Reference, HFileLink or simple HFile)
|
||||||
*/
|
*/
|
||||||
private void restoreStoreFile(final Path familyDir, final HRegionInfo regionInfo,
|
private void restoreStoreFile(final Path familyDir, final HRegionInfo regionInfo,
|
||||||
final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
|
final SnapshotRegionManifest.StoreFile storeFile, final boolean createBackRef)
|
||||||
|
throws IOException {
|
||||||
String hfileName = storeFile.getName();
|
String hfileName = storeFile.getName();
|
||||||
if (HFileLink.isHFileLink(hfileName)) {
|
if (HFileLink.isHFileLink(hfileName)) {
|
||||||
HFileLink.createFromHFileLink(conf, fs, familyDir, hfileName);
|
HFileLink.createFromHFileLink(conf, fs, familyDir, hfileName, createBackRef);
|
||||||
} else if (StoreFileInfo.isReference(hfileName)) {
|
} else if (StoreFileInfo.isReference(hfileName)) {
|
||||||
restoreReferenceFile(familyDir, regionInfo, storeFile);
|
restoreReferenceFile(familyDir, regionInfo, storeFile);
|
||||||
} else {
|
} else {
|
||||||
HFileLink.create(conf, fs, familyDir, regionInfo, hfileName);
|
HFileLink.create(conf, fs, familyDir, regionInfo, hfileName, createBackRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -806,8 +821,10 @@ public class RestoreSnapshotHelper {
|
|||||||
"Restoring snapshot '" + snapshotName + "' to directory " + restoreDir);
|
"Restoring snapshot '" + snapshotName + "' to directory " + restoreDir);
|
||||||
ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher();
|
ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher();
|
||||||
|
|
||||||
|
// we send createBackRefs=false so that restored hfiles do not create back reference links
|
||||||
|
// in the base hbase root dir.
|
||||||
RestoreSnapshotHelper helper = new RestoreSnapshotHelper(conf, fs,
|
RestoreSnapshotHelper helper = new RestoreSnapshotHelper(conf, fs,
|
||||||
manifest, manifest.getTableDescriptor(), restoreDir, monitor, status);
|
manifest, manifest.getTableDescriptor(), restoreDir, monitor, status, false);
|
||||||
helper.restoreHdfsRegions(); // TODO: parallelize.
|
helper.restoreHdfsRegions(); // TODO: parallelize.
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
|
@ -23,7 +23,6 @@ import java.io.IOException;
|
|||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CompletionService;
|
import java.util.concurrent.CompletionService;
|
||||||
@ -33,7 +32,6 @@ import java.util.concurrent.ThreadFactory;
|
|||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.lang.RandomStringUtils;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
@ -44,10 +42,6 @@ import org.apache.hadoop.hbase.HRegionInfo;
|
|||||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||||
import org.apache.hadoop.hbase.regionserver.HRegion;
|
import org.apache.hadoop.hbase.regionserver.HRegion;
|
||||||
import org.apache.hadoop.hbase.master.AssignmentManager;
|
import org.apache.hadoop.hbase.master.AssignmentManager;
|
||||||
import org.apache.hadoop.hbase.regionserver.wal.MetricsWAL;
|
|
||||||
import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
|
|
||||||
import org.apache.hadoop.hbase.wal.WAL;
|
|
||||||
import org.apache.hadoop.hbase.wal.WALFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for interacting with the regions.
|
* Utility methods for interacting with the regions.
|
||||||
@ -176,11 +170,7 @@ public abstract class ModifyRegionUtils {
|
|||||||
// unless I pass along via the conf.
|
// unless I pass along via the conf.
|
||||||
Configuration confForWAL = new Configuration(conf);
|
Configuration confForWAL = new Configuration(conf);
|
||||||
confForWAL.set(HConstants.HBASE_DIR, rootDir.toString());
|
confForWAL.set(HConstants.HBASE_DIR, rootDir.toString());
|
||||||
WAL wal = (new WALFactory(confForWAL,
|
HRegion region = HRegion.createHRegion(newRegion, rootDir, conf, hTableDescriptor, null, false);
|
||||||
Collections.<WALActionsListener>singletonList(new MetricsWAL()),
|
|
||||||
"hregion-" + RandomStringUtils.randomNumeric(8))).
|
|
||||||
getWAL(newRegion.getEncodedNameAsBytes());
|
|
||||||
HRegion region = HRegion.createHRegion(newRegion, rootDir, conf, hTableDescriptor, wal, false);
|
|
||||||
try {
|
try {
|
||||||
// 2. Custom user code to interact with the created region
|
// 2. Custom user code to interact with the created region
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
@ -189,7 +179,6 @@ public abstract class ModifyRegionUtils {
|
|||||||
} finally {
|
} finally {
|
||||||
// 3. Close the new region to flush to disk. Close log file too.
|
// 3. Close the new region to flush to disk. Close log file too.
|
||||||
region.close();
|
region.close();
|
||||||
wal.close();
|
|
||||||
}
|
}
|
||||||
return region.getRegionInfo();
|
return region.getRegionInfo();
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,15 @@ public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBa
|
|||||||
testWithMapReduce(UTIL, "testWithMapReduceAndOfflineHBaseMultiRegion", 10, 10, true);
|
testWithMapReduce(UTIL, "testWithMapReduceAndOfflineHBaseMultiRegion", 10, 10, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,
|
||||||
|
String snapshotName, Path tmpTableDir) throws Exception {
|
||||||
|
JobConf job = new JobConf(UTIL.getConfiguration());
|
||||||
|
TableMapReduceUtil.initTableSnapshotMapJob(snapshotName,
|
||||||
|
COLUMNS, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,
|
||||||
|
NullWritable.class, job, false, tmpTableDir);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void testWithMockedMapReduce(HBaseTestingUtility util, String snapshotName,
|
protected void testWithMockedMapReduce(HBaseTestingUtility util, String snapshotName,
|
||||||
int numRegions, int expectedNumSplits) throws Exception {
|
int numRegions, int expectedNumSplits) throws Exception {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.apache.hadoop.hbase.mapreduce;
|
package org.apache.hadoop.hbase.mapreduce;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.FileStatus;
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.hbase.Cell;
|
import org.apache.hadoop.hbase.Cell;
|
||||||
@ -26,17 +27,21 @@ import org.apache.hadoop.hbase.CellScanner;
|
|||||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.client.Admin;
|
import org.apache.hadoop.hbase.client.Admin;
|
||||||
import org.apache.hadoop.hbase.client.HTable;
|
|
||||||
import org.apache.hadoop.hbase.client.Result;
|
import org.apache.hadoop.hbase.client.Result;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
|
import org.apache.hadoop.hbase.io.HFileLink;
|
||||||
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
||||||
import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
|
import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
|
||||||
|
import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
|
||||||
import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;
|
import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.FSUtils;
|
import org.apache.hadoop.hbase.util.FSUtils;
|
||||||
|
import org.apache.hadoop.hbase.util.HFileArchiveUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -102,6 +107,50 @@ public abstract class TableSnapshotInputFormatTestBase {
|
|||||||
testWithMapReduce(UTIL, "testWithMapReduceAndOfflineHBaseMultiRegion", 10, 8, true);
|
testWithMapReduce(UTIL, "testWithMapReduceAndOfflineHBaseMultiRegion", 10, 8, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that snapshot restore does not create back references in the HBase root dir.
|
||||||
|
@Test
|
||||||
|
public void testRestoreSnapshotDoesNotCreateBackRefLinks() throws Exception {
|
||||||
|
setupCluster();
|
||||||
|
TableName tableName = TableName.valueOf("testRestoreSnapshotDoesNotCreateBackRefLinks");
|
||||||
|
String snapshotName = "foo";
|
||||||
|
|
||||||
|
try {
|
||||||
|
createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);
|
||||||
|
|
||||||
|
Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);
|
||||||
|
|
||||||
|
testRestoreSnapshotDoesNotCreateBackRefLinksInit(tableName, snapshotName,tmpTableDir);
|
||||||
|
|
||||||
|
Path rootDir = FSUtils.getRootDir(UTIL.getConfiguration());
|
||||||
|
for (Path regionDir : FSUtils.getRegionDirs(fs, FSUtils.getTableDir(rootDir, tableName))) {
|
||||||
|
for (Path storeDir : FSUtils.getFamilyDirs(fs, regionDir)) {
|
||||||
|
for (FileStatus status : fs.listStatus(storeDir)) {
|
||||||
|
System.out.println(status.getPath());
|
||||||
|
if (StoreFileInfo.isValid(status)) {
|
||||||
|
Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(UTIL.getConfiguration(),
|
||||||
|
tableName, regionDir.getName(), storeDir.getName());
|
||||||
|
|
||||||
|
Path path = HFileLink.getBackReferencesDir(storeDir, status.getPath().getName());
|
||||||
|
// assert back references directory is empty
|
||||||
|
assertFalse("There is a back reference in " + path, fs.exists(path));
|
||||||
|
|
||||||
|
path = HFileLink.getBackReferencesDir(archiveStoreDir, status.getPath().getName());
|
||||||
|
// assert back references directory is empty
|
||||||
|
assertFalse("There is a back reference in " + path, fs.exists(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
UTIL.getHBaseAdmin().deleteSnapshot(snapshotName);
|
||||||
|
UTIL.deleteTable(tableName);
|
||||||
|
tearDownCluster();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,
|
||||||
|
String snapshotName, Path tmpTableDir) throws Exception;
|
||||||
|
|
||||||
protected void testWithMapReduce(HBaseTestingUtility util, String snapshotName,
|
protected void testWithMapReduce(HBaseTestingUtility util, String snapshotName,
|
||||||
int numRegions, int expectedNumSplits, boolean shutdownCluster) throws Exception {
|
int numRegions, int expectedNumSplits, boolean shutdownCluster) throws Exception {
|
||||||
setupCluster();
|
setupCluster();
|
||||||
|
@ -178,6 +178,16 @@ public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,
|
||||||
|
String snapshotName, Path tmpTableDir) throws Exception {
|
||||||
|
Job job = new Job(UTIL.getConfiguration());
|
||||||
|
TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,
|
||||||
|
new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,
|
||||||
|
NullWritable.class, job, false, tmpTableDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void testWithMockedMapReduce(HBaseTestingUtility util, String snapshotName,
|
public void testWithMockedMapReduce(HBaseTestingUtility util, String snapshotName,
|
||||||
int numRegions, int expectedNumSplits) throws Exception {
|
int numRegions, int expectedNumSplits) throws Exception {
|
||||||
setupCluster();
|
setupCluster();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user