Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ private CompletedSnapshotStore createCompletedSnapshotStore(
retrievedSnapshots.add(
checkNotNull(snapshotStateHandle.retrieveCompleteSnapshot()));
} catch (Exception e) {
if (e.getMessage()
.contains(CompletedSnapshot.SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE)) {
if (CompletedSnapshot.isSnapshotDataNotExists(e)) {
LOG.error(
"Metadata not found for snapshot {} of table bucket {}, maybe snapshot already removed or broken.",
snapshotStateHandle.getSnapshotId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public class CompletedSnapshot {

public static final String SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE = "No such file or directory";

private static final String HADOOP_SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE =
"File does not exist";

public CompletedSnapshot(
TableBucket tableBucket,
long snapshotID,
Expand Down Expand Up @@ -195,6 +198,24 @@ public static FsPath getMetadataFilePath(FsPath snapshotLocation) {
return new FsPath(snapshotLocation, SNAPSHOT_METADATA_FILE_NAME);
}

/**
* Returns whether the throwable or any of its causes indicates that snapshot data no longer
* exists in the remote storage.
*/
public static boolean isSnapshotDataNotExists(Throwable throwable) {
Throwable cause = throwable;
while (cause != null) {
String message = cause.getMessage();
if (message != null
&& (message.contains(SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE)
|| message.contains(HADOOP_SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE))) {
return true;
}
cause = cause.getCause();
}
return false;
}

private void disposeMetadata() throws IOException {
FsPath metadataFilePath = getMetadataFilePath();
FileSystem fileSystem = metadataFilePath.getFileSystem();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ private void downloadKvSnapshots(CompletedSnapshot completedSnapshot, Path kvTab
try {
kvSnapshotDataDownloader.transferAllDataToDirectory(downloadSpec, closeableRegistry);
} catch (Exception e) {
if (e.getMessage().contains(CompletedSnapshot.SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE)) {
if (CompletedSnapshot.isSnapshotDataNotExists(e)) {
try {
snapshotContext.handleSnapshotBroken(completedSnapshot);
} catch (Exception t) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ void testRemoveCompletedSnapshotStoreFromManager() throws Exception {

@Test
void testMetadataInconsistencyWithMetadataNotExistsException() throws Exception {
testMetadataInconsistencyWithMetadataNotExistsException(
CompletedSnapshot.SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE);
}

@Test
void testMetadataInconsistencyWithHadoopFileDoesNotExistException() throws Exception {
testMetadataInconsistencyWithMetadataNotExistsException(
"File does not exist: /remote/snapshot/CURRENT");
}

private void testMetadataInconsistencyWithMetadataNotExistsException(String errorMessage)
throws Exception {
// setup test data with mixed valid and invalid snapshots
TableBucket tableBucket = new TableBucket(1, 1);
CompletedSnapshot validSnapshot =
Expand All @@ -196,7 +208,7 @@ void testMetadataInconsistencyWithMetadataNotExistsException() throws Exception
CompletedSnapshot invalidSnapshot =
KvTestUtils.mockCompletedSnapshot(tempDir, tableBucket, 2L);
TestingCompletedSnapshotHandle invalidSnapshotHandle =
new TestingCompletedSnapshotHandleWithFileNotFound(invalidSnapshot);
new TestingCompletedSnapshotHandleWithFileNotFound(invalidSnapshot, errorMessage);

// create CompletedSnapshotHandleStore with real implementations
CompletedSnapshotHandleStore completedSnapshotHandleStore =
Expand Down Expand Up @@ -284,14 +296,17 @@ private Set<TableBucket> createTableBuckets(int tableNum, int bucketNum) {
private static class TestingCompletedSnapshotHandleWithFileNotFound
extends TestingCompletedSnapshotHandle {

public TestingCompletedSnapshotHandleWithFileNotFound(CompletedSnapshot snapshot) {
private final String errorMessage;

public TestingCompletedSnapshotHandleWithFileNotFound(
CompletedSnapshot snapshot, String errorMessage) {
super(snapshot, false);
this.errorMessage = errorMessage;
}

@Override
public CompletedSnapshot retrieveCompleteSnapshot() throws IOException {
throw new FileNotFoundException(
CompletedSnapshot.SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE);
throw new FileNotFoundException(errorMessage);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,28 @@ void testKvSnapshotSize(@TempDir Path tempDir) throws Exception {
assertThat(snapshot.getKvSnapshotHandle().getSnapshotSize()).isEqualTo(400L);
}

@Test
void testIsSnapshotDataNotExists() {
assertThat(
CompletedSnapshot.isSnapshotDataNotExists(
new IOException(
CompletedSnapshot.SNAPSHOT_DATA_NOT_EXISTS_ERROR_MESSAGE)))
.isTrue();
assertThat(
CompletedSnapshot.isSnapshotDataNotExists(
new IOException("File does not exist: /remote/snapshot/CURRENT")))
.isTrue();
assertThat(
CompletedSnapshot.isSnapshotDataNotExists(
new IOException(
"Failed to download snapshot.",
new IOException(
"File does not exist: /remote/snapshot/CURRENT"))))
.isTrue();
assertThat(CompletedSnapshot.isSnapshotDataNotExists(new IOException("Access denied")))
.isFalse();
}

private void checkCompletedSnapshotCleanUp(
Path snapshotPath, KvSnapshotHandle kvSnapshotHandle, boolean isShareFileShouldDelete) {
// private should be deleted, but the local file should still remain
Expand Down