Skip to content
This repository has been archived by the owner on Nov 14, 2024. It is now read-only.

BackupService backwards compatibility #6040

Merged
merged 9 commits into from
May 26, 2022
Merged
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 @@ -17,6 +17,9 @@
package com.palantir.atlasdb.backup;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.google.common.annotations.VisibleForTesting;
import com.palantir.atlasdb.backup.api.AtlasService;
import com.palantir.atlasdb.backup.api.CompletedBackup;
import com.palantir.atlasdb.backup.api.InProgressBackupToken;
Expand All @@ -37,6 +40,9 @@ public class ExternalBackupPersister implements BackupPersister {
private static final SafeLogger log = SafeLoggerFactory.get(ExternalBackupPersister.class);

private static final ObjectMapper OBJECT_MAPPER = ObjectMappers.newClientObjectMapper();
private static final ObjectMapper LEGACY_OBJECT_MAPPER =
OBJECT_MAPPER.copy().setPropertyNamingStrategy(PropertyNamingStrategies.KEBAB_CASE);

private static final String SCHEMA_METADATA_FILE_NAME = "internal_schema_metadata_state";
private static final String BACKUP_TIMESTAMP_FILE_NAME = "backup.timestamp";
private static final String IMMUTABLE_TIMESTAMP_FILE_NAME = "immutable.timestamp";
Expand Down Expand Up @@ -138,21 +144,22 @@ private void writeToFile(AtlasService atlasService, File file, Object data) {
}
}

private <T> Optional<T> loadFromFile(AtlasService atlasService, File file, Class<T> clazz) {
@VisibleForTesting
<T> Optional<T> loadFromFile(AtlasService atlasService, File file, Class<T> clazz) {
if (!file.exists()) {
log.info(
"Tried to load file, but it did not exist",
SafeArg.of("fileName", file.getName()),
SafeArg.of("atlasService", atlasService));
SafeArg.of("namespace", atlasService.getNamespace()));
return Optional.empty();
}

try {
T state = OBJECT_MAPPER.readValue(file, clazz);
T state = tryLoadFromFile(file, clazz);
log.info(
"Successfully loaded file",
SafeArg.of("fileName", file.getName()),
SafeArg.of("atlasService", atlasService));
SafeArg.of("namespace", atlasService.getNamespace()));
return Optional.of(state);
} catch (IOException e) {
log.warn(
Expand All @@ -163,4 +170,13 @@ private <T> Optional<T> loadFromFile(AtlasService atlasService, File file, Class
return Optional.empty();
}
}

private <T> T tryLoadFromFile(File file, Class<T> clazz) throws IOException {
try {
return OBJECT_MAPPER.readValue(file, clazz);
} catch (MismatchedInputException e) {
log.debug("Using old mapper format", e);
return LEGACY_OBJECT_MAPPER.readValue(file, clazz);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@
import com.palantir.atlasdb.internalschema.InternalSchemaMetadataState;
import com.palantir.atlasdb.timelock.api.Namespace;
import com.palantir.lock.v2.LockToken;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.UUID;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -101,6 +105,22 @@ public void putAndGetCompletedBackup() {
assertThat(externalBackupPersister.getCompletedBackup(ATLAS_SERVICE)).contains(completedBackup);
}

@Test
public void testLegacyCasing() throws IOException {
String legacyState = "{\"value\":{\"value\":{\"timestampToTransactionsTableSchemaVersion\":{\"timestampMappings"
+ "\":[{\"longRange\":{\"lower-endpoint\":1316020054,\"lower-bound-type\":\"CLOSED\"},\"value\":3},{\"longRange\":{\"lower-endpoint\":1,\"lower-bound-type\":\"CLOSED\",\"upper-endpoint\":1316020054,\"upper-bound-type\":\"OPEN\"},\"value\":1}]}},\"bound\":1318613869}}";
File tempFile = tempFolder.newFile();
Files.copy(
new ByteArrayInputStream(legacyState.getBytes(StandardCharsets.UTF_8)),
tempFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);

InternalSchemaMetadataState parsed = externalBackupPersister
.loadFromFile(ATLAS_SERVICE, tempFile, InternalSchemaMetadataState.class)
.get();
assertThat(parsed).isNotNull();
}

private Path getPath(AtlasService atlasService) {
try {
return getOrCreateFolder(atlasService).toPath();
Expand Down
5 changes: 5 additions & 0 deletions changelog/0.610.0-rc1/pr-6040.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Backup Service can now deserialise metadata persisted from older formats.
links:
- https://github.com/palantir/atlasdb/pull/6040
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-6040.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Backup Service can now deserialise metadata persisted from older formats.
links:
- https://github.com/palantir/atlasdb/pull/6040