Skip to content

Commit 90639d7

Browse files
authored
HBASE-28460 Full backup restore failed on empty HFiles (#5782)
Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
1 parent 6f236c0 commit 90639d7

3 files changed

Lines changed: 50 additions & 7 deletions

File tree

hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/mapreduce/MapReduceRestoreJob.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,7 @@ public void run(Path[] dirPaths, TableName[] tableNames, Path restoreRootDir,
8787
LOG.debug("Restoring HFiles from directory " + bulkOutputPath);
8888
}
8989

90-
if (loader.bulkLoad(newTableNames[i], bulkOutputPath).isEmpty()) {
91-
throw new IOException("Can not restore from backup directory " + dirs
92-
+ " (check Hadoop and HBase logs). Bulk loader returns null");
93-
}
90+
loader.bulkLoad(newTableNames[i], bulkOutputPath);
9491
} else {
9592
throw new IOException("Can not restore from backup directory " + dirs
9693
+ " (check Hadoop/MR and HBase logs). Player return code =" + result);

hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/util/RestoreTool.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
*/
6262
@InterfaceAudience.Private
6363
public class RestoreTool {
64-
public static final Logger LOG = LoggerFactory.getLogger(BackupUtils.class);
64+
public static final Logger LOG = LoggerFactory.getLogger(RestoreTool.class);
6565
private final static long TABLE_AVAILABILITY_WAIT_TIME = 180000;
6666

6767
private final String[] ignoreDirs = { HConstants.RECOVERED_EDITS_DIR };
@@ -437,6 +437,10 @@ byte[][] generateBoundaryKeys(ArrayList<Path> regionDirList) throws IOException
437437
HFile.Reader reader = HFile.createReader(fs, hfile, conf);
438438
final byte[] first, last;
439439
try {
440+
if (reader.getEntries() == 0) {
441+
LOG.debug("Skipping hfile with 0 entries: " + hfile);
442+
continue;
443+
}
440444
first = reader.getFirstRowKey().get();
441445
last = reader.getLastRowKey().get();
442446
LOG.debug("Trying to figure out region boundaries hfile=" + hfile + " first="
@@ -491,8 +495,12 @@ private void checkAndCreateTable(Connection conn, TableName targetTableName,
491495
admin.createTable(htd);
492496
} else {
493497
keys = generateBoundaryKeys(regionDirList);
494-
// create table using table descriptor and region boundaries
495-
admin.createTable(htd, keys);
498+
if (keys.length > 0) {
499+
// create table using table descriptor and region boundaries
500+
admin.createTable(htd, keys);
501+
} else {
502+
admin.createTable(htd);
503+
}
496504
}
497505
} catch (NamespaceNotFoundException e) {
498506
LOG.warn("There was no namespace and the same will be created");

hbase-backup/src/test/java/org/apache/hadoop/hbase/backup/TestFullRestore.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.hadoop.hbase.TableName;
2828
import org.apache.hadoop.hbase.backup.util.BackupUtils;
2929
import org.apache.hadoop.hbase.client.Admin;
30+
import org.apache.hadoop.hbase.client.Table;
3031
import org.apache.hadoop.hbase.testclassification.LargeTests;
3132
import org.apache.hadoop.util.ToolRunner;
3233
import org.junit.ClassRule;
@@ -71,6 +72,43 @@ public void testFullRestoreSingle() throws Exception {
7172
hba.close();
7273
}
7374

75+
@Test
76+
public void testFullRestoreSingleWithRegion() throws Exception {
77+
LOG.info("test full restore on a single table empty table that has a region");
78+
79+
// This test creates its own table so other tests are not affected (we adjust it in this test)
80+
TableName tableName = TableName.valueOf("table-full-restore-single-region");
81+
TEST_UTIL.createTable(tableName, famName);
82+
83+
Admin admin = TEST_UTIL.getAdmin();
84+
85+
// Add & remove data to ensure a region is active, but functionally empty
86+
Table table = TEST_UTIL.getConnection().getTable(tableName);
87+
loadTable(table);
88+
admin.flush(tableName);
89+
TEST_UTIL.deleteTableData(tableName);
90+
admin.flush(tableName);
91+
92+
TEST_UTIL.compact(tableName, true);
93+
94+
List<TableName> tables = Lists.newArrayList(tableName);
95+
String backupId = fullTableBackup(tables);
96+
assertTrue(checkSucceeded(backupId));
97+
98+
LOG.info("backup complete");
99+
100+
TEST_UTIL.deleteTable(tableName);
101+
102+
TableName[] tableset = new TableName[] { tableName };
103+
TableName[] tablemap = new TableName[] { tableName };
104+
BackupAdmin client = getBackupAdmin();
105+
client.restore(BackupUtils.createRestoreRequest(BACKUP_ROOT_DIR, backupId, false, tableset,
106+
tablemap, false));
107+
assertTrue(admin.tableExists(tableName));
108+
TEST_UTIL.deleteTable(tableName);
109+
admin.close();
110+
}
111+
74112
@Test
75113
public void testFullRestoreSingleCommand() throws Exception {
76114
LOG.info("test full restore on a single table empty table: command-line");

0 commit comments

Comments
 (0)