Skip to content

Commit 1780ab6

Browse files
committed
HBASE-28806 ExportSnapshot failed if reference file presented
1 parent 0e1db79 commit 1780ab6

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/snapshot/ExportSnapshot.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import java.util.Comparator;
2929
import java.util.LinkedList;
3030
import java.util.List;
31+
import java.util.Set;
32+
import java.util.TreeSet;
3133
import java.util.concurrent.ExecutionException;
3234
import java.util.concurrent.ExecutorService;
3335
import java.util.concurrent.Executors;
@@ -659,6 +661,7 @@ private static List<Pair<SnapshotFileInfo, Long>> getSnapshotFiles(final Configu
659661

660662
// Get snapshot files
661663
LOG.info("Loading Snapshot '" + snapshotDesc.getName() + "' hfile list");
664+
Set<String> existingFiles = new TreeSet<>();
662665
SnapshotReferenceUtil.visitReferencedFiles(conf, fs, snapshotDir, snapshotDesc,
663666
new SnapshotReferenceUtil.SnapshotVisitor() {
664667
@Override
@@ -678,7 +681,13 @@ public void storeFile(final RegionInfo regionInfo, final String family,
678681
snapshotFileAndSize = getSnapshotFileAndSize(fs, conf, table, referencedRegion, family,
679682
referencedHFile, storeFile.hasFileSize() ? storeFile.getFileSize() : -1);
680683
}
681-
files.add(snapshotFileAndSize);
684+
String fileToExport = snapshotFileAndSize.getFirst().getHfile();
685+
if (!existingFiles.contains(fileToExport)) {
686+
files.add(snapshotFileAndSize);
687+
existingFiles.add(fileToExport);
688+
} else {
689+
LOG.debug("Skip the existing file: {}.", fileToExport);
690+
}
682691
}
683692
});
684693

hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/snapshot/TestExportSnapshot.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public static void setUpBaseConf(Configuration conf) {
106106
// If a single node has enough failures (default 3), resource manager will blacklist it.
107107
// With only 2 nodes and tests injecting faults, we don't want that.
108108
conf.setInt("mapreduce.job.maxtaskfailures.per.tracker", 100);
109+
conf.setInt("snapshot.export.default.map.group", 1);
109110
}
110111

111112
@BeforeClass
@@ -206,6 +207,48 @@ public void testExportFileSystemStateWithMergeRegion() throws Exception {
206207
TEST_UTIL.deleteTable(tableName0);
207208
}
208209

210+
@Test
211+
public void testExportFileSystemStateWithSplitRegion() throws Exception {
212+
// disable compaction
213+
admin.compactionSwitch(false,
214+
admin.getRegionServers().stream().map(a -> a.getServerName()).collect(Collectors.toList()));
215+
// create Table
216+
TableName splitTableName = TableName.valueOf(testName.getMethodName());
217+
String splitTableSnap = "snapshot-" + testName.getMethodName();
218+
admin.createTable(TableDescriptorBuilder.newBuilder(splitTableName).setColumnFamilies(
219+
Lists.newArrayList(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build())).build());
220+
221+
// put some data
222+
try (Table table = admin.getConnection().getTable(splitTableName)) {
223+
table.put(new Put(Bytes.toBytes("row1")).addColumn(FAMILY, null, Bytes.toBytes("value1")));
224+
table.put(new Put(Bytes.toBytes("row2")).addColumn(FAMILY, null, Bytes.toBytes("value2")));
225+
table.put(new Put(Bytes.toBytes("row3")).addColumn(FAMILY, null, Bytes.toBytes("value3")));
226+
table.put(new Put(Bytes.toBytes("row4")).addColumn(FAMILY, null, Bytes.toBytes("value4")));
227+
table.put(new Put(Bytes.toBytes("row5")).addColumn(FAMILY, null, Bytes.toBytes("value5")));
228+
table.put(new Put(Bytes.toBytes("row6")).addColumn(FAMILY, null, Bytes.toBytes("value6")));
229+
table.put(new Put(Bytes.toBytes("row7")).addColumn(FAMILY, null, Bytes.toBytes("value7")));
230+
table.put(new Put(Bytes.toBytes("row8")).addColumn(FAMILY, null, Bytes.toBytes("value8")));
231+
// Flush to HFile
232+
admin.flush(tableName);
233+
}
234+
235+
List<RegionInfo> regions = admin.getRegions(splitTableName);
236+
assertEquals(1, regions.size());
237+
tableNumFiles = regions.size();
238+
239+
// split region
240+
admin.split(splitTableName, Bytes.toBytes("row5"));
241+
regions = admin.getRegions(splitTableName);
242+
assertEquals(2, regions.size());
243+
244+
// take a snapshot
245+
admin.snapshot(splitTableSnap, splitTableName);
246+
// export snapshot and verify
247+
testExportFileSystemState(splitTableName, splitTableSnap, splitTableSnap, tableNumFiles);
248+
// delete table
249+
TEST_UTIL.deleteTable(splitTableName);
250+
}
251+
209252
@Test
210253
public void testExportFileSystemStateWithSkipTmp() throws Exception {
211254
TEST_UTIL.getConfiguration().setBoolean(ExportSnapshot.CONF_SKIP_TMP, true);

0 commit comments

Comments
 (0)