-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-28882 Backup restores are broken if the backup has moved locations #6294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -228,13 +228,15 @@ protected void copyMetaData(FileSystem fs, Path tmpBackupDir, Path backupDirPath | |
| if ( | ||
| fileName.indexOf(FSTableDescriptors.TABLEINFO_DIR) > 0 | ||
| || fileName.indexOf(HRegionFileSystem.REGION_INFO_FILE) > 0 | ||
| || fileName.indexOf(BackupManifest.MANIFEST_FILE_NAME) > 0 | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This becomes necessary because the manifest file would implicitly move to the tmp directory during the merge process, since it follows the application's working root dir rather than its original root dir. So, before this changeset, rewriting the manifest would always update the original root dir (where we want this eventually), but with this changeset rewriting the manifest would put it in the tmp dir. Since the tmp dir will be purged, we need to make sure we copy the manifest file out first
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a test that asserts that we haven't lost any critical components of a backup image during processing it?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not so specifically I suppose. But the larger tests do implicitly validate that — for example, I realized this change was necessary due to test failures
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While I agree with this change, I can't find what was changed that previously put the manifest in the correct location. Just curious.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question, this was confusing to me too. Before we stripped the root directory from the BackupImage, rewriting the manifest would implicitly always use the original root directory. So this only worked because we were unable to relocate backups |
||
| ) { | ||
| toKeep.add(p); | ||
| } | ||
| } | ||
| // Copy meta to destination | ||
| for (Path p : toKeep) { | ||
| Path newPath = convertToDest(p, backupDirPath); | ||
| LOG.info("Copying tmp metadata from {} to {}", p, newPath); | ||
| copyFile(fs, p, newPath); | ||
| } | ||
| } | ||
|
|
@@ -310,8 +312,11 @@ protected void updateBackupManifest(String backupRoot, String mergedBackupId, | |
| List<String> backupsToDelete) throws IllegalArgumentException, IOException { | ||
| BackupManifest manifest = | ||
| HBackupFileSystem.getManifest(conf, new Path(backupRoot), mergedBackupId); | ||
| LOG.info("Removing ancestors from merged backup {} : {}", mergedBackupId, backupsToDelete); | ||
| manifest.getBackupImage().removeAncestors(backupsToDelete); | ||
| // save back | ||
| LOG.info("Creating new manifest file for merged backup {} at root {}", mergedBackupId, | ||
| backupRoot); | ||
| manifest.store(conf); | ||
| } | ||
|
|
||
|
|
@@ -320,12 +325,14 @@ protected void deleteBackupImages(List<String> backupIds, Connection conn, FileS | |
| // Delete from backup system table | ||
| try (BackupSystemTable table = new BackupSystemTable(conn)) { | ||
| for (String backupId : backupIds) { | ||
| LOG.info("Removing metadata for backup {}", backupId); | ||
| table.deleteBackupInfo(backupId); | ||
| } | ||
| } | ||
|
|
||
| // Delete from file system | ||
| for (String backupId : backupIds) { | ||
| LOG.info("Purging backup {} from FileSystem", backupId); | ||
| Path backupDirPath = HBackupFileSystem.getBackupPath(backupRoot, backupId); | ||
|
|
||
| if (!fs.delete(backupDirPath, true)) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.apache.hadoop.hbase.backup; | ||
|
|
||
| import static org.junit.Assert.assertEquals; | ||
|
|
||
| import java.io.IOException; | ||
| import org.apache.hadoop.conf.Configuration; | ||
| import org.apache.hadoop.fs.Path; | ||
| import org.apache.hadoop.hbase.HBaseClassTestRule; | ||
| import org.apache.hadoop.hbase.testclassification.SmallTests; | ||
| import org.junit.ClassRule; | ||
| import org.junit.Test; | ||
| import org.junit.experimental.categories.Category; | ||
|
|
||
| @Category(SmallTests.class) | ||
| public class TestHBackupFileSystem { | ||
|
|
||
| @ClassRule | ||
| public static final HBaseClassTestRule CLASS_RULE = | ||
| HBaseClassTestRule.forClass(TestHBackupFileSystem.class); | ||
|
|
||
| private static final Path ROOT_DIR = new Path("/backup/root"); | ||
| private static final String BACKUP_ID = "123"; | ||
|
|
||
| @Test | ||
| public void testRootDirManifestPathConversion() throws IOException { | ||
| Path manifestPath = | ||
| HBackupFileSystem.getManifestPath(new Configuration(), ROOT_DIR, BACKUP_ID, false); | ||
| Path convertedRootDir = HBackupFileSystem.getRootDirFromBackupPath(manifestPath, BACKUP_ID); | ||
| assertEquals(ROOT_DIR, convertedRootDir); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.