diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneSnapshot.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneSnapshot.java index b7bf7051caeb..360fd4cef6da 100644 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneSnapshot.java +++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneSnapshot.java @@ -192,7 +192,7 @@ public static OzoneSnapshot fromSnapshotInfo(SnapshotInfo snapshotInfo) { snapshotInfo.getSnapshotStatus(), snapshotInfo.getSnapshotId(), snapshotInfo.getSnapshotPath(), - snapshotInfo.getCheckpointDir(), + snapshotInfo.getCheckpointDirName(0), snapshotInfo.getReferencedSize(), snapshotInfo.getReferencedReplicatedSize(), snapshotInfo.getExclusiveSize() + snapshotInfo.getExclusiveSizeDeltaFromDirDeepCleaning(), @@ -222,4 +222,22 @@ public int hashCode() { return Objects.hash(volumeName, bucketName, name, creationTime, snapshotStatus, snapshotId, snapshotPath, checkpointDir, referencedSize, referencedReplicatedSize, exclusiveSize, exclusiveReplicatedSize); } + + @Override + public String toString() { + return "OzoneSnapshot{" + + "bucketName='" + bucketName + '\'' + + ", volumeName='" + volumeName + '\'' + + ", name='" + name + '\'' + + ", creationTime=" + creationTime + + ", snapshotStatus=" + snapshotStatus + + ", snapshotId=" + snapshotId + + ", snapshotPath='" + snapshotPath + '\'' + + ", checkpointDir='" + checkpointDir + '\'' + + ", referencedSize=" + referencedSize + + ", referencedReplicatedSize=" + referencedReplicatedSize + + ", exclusiveSize=" + exclusiveSize + + ", exclusiveReplicatedSize=" + exclusiveReplicatedSize + + '}'; + } } diff --git a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneSnapshot.java b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneSnapshot.java index 8980e28b59b4..028e937a9c2e 100644 --- a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneSnapshot.java +++ b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneSnapshot.java @@ -19,6 +19,7 @@ import static org.apache.hadoop.ozone.om.helpers.SnapshotInfo.SnapshotStatus.SNAPSHOT_ACTIVE; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import java.util.UUID; @@ -40,7 +41,7 @@ private SnapshotInfo getMockedSnapshotInfo(UUID snapshotId) { when(snapshotInfo.getSnapshotStatus()).thenReturn(SNAPSHOT_ACTIVE); when(snapshotInfo.getSnapshotId()).thenReturn(snapshotId); when(snapshotInfo.getSnapshotPath()).thenReturn("volume/bucket"); - when(snapshotInfo.getCheckpointDir()).thenReturn("checkpointDir"); + when(snapshotInfo.getCheckpointDirName(eq(0))).thenReturn("checkpointDir"); when(snapshotInfo.getReferencedSize()).thenReturn(1000L); when(snapshotInfo.getReferencedReplicatedSize()).thenReturn(3000L); when(snapshotInfo.getExclusiveSize()).thenReturn(4000L); diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/SnapshotInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/SnapshotInfo.java index cbc3709ea1e8..a26422cd81fb 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/SnapshotInfo.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/SnapshotInfo.java @@ -71,7 +71,6 @@ public final class SnapshotInfo implements Auditable, CopyObject { private UUID pathPreviousSnapshotId; private UUID globalPreviousSnapshotId; private String snapshotPath; // snapshot mask - private String checkpointDir; /** * RocksDB's transaction sequence number at the time of checkpoint creation. */ @@ -99,7 +98,6 @@ private SnapshotInfo(Builder b) { this.pathPreviousSnapshotId = b.pathPreviousSnapshotId; this.globalPreviousSnapshotId = b.globalPreviousSnapshotId; this.snapshotPath = b.snapshotPath; - this.checkpointDir = b.checkpointDir; this.dbTxSequenceNumber = b.dbTxSequenceNumber; this.deepClean = b.deepClean; this.sstFiltered = b.sstFiltered; @@ -150,10 +148,6 @@ public void setSnapshotPath(String snapshotPath) { this.snapshotPath = snapshotPath; } - public void setCheckpointDir(String checkpointDir) { - this.checkpointDir = checkpointDir; - } - public boolean isDeepCleaned() { return deepClean; } @@ -202,10 +196,6 @@ public String getSnapshotPath() { return snapshotPath; } - public String getCheckpointDir() { - return checkpointDir; - } - public boolean isSstFiltered() { return sstFiltered; } @@ -231,7 +221,6 @@ public SnapshotInfo.Builder toBuilder() { .setPathPreviousSnapshotId(pathPreviousSnapshotId) .setGlobalPreviousSnapshotId(globalPreviousSnapshotId) .setSnapshotPath(snapshotPath) - .setCheckpointDir(checkpointDir) .setDbTxSequenceNumber(dbTxSequenceNumber) .setDeepClean(deepClean) .setSstFiltered(sstFiltered) @@ -260,7 +249,6 @@ public static class Builder { private UUID pathPreviousSnapshotId; private UUID globalPreviousSnapshotId; private String snapshotPath; - private String checkpointDir; private long dbTxSequenceNumber; private boolean deepClean; private boolean sstFiltered; @@ -339,12 +327,6 @@ public Builder setSnapshotPath(String snapshotPath) { return this; } - /** @param checkpointDir - Snapshot checkpoint directory. */ - public Builder setCheckpointDir(String checkpointDir) { - this.checkpointDir = checkpointDir; - return this; - } - /** @param dbTxSequenceNumber - RDB latest transaction sequence number. */ public Builder setDbTxSequenceNumber(long dbTxSequenceNumber) { this.dbTxSequenceNumber = dbTxSequenceNumber; @@ -459,7 +441,6 @@ public OzoneManagerProtocolProtos.SnapshotInfo getProtobuf() { } sib.setSnapshotPath(snapshotPath) - .setCheckpointDir(checkpointDir) .setDbTxSequenceNumber(dbTxSequenceNumber) .setDeepClean(deepClean); return sib.build(); @@ -544,7 +525,6 @@ public static SnapshotInfo getFromProtobuf( } osib.setSnapshotPath(snapshotInfoProto.getSnapshotPath()) - .setCheckpointDir(snapshotInfoProto.getCheckpointDir()) .setDbTxSequenceNumber(snapshotInfoProto.getDbTxSequenceNumber()); return osib.build(); @@ -562,17 +542,20 @@ public Map toAuditMap() { /** * Get the name of the checkpoint directory. */ - public static String getCheckpointDirName(UUID snapshotId) { + public static String getCheckpointDirName(UUID snapshotId, int version) { Objects.requireNonNull(snapshotId, "SnapshotId is needed to create checkpoint directory"); - return OM_SNAPSHOT_SEPARATOR + snapshotId; + if (version == 0) { + return OM_SNAPSHOT_SEPARATOR + snapshotId; + } + return OM_SNAPSHOT_SEPARATOR + snapshotId + OM_SNAPSHOT_SEPARATOR + version; } /** * Get the name of the checkpoint directory, (non-static). */ - public String getCheckpointDirName() { - return getCheckpointDirName(getSnapshotId()); + public String getCheckpointDirName(int version) { + return getCheckpointDirName(getSnapshotId(), version); } public long getDbTxSequenceNumber() { @@ -703,10 +686,6 @@ public static SnapshotInfo newInstance(String volumeName, .setBucketName(bucketName) .setDeepClean(false) .setDeepCleanedDeletedDir(false); - - if (snapshotId != null) { - builder.setCheckpointDir(getCheckpointDirName(snapshotId)); - } return builder.build(); } @@ -729,7 +708,6 @@ public boolean equals(Object o) { Objects.equals( globalPreviousSnapshotId, that.globalPreviousSnapshotId) && snapshotPath.equals(that.snapshotPath) && - checkpointDir.equals(that.checkpointDir) && deepClean == that.deepClean && sstFiltered == that.sstFiltered && referencedSize == that.referencedSize && @@ -746,7 +724,7 @@ public int hashCode() { return Objects.hash(snapshotId, name, volumeName, bucketName, snapshotStatus, creationTime, deletionTime, pathPreviousSnapshotId, - globalPreviousSnapshotId, snapshotPath, checkpointDir, + globalPreviousSnapshotId, snapshotPath, deepClean, sstFiltered, referencedSize, referencedReplicatedSize, exclusiveSize, exclusiveReplicatedSize, deepCleanedDeletedDir, lastTransactionInfo, createTransactionInfo); @@ -773,7 +751,6 @@ public String toString() { ", pathPreviousSnapshotId: '" + pathPreviousSnapshotId + '\'' + ", globalPreviousSnapshotId: '" + globalPreviousSnapshotId + '\'' + ", snapshotPath: '" + snapshotPath + '\'' + - ", checkpointDir: '" + checkpointDir + '\'' + ", dbTxSequenceNumber: '" + dbTxSequenceNumber + '\'' + ", deepClean: '" + deepClean + '\'' + ", sstFiltered: '" + sstFiltered + '\'' + diff --git a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmSnapshotInfo.java b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmSnapshotInfo.java index 98cc035b3c07..e7695debd619 100644 --- a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmSnapshotInfo.java +++ b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmSnapshotInfo.java @@ -45,7 +45,6 @@ public class TestOmSnapshotInfo { private static final UUID GLOBAL_PREVIOUS_SNAPSHOT_ID = PATH_PREVIOUS_SNAPSHOT_ID; private static final String SNAPSHOT_PATH = "test/path"; - private static final String CHECKPOINT_DIR = "checkpoint.testdir"; private static final long DB_TX_SEQUENCE_NUMBER = 12345L; private SnapshotInfo createSnapshotInfo() { @@ -60,7 +59,6 @@ private SnapshotInfo createSnapshotInfo() { .setPathPreviousSnapshotId(PATH_PREVIOUS_SNAPSHOT_ID) .setGlobalPreviousSnapshotId(GLOBAL_PREVIOUS_SNAPSHOT_ID) .setSnapshotPath(SNAPSHOT_PATH) - .setCheckpointDir(CHECKPOINT_DIR) .setDbTxSequenceNumber(DB_TX_SEQUENCE_NUMBER) .setDeepClean(false) .setSstFiltered(false) @@ -86,7 +84,6 @@ private OzoneManagerProtocolProtos.SnapshotInfo createSnapshotInfoProto() { .setPathPreviousSnapshotID(toProtobuf(PATH_PREVIOUS_SNAPSHOT_ID)) .setGlobalPreviousSnapshotID(toProtobuf(GLOBAL_PREVIOUS_SNAPSHOT_ID)) .setSnapshotPath(SNAPSHOT_PATH) - .setCheckpointDir(CHECKPOINT_DIR) .setDbTxSequenceNumber(DB_TX_SEQUENCE_NUMBER) .setDeepClean(false) .setSstFiltered(false) diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFsSnapshot.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFsSnapshot.java index d02319a4cab6..6a97796af32b 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFsSnapshot.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFsSnapshot.java @@ -547,7 +547,7 @@ private String createSnapshot() throws Exception { SnapshotInfo snapshotInfo = ozoneManager.getMetadataManager() .getSnapshotInfoTable() .get(SnapshotInfo.getTableKey(VOLUME, BUCKET, snapshotName)); - String snapshotDirName = getSnapshotPath(conf, snapshotInfo) + + String snapshotDirName = getSnapshotPath(conf, snapshotInfo, 0) + OM_KEY_PREFIX + "CURRENT"; GenericTestUtils.waitFor(() -> new File(snapshotDirName).exists(), 1000, 100000); diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/freon/TestOMSnapshotDAG.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/freon/TestOMSnapshotDAG.java index 5429dc0f4a12..9f69ed51b7ca 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/freon/TestOMSnapshotDAG.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/freon/TestOMSnapshotDAG.java @@ -130,7 +130,7 @@ public static void shutdown() { } private String getDBCheckpointAbsolutePath(SnapshotInfo snapshotInfo) { - return OmSnapshotManager.getSnapshotPath(conf, snapshotInfo); + return OmSnapshotManager.getSnapshotPath(conf, snapshotInfo, 0); } private static String getSnapshotDBKey(String volumeName, String bucketName, diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java index 3d542785e113..d0b38116d5fa 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServlet.java @@ -733,7 +733,7 @@ private String createSnapshot(String vname, String bname) writeClient.createSnapshot(vname, bname, snapshotName); SnapshotInfo snapshotInfo = om.getMetadataManager().getSnapshotInfoTable() .get(SnapshotInfo.getTableKey(vname, bname, snapshotName)); - String snapshotPath = getSnapshotPath(conf, snapshotInfo) + String snapshotPath = getSnapshotPath(conf, snapshotInfo, 0) + OM_KEY_PREFIX; GenericTestUtils.waitFor(() -> new File(snapshotPath).exists(), 100, 30000); diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServletInodeBasedXfer.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServletInodeBasedXfer.java index f2b94182c809..a6ae3eaab21f 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServletInodeBasedXfer.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMDbCheckpointServletInodeBasedXfer.java @@ -240,7 +240,7 @@ public void write(int b) throws IOException { doCallRealMethod().when(omDbCheckpointServletMock) .transferSnapshotData(anySet(), any(), anySet(), any(), any(), anyMap()); doCallRealMethod().when(omDbCheckpointServletMock).createAndPrepareCheckpoint(anyBoolean()); - doCallRealMethod().when(omDbCheckpointServletMock).getSnapshotDirsFromDB(any()); + doCallRealMethod().when(omDbCheckpointServletMock).getSnapshotDirsFromDB(any(), any(), any()); } @ParameterizedTest @@ -748,7 +748,7 @@ private void setupClusterAndMocks(String volumeName, String bucketName, // Init the mock with the spyDbstore doCallRealMethod().when(omDbCheckpointServletMock).initialize(any(), any(), eq(false), any(), any(), eq(false)); - doCallRealMethod().when(omDbCheckpointServletMock).getSnapshotDirsFromDB(any()); + doCallRealMethod().when(omDbCheckpointServletMock).getSnapshotDirsFromDB(any(), any(), any()); omDbCheckpointServletMock.initialize(spyDbStore, om.getMetrics().getDBCheckpointMetrics(), false, om.getOmAdminUsernames(), om.getOmAdminGroups(), false); diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMRatisSnapshots.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMRatisSnapshots.java index a1de8fc377a0..3609703c7ef6 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMRatisSnapshots.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMRatisSnapshots.java @@ -337,11 +337,11 @@ private void checkSnapshot(OzoneManager leaderOM, OzoneManager followerOM, File followerMetaDir = OMStorage.getOmDbDir(followerOM.getConfiguration()); Path followerActiveDir = Paths.get(followerMetaDir.toString(), OM_DB_NAME); Path followerSnapshotDir = - Paths.get(getSnapshotPath(followerOM.getConfiguration(), snapshotInfo)); + Paths.get(getSnapshotPath(followerOM.getConfiguration(), snapshotInfo, 0)); File leaderMetaDir = OMStorage.getOmDbDir(leaderOM.getConfiguration()); Path leaderActiveDir = Paths.get(leaderMetaDir.toString(), OM_DB_NAME); Path leaderSnapshotDir = - Paths.get(getSnapshotPath(leaderOM.getConfiguration(), snapshotInfo)); + Paths.get(getSnapshotPath(leaderOM.getConfiguration(), snapshotInfo, 0)); // Get list of live files on the leader. RocksDB activeRocksDB = ((RDBStore) leaderOM.getMetadataManager().getStore()) @@ -1056,7 +1056,7 @@ private SnapshotInfo createOzoneSnapshot(OzoneManager leaderOM, String name) .get(tableKey); // Allow the snapshot to be written to disk String fileName = - getSnapshotPath(leaderOM.getConfiguration(), snapshotInfo); + getSnapshotPath(leaderOM.getConfiguration(), snapshotInfo, 0); File snapshotDir = new File(fileName); if (!RDBCheckpointUtils .waitForCheckpointDirectoryExist(snapshotDir)) { diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java index 93dba945d46d..19b237fe2600 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java @@ -1990,7 +1990,7 @@ private String createSnapshot(String volName, String buckName, .get(SnapshotInfo.getTableKey(volName, linkedBuckets.getOrDefault(buckName, buckName), snapshotName)); String snapshotDirName = OmSnapshotManager.getSnapshotPath(ozoneManager.getConfiguration(), - snapshotInfo) + OM_KEY_PREFIX + "CURRENT"; + snapshotInfo, 0) + OM_KEY_PREFIX + "CURRENT"; GenericTestUtils .waitFor(() -> new File(snapshotDirName).exists(), 1000, 120000); return snapshotKeyPrefix; diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotFileSystem.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotFileSystem.java index fca8b137b720..964513702a08 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotFileSystem.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotFileSystem.java @@ -709,7 +709,7 @@ private String createSnapshot(String snapshotName) SnapshotInfo snapshotInfo = ozoneManager.getMetadataManager() .getSnapshotInfoTable() .get(SnapshotInfo.getTableKey(snapshot.getVolumeName(), snapshot.getBucketName(), snapshotName)); - String snapshotDirName = getSnapshotPath(conf, snapshotInfo) + + String snapshotDirName = getSnapshotPath(conf, snapshotInfo, 0) + OM_KEY_PREFIX + "CURRENT"; GenericTestUtils.waitFor(() -> new File(snapshotDirName).exists(), 1000, 120000); diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerHASnapshot.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerHASnapshot.java index bae852ae3368..b6008ab3d2e2 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerHASnapshot.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerHASnapshot.java @@ -410,7 +410,7 @@ private void createSnapshot(String volName, String buckName, String snapName) th String tableKey = SnapshotInfo.getTableKey(volName, buckName, snapName); SnapshotInfo snapshotInfo = SnapshotUtils.getSnapshotInfo(cluster.getOMLeader(), tableKey); - String fileName = getSnapshotPath(cluster.getOMLeader().getConfiguration(), snapshotInfo); + String fileName = getSnapshotPath(cluster.getOMLeader().getConfiguration(), snapshotInfo, 0); File snapshotDir = new File(fileName); if (!RDBCheckpointUtils.waitForCheckpointDirectoryExist(snapshotDir)) { throw new IOException("Snapshot directory doesn't exist"); diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerSnapshotAcl.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerSnapshotAcl.java index f735ad15d295..455f1430d997 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerSnapshotAcl.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneManagerSnapshotAcl.java @@ -685,7 +685,7 @@ private void createSnapshot() .get(SnapshotInfo.getTableKey(volumeName, bucketName, snapshotName)); // Allow the snapshot to be written to disk String fileName = - getSnapshotPath(ozoneManager.getConfiguration(), snapshotInfo); + getSnapshotPath(ozoneManager.getConfiguration(), snapshotInfo, 0); File snapshotDir = new File(fileName); if (!RDBCheckpointUtils .waitForCheckpointDirectoryExist(snapshotDir)) { diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneSnapshotRestore.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneSnapshotRestore.java index 6c67554d7b8d..b2fde1f01960 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneSnapshotRestore.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOzoneSnapshotRestore.java @@ -159,7 +159,7 @@ private String createSnapshot(String volName, String buckName, .getSnapshotInfoTable() .get(SnapshotInfo.getTableKey(volName, buckName, snapshotName)); String snapshotDirName = OmSnapshotManager - .getSnapshotPath(clientConf, snapshotInfo) + OM_KEY_PREFIX + "CURRENT"; + .getSnapshotPath(clientConf, snapshotInfo, 0) + OM_KEY_PREFIX + "CURRENT"; GenericTestUtils.waitFor(() -> new File(snapshotDirName).exists(), 1000, 120000); return snapshotKeyPrefix; diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotBackgroundServices.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotBackgroundServices.java index a67a4599beee..eacde483d2ac 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotBackgroundServices.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotBackgroundServices.java @@ -633,7 +633,7 @@ private SnapshotInfo createOzoneSnapshot(OzoneManager leaderOM, String name) thr .getSnapshotInfoTable() .get(tableKey); // Allow the snapshot to be written to disk - String fileName = getSnapshotPath(leaderOM.getConfiguration(), snapshotInfo); + String fileName = getSnapshotPath(leaderOM.getConfiguration(), snapshotInfo, 0); File snapshotDir = new File(fileName); if (!RDBCheckpointUtils.waitForCheckpointDirectoryExist(snapshotDir)) { throw new IOException("snapshot directory doesn't exist"); diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index 61a3c1d6792e..1e5675f612e6 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -880,7 +880,7 @@ message SnapshotInfo { optional hadoop.hdds.UUID pathPreviousSnapshotID = 8; optional hadoop.hdds.UUID globalPreviousSnapshotID = 9; optional string snapshotPath = 10; - optional string checkpointDir = 11; + optional string checkpointDir = 11 [deprecated = true]; optional int64 dbTxSequenceNumber = 12; optional bool deepClean = 13; optional bool sstFiltered = 14; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java index 4d85e9f07472..efe9fc0aeea9 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServlet.java @@ -69,6 +69,7 @@ import org.apache.hadoop.ozone.lock.BootstrapStateHandler; import org.apache.hadoop.ozone.om.helpers.SnapshotInfo; import org.apache.hadoop.ozone.om.snapshot.OMDBCheckpointUtils; +import org.apache.hadoop.ozone.om.snapshot.OmSnapshotLocalDataManager; import org.apache.hadoop.ozone.om.snapshot.OmSnapshotUtils; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.Time; @@ -347,7 +348,8 @@ private Set getSnapshotDirs(DBCheckpoint checkpoint, boolean waitForDir) OzoneConfiguration conf = getConf(); Set snapshotPaths = new HashSet<>(); - + OzoneManager om = (OzoneManager) getServletContext().getAttribute(OzoneConsts.OM_CONTEXT_ATTRIBUTE); + OmSnapshotLocalDataManager snapshotLocalDataManager = om.getOmSnapshotManager().getSnapshotLocalDataManager(); // get snapshotInfo entries OmMetadataManagerImpl checkpointMetadataManager = OmMetadataManagerImpl.createCheckpointMetadataManager( @@ -359,11 +361,14 @@ private Set getSnapshotDirs(DBCheckpoint checkpoint, boolean waitForDir) // For each entry, wait for corresponding directory. while (iterator.hasNext()) { Table.KeyValue entry = iterator.next(); - Path path = Paths.get(getSnapshotPath(conf, entry.getValue())); - if (waitForDir) { - waitForDirToExist(path); + try (OmSnapshotLocalDataManager.ReadableOmSnapshotLocalDataMetaProvider snapMetaProvider = + snapshotLocalDataManager.getOmSnapshotLocalDataMeta(entry.getValue())) { + Path path = Paths.get(getSnapshotPath(conf, entry.getValue(), snapMetaProvider.getMeta().getVersion())); + if (waitForDir) { + waitForDirToExist(path); + } + snapshotPaths.add(path); } - snapshotPaths.add(path); } } finally { checkpointMetadataManager.stop(); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServletInodeBasedXfer.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServletInodeBasedXfer.java index 0c120ba080d6..748329be83ae 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServletInodeBasedXfer.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMDBCheckpointServletInodeBasedXfer.java @@ -27,6 +27,7 @@ import static org.apache.hadoop.ozone.OzoneConsts.ROCKSDB_SST_SUFFIX; import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_RATIS_SNAPSHOT_MAX_TOTAL_SST_SIZE_DEFAULT; import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_RATIS_SNAPSHOT_MAX_TOTAL_SST_SIZE_KEY; +import static org.apache.hadoop.ozone.om.OmSnapshotManager.getSnapshotPath; import static org.apache.hadoop.ozone.om.lock.FlatResource.SNAPSHOT_DB_LOCK; import static org.apache.hadoop.ozone.om.snapshot.OMDBCheckpointUtils.includeSnapshotData; import static org.apache.hadoop.ozone.om.snapshot.OMDBCheckpointUtils.logEstimatedTarballSize; @@ -211,6 +212,7 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina DBCheckpoint checkpoint = null; OzoneManager om = (OzoneManager) getServletContext().getAttribute(OzoneConsts.OM_CONTEXT_ATTRIBUTE); OMMetadataManager omMetadataManager = om.getMetadataManager(); + OmSnapshotLocalDataManager snapshotLocalDataManager = om.getOmSnapshotManager().getSnapshotLocalDataManager(); boolean includeSnapshotData = includeSnapshotData(request); AtomicLong maxTotalSstSize = new AtomicLong(getConf().getLong(OZONE_OM_RATIS_SNAPSHOT_MAX_TOTAL_SST_SIZE_KEY, OZONE_OM_RATIS_SNAPSHOT_MAX_TOTAL_SST_SIZE_DEFAULT)); @@ -220,7 +222,7 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina if (!includeSnapshotData) { maxTotalSstSize.set(Long.MAX_VALUE); } else { - snapshotPaths = getSnapshotDirsFromDB(omMetadataManager); + snapshotPaths = getSnapshotDirsFromDB(omMetadataManager, omMetadataManager, snapshotLocalDataManager); } if (sstFilesToExclude.isEmpty()) { @@ -267,7 +269,8 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina // get the list of snapshots from the checkpoint try (OmMetadataManagerImpl checkpointMetadataManager = OmMetadataManagerImpl .createCheckpointMetadataManager(om.getConfiguration(), checkpoint)) { - snapshotPaths = getSnapshotDirsFromDB(checkpointMetadataManager); + snapshotPaths = getSnapshotDirsFromDB(omMetadataManager, checkpointMetadataManager, + snapshotLocalDataManager); } writeDBToArchive(sstFilesToExclude, getCompactionLogDir(), maxTotalSstSize, archiveOutputStream, tmpdir, hardLinkFileMap, false); @@ -388,21 +391,24 @@ private OzoneConfiguration getConf() { /** * Collects paths to all snapshot databases from the OM DB. * - * @param omMetadataManager OMMetadataManager instance + * @param activeOMMetadataManager OMMetadataManager instance * @return Set of paths to snapshot databases * @throws IOException if an I/O error occurs */ - Set getSnapshotDirsFromDB(OMMetadataManager omMetadataManager) throws IOException { + Set getSnapshotDirsFromDB(OMMetadataManager activeOMMetadataManager, OMMetadataManager omMetadataManager, + OmSnapshotLocalDataManager localDataManager) throws IOException { Set snapshotPaths = new HashSet<>(); try (TableIterator> iter = omMetadataManager.getSnapshotInfoTable().iterator()) { while (iter.hasNext()) { Table.KeyValue kv = iter.next(); SnapshotInfo snapshotInfo = kv.getValue(); - String snapshotDir = OmSnapshotManager.getSnapshotPath(getConf(), - snapshotInfo.getCheckpointDirName()); - Path path = Paths.get(snapshotDir); - snapshotPaths.add(path); + try (OmSnapshotLocalDataManager.ReadableOmSnapshotLocalDataMetaProvider snapLocalMeta = + localDataManager.getOmSnapshotLocalDataMeta(snapshotInfo.getSnapshotId())) { + Path snapshotDir = getSnapshotPath(activeOMMetadataManager, snapshotInfo.getSnapshotId(), + snapLocalMeta.getMeta().getVersion()); + snapshotPaths.add(snapshotDir); + } } } return snapshotPaths; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java index 7b9beb80cf6f..0954b029ab67 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmSnapshotManager.java @@ -415,8 +415,12 @@ public OmSnapshot load(@Nonnull UUID snapshotId) throws IOException { "' with txnId : '" + TransactionInfo.fromByteString(snapshotInfo.getCreateTransactionInfo()) + "' has not been flushed yet. Please wait a few more seconds before retrying", TIMEOUT); } - snapshotMetadataManager = new OmMetadataManagerImpl(conf, - snapshotInfo.getCheckpointDirName(), maxOpenSstFilesInSnapshotDb); + try (OmSnapshotLocalDataManager.ReadableOmSnapshotLocalDataMetaProvider snapshotLocalDataProvider = + snapshotLocalDataManager.getOmSnapshotLocalDataMeta(snapshotInfo)) { + snapshotMetadataManager = new OmMetadataManagerImpl(conf, + snapshotInfo.getCheckpointDirName(snapshotLocalDataProvider.getMeta().getVersion()), + maxOpenSstFilesInSnapshotDb); + } } catch (IOException e) { LOG.error("Failed to retrieve snapshot: {}", snapshotTableKey, e); throw e; @@ -505,14 +509,12 @@ public static DBCheckpoint createOmSnapshotCheckpoint( boolean snapshotDirExist = false; // Create DB checkpoint for snapshot - String checkpointPrefix = store.getDbLocation().getName(); - Path snapshotDirPath = Paths.get(store.getSnapshotsParentDir(), - checkpointPrefix + snapshotInfo.getCheckpointDir()); + Path snapshotDirPath = getSnapshotPath(omMetadataManager, snapshotInfo, 0); if (Files.exists(snapshotDirPath)) { snapshotDirExist = true; dbCheckpoint = new RocksDBCheckpoint(snapshotDirPath); } else { - dbCheckpoint = store.getSnapshot(snapshotInfo.getCheckpointDirName()); + dbCheckpoint = store.getSnapshot(snapshotInfo.getCheckpointDirName(0)); } OmSnapshotManager omSnapshotManager = ((OmMetadataManagerImpl) omMetadataManager).getOzoneManager().getOmSnapshotManager(); @@ -796,27 +798,23 @@ public static String getSnapshotPrefix(String snapshotName) { snapshotName + OM_KEY_PREFIX; } - public static Path getSnapshotPath(OMMetadataManager omMetadataManager, SnapshotInfo snapshotInfo) { - RDBStore store = (RDBStore) omMetadataManager.getStore(); - String checkpointPrefix = store.getDbLocation().getName(); - return Paths.get(store.getSnapshotsParentDir(), - checkpointPrefix + snapshotInfo.getCheckpointDir()); + public static Path getSnapshotPath(OMMetadataManager omMetadataManager, SnapshotInfo snapshotInfo, int version) { + return getSnapshotPath(omMetadataManager, snapshotInfo.getSnapshotId(), version); } - public static Path getSnapshotPath(OMMetadataManager omMetadataManager, UUID snapshotId) { + public static Path getSnapshotPath(OMMetadataManager omMetadataManager, UUID snapshotId, int version) { RDBStore store = (RDBStore) omMetadataManager.getStore(); String checkpointPrefix = store.getDbLocation().getName(); return Paths.get(store.getSnapshotsParentDir(), - checkpointPrefix + SnapshotInfo.getCheckpointDirName(snapshotId)); + checkpointPrefix + SnapshotInfo.getCheckpointDirName(snapshotId, version)); } public static String getSnapshotPath(OzoneConfiguration conf, - SnapshotInfo snapshotInfo) { - return getSnapshotPath(conf, snapshotInfo.getCheckpointDirName()); + SnapshotInfo snapshotInfo, int version) { + return getSnapshotPath(conf, snapshotInfo.getCheckpointDirName(version)); } - public static String getSnapshotPath(OzoneConfiguration conf, - String checkpointDirName) { + private static String getSnapshotPath(OzoneConfiguration conf, String checkpointDirName) { return OMStorage.getOmDbDir(conf) + OM_KEY_PREFIX + OM_SNAPSHOT_CHECKPOINT_DIR + OM_KEY_PREFIX + OM_DB_NAME + checkpointDirName; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotDefragService.java index b99bb973931a..61b6cba68010 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotDefragService.java @@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting; import java.io.IOException; +import java.nio.file.Path; import java.util.Collections; import java.util.Iterator; import java.util.Optional; @@ -79,6 +80,7 @@ public class SnapshotDefragService extends BackgroundService private final AtomicBoolean running; private final MultiSnapshotLocks snapshotIdLocks; + private final OzoneConfiguration conf; private final BootstrapStateHandler.Lock lock = new BootstrapStateHandler.Lock(); @@ -90,6 +92,7 @@ public SnapshotDefragService(long interval, TimeUnit unit, long serviceTimeout, this.snapshotLimitPerTask = configuration .getLong(SNAPSHOT_DEFRAG_LIMIT_PER_TASK, SNAPSHOT_DEFRAG_LIMIT_PER_TASK_DEFAULT); + this.conf = configuration; snapshotsDefraggedCount = new AtomicLong(0); running = new AtomicBoolean(false); IOzoneManagerLock omLock = ozoneManager.getMetadataManager().getLock(); @@ -128,11 +131,14 @@ private boolean isRocksToolsNativeLibAvailable() { * Checks if a snapshot needs defragmentation by examining its YAML metadata. */ private boolean needsDefragmentation(SnapshotInfo snapshotInfo) { - String snapshotPath = OmSnapshotManager.getSnapshotPath( - ozoneManager.getConfiguration(), snapshotInfo); - + if (!SstFilteringService.isSstFiltered(conf, snapshotInfo)) { + return false; + } try (OmSnapshotLocalDataManager.ReadableOmSnapshotLocalDataProvider readableOmSnapshotLocalDataProvider = ozoneManager.getOmSnapshotManager().getSnapshotLocalDataManager().getOmSnapshotLocalData(snapshotInfo)) { + Path snapshotPath = OmSnapshotManager.getSnapshotPath( + ozoneManager.getMetadataManager(), snapshotInfo, + readableOmSnapshotLocalDataProvider.getSnapshotLocalData().getVersion()); // Read snapshot local metadata from YAML // Check if snapshot needs compaction (defragmentation) boolean needsDefrag = readableOmSnapshotLocalDataProvider.needsDefrag(); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SstFilteringService.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SstFilteringService.java index 522ea7df6de5..4b5002eb6c4a 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SstFilteringService.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SstFilteringService.java @@ -87,7 +87,7 @@ public class SstFilteringService extends BackgroundService public static boolean isSstFiltered(OzoneConfiguration ozoneConfiguration, SnapshotInfo snapshotInfo) { Path sstFilteredFile = Paths.get(OmSnapshotManager.getSnapshotPath(ozoneConfiguration, - snapshotInfo), SST_FILTERED_FILE); + snapshotInfo, 0), SST_FILTERED_FILE); return snapshotInfo.isSstFiltered() || sstFilteredFile.toFile().exists(); } @@ -138,7 +138,8 @@ private void markSSTFilteredFlagForSnapshot(SnapshotInfo snapshotInfo) throws IO .acquireReadLock(SNAPSHOT_DB_LOCK, snapshotInfo.getSnapshotId().toString()); boolean acquiredSnapshotLock = omLockDetails.isLockAcquired(); if (acquiredSnapshotLock) { - String snapshotDir = OmSnapshotManager.getSnapshotPath(ozoneManager.getConfiguration(), snapshotInfo); + // Ensure snapshot is sstFiltered before defrag. + String snapshotDir = OmSnapshotManager.getSnapshotPath(ozoneManager.getConfiguration(), snapshotInfo, 0); try { // mark the snapshot as filtered by creating a file. if (Files.exists(Paths.get(snapshotDir))) { diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotPurgeResponse.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotPurgeResponse.java index 8a370cb975e5..3bc8a8dc27bf 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotPurgeResponse.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotPurgeResponse.java @@ -109,7 +109,7 @@ protected void addToDBBatch(OMMetadataManager omMetadataManager, // snapshot purged txn is flushed to rocksdb. updateLocalData(snapshotLocalDataManager, snapshotInfo); // Delete Snapshot checkpoint directory. - deleteCheckpointDirectory(omMetadataManager, snapshotInfo); + deleteCheckpointDirectory(snapshotLocalDataManager, omMetadataManager, snapshotInfo); // Delete snapshotInfo from the table. omMetadataManager.getSnapshotInfoTable().deleteWithBatch(batchOperation, dbKey); } @@ -136,7 +136,8 @@ private void updateLocalData(OmSnapshotLocalDataManager localDataManager, Snapsh /** * Deletes the checkpoint directory for a snapshot. */ - private void deleteCheckpointDirectory(OMMetadataManager omMetadataManager, SnapshotInfo snapshotInfo) { + private void deleteCheckpointDirectory(OmSnapshotLocalDataManager snapshotLocalDataManager, + OMMetadataManager omMetadataManager, SnapshotInfo snapshotInfo) throws IOException { // Acquiring write lock to avoid race condition with sst filtering service which creates a sst filtered file // inside the snapshot directory. Any operation apart which doesn't create/delete files under this snapshot // directory can run in parallel along with this operation. @@ -144,14 +145,18 @@ private void deleteCheckpointDirectory(OMMetadataManager omMetadataManager, Snap .acquireWriteLock(SNAPSHOT_DB_LOCK, snapshotInfo.getSnapshotId().toString()); boolean acquiredSnapshotLock = omLockDetails.isLockAcquired(); if (acquiredSnapshotLock) { - Path snapshotDirPath = OmSnapshotManager.getSnapshotPath(omMetadataManager, snapshotInfo); - try { - FileUtils.deleteDirectory(snapshotDirPath.toFile()); - } catch (IOException ex) { - LOG.error("Failed to delete snapshot directory {} for snapshot {}", - snapshotDirPath, snapshotInfo.getTableKey(), ex); - } finally { - omMetadataManager.getLock().releaseWriteLock(SNAPSHOT_DB_LOCK, snapshotInfo.getSnapshotId().toString()); + try (OmSnapshotLocalDataManager.ReadableOmSnapshotLocalDataMetaProvider snapMetaProvider = + snapshotLocalDataManager.getOmSnapshotLocalDataMeta(snapshotInfo)) { + Path snapshotDirPath = OmSnapshotManager.getSnapshotPath(omMetadataManager, snapshotInfo, + snapMetaProvider.getMeta().getVersion()); + try { + FileUtils.deleteDirectory(snapshotDirPath.toFile()); + } catch (IOException ex) { + LOG.error("Failed to delete snapshot directory {} for snapshot {}", + snapshotDirPath, snapshotInfo.getTableKey(), ex); + } finally { + omMetadataManager.getLock().releaseWriteLock(SNAPSHOT_DB_LOCK, snapshotInfo.getSnapshotId().toString()); + } } } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java index 8298ba355442..33caddc92327 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java @@ -147,7 +147,7 @@ public String getSnapshotLocalPropertyYamlPath(SnapshotInfo snapshotInfo) { @VisibleForTesting public String getSnapshotLocalPropertyYamlPath(UUID snapshotId) { - Path snapshotPath = OmSnapshotManager.getSnapshotPath(omMetadataManager, snapshotId); + Path snapshotPath = OmSnapshotManager.getSnapshotPath(omMetadataManager, snapshotId, 0); return getSnapshotLocalPropertyYamlPath(snapshotPath); } @@ -167,6 +167,14 @@ public void createNewOmSnapshotLocalDataFile(RDBStore snapshotStore, SnapshotInf } } + public ReadableOmSnapshotLocalDataMetaProvider getOmSnapshotLocalDataMeta(SnapshotInfo snapInfo) throws IOException { + return getOmSnapshotLocalDataMeta(snapInfo.getSnapshotId()); + } + + public ReadableOmSnapshotLocalDataMetaProvider getOmSnapshotLocalDataMeta(UUID snapshotId) throws IOException { + return new ReadableOmSnapshotLocalDataMetaProvider(snapshotId); + } + public ReadableOmSnapshotLocalDataProvider getOmSnapshotLocalData(SnapshotInfo snapshotInfo) throws IOException { return getOmSnapshotLocalData(snapshotInfo.getSnapshotId()); } @@ -328,6 +336,15 @@ public void close() { } } + private HierarchicalResourceLock acquireLock(UUID snapId, boolean readLock) throws IOException { + HierarchicalResourceLock acquiredLock = readLock ? locks.acquireReadLock(FlatResource.SNAPSHOT_LOCAL_DATA_LOCK, + snapId.toString()) : locks.acquireWriteLock(FlatResource.SNAPSHOT_LOCAL_DATA_LOCK, snapId.toString()); + if (!acquiredLock.isLockAcquired()) { + throw new IOException("Unable to acquire lock for snapshotId: " + snapId); + } + return acquiredLock; + } + private static final class LockDataProviderInitResult { private final OmSnapshotLocalData snapshotLocalData; private final HierarchicalResourceLock lock; @@ -359,6 +376,34 @@ private OmSnapshotLocalData getSnapshotLocalData() { } } + /** + * Provides LocalData's metadata stored in memory for a snapshot after acquiring a read lock on this. + */ + public final class ReadableOmSnapshotLocalDataMetaProvider implements AutoCloseable { + private final SnapshotVersionsMeta meta; + private final HierarchicalResourceLock lock; + private boolean closed; + + private ReadableOmSnapshotLocalDataMetaProvider(UUID snapshotId) throws IOException { + this.lock = acquireLock(snapshotId, true); + this.meta = versionNodeMap.get(snapshotId); + this.closed = false; + } + + public synchronized SnapshotVersionsMeta getMeta() throws IOException { + if (closed) { + throw new IOException("Resource has already been closed."); + } + return meta; + } + + @Override + public synchronized void close() throws IOException { + closed = true; + lock.close(); + } + } + /** * The ReadableOmSnapshotLocalDataProvider class is responsible for managing the * access and initialization of local snapshot data in a thread-safe manner. @@ -441,15 +486,6 @@ public synchronized OmSnapshotLocalData getPreviousSnapshotLocalData() throws IO return previousSnapshotLocalData; } - private HierarchicalResourceLock acquireLock(UUID snapId, boolean readLock) throws IOException { - HierarchicalResourceLock acquiredLock = readLock ? locks.acquireReadLock(FlatResource.SNAPSHOT_LOCAL_DATA_LOCK, - snapId.toString()) : locks.acquireWriteLock(FlatResource.SNAPSHOT_LOCAL_DATA_LOCK, snapId.toString()); - if (!acquiredLock.isLockAcquired()) { - throw new IOException("Unable to acquire lock for snapshotId: " + snapId); - } - return acquiredLock; - } - /** * Intializes the snapshot local data by acquiring the lock on the snapshot and also acquires a read lock on the * snapshotId to be resolved by iterating through the chain of previous snapshot ids. @@ -806,7 +842,10 @@ public String toString() { } } - static final class SnapshotVersionsMeta { + /** + * Class that encapsulates the metadata corresponding to a snapshot's local data. + */ + public static final class SnapshotVersionsMeta { private final UUID previousSnapshotId; private final Map snapshotVersions; private int version; @@ -828,16 +867,16 @@ private Map getVersionNodes(OmSnapshotLocalData s return versionNodes; } - UUID getPreviousSnapshotId() { + public UUID getPreviousSnapshotId() { return previousSnapshotId; } - int getVersion() { + public int getVersion() { return version; } - Map getSnapshotVersions() { - return snapshotVersions; + private Map getSnapshotVersions() { + return Collections.unmodifiableMap(snapshotVersions); } LocalDataVersionNode getVersionNode(int snapshotVersion) { diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOmSnapshotManager.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOmSnapshotManager.java index 8f9375f39622..8c5ec7e5ab45 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOmSnapshotManager.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOmSnapshotManager.java @@ -37,7 +37,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -83,6 +85,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.MockedStatic; import org.slf4j.event.Level; /** @@ -663,6 +668,43 @@ void testProcessFileWithDestDirParameter(@TempDir File testDir) throws IOExcepti destAddNonSstToCopiedFiles); } + @ParameterizedTest + @ValueSource(ints = {0, 1, 10, 100}) + public void testGetSnapshotPath(int version) { + OMMetadataManager metadataManager = mock(OMMetadataManager.class); + RDBStore store = mock(RDBStore.class); + when(metadataManager.getStore()).thenReturn(store); + File file = new File("test-db"); + when(store.getDbLocation()).thenReturn(file); + String path = "dir1/dir2"; + when(store.getSnapshotsParentDir()).thenReturn(path); + UUID snapshotId = UUID.randomUUID(); + String snapshotPath = OmSnapshotManager.getSnapshotPath(metadataManager, snapshotId, version).toString(); + String expectedPath = "dir1/dir2/test-db-" + snapshotId; + if (version != 0) { + expectedPath = expectedPath + "-" + version; + } + assertEquals(expectedPath, snapshotPath); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1, 10, 100}) + public void testGetSnapshotPathFromConf(int version) { + try (MockedStatic mocked = mockStatic(OMStorage.class)) { + String omDir = "dir1/dir2"; + mocked.when(() -> OMStorage.getOmDbDir(any())).thenReturn(new File(omDir)); + OzoneConfiguration conf = mock(OzoneConfiguration.class); + SnapshotInfo snapshotInfo = createSnapshotInfo("volumeName", "bucketname"); + String snapshotPath = OmSnapshotManager.getSnapshotPath(conf, snapshotInfo, version); + String expectedPath = omDir + OM_KEY_PREFIX + OM_SNAPSHOT_CHECKPOINT_DIR + OM_KEY_PREFIX + + OM_DB_NAME + "-" + snapshotInfo.getSnapshotId(); + if (version != 0) { + expectedPath = expectedPath + "-" + version; + } + assertEquals(expectedPath, snapshotPath); + } + } + @Test public void testCreateSnapshotIdempotent() throws Exception { // set up db tables diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotCreateResponse.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotCreateResponse.java index 2cafae138fd4..6bef4b84247b 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotCreateResponse.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotCreateResponse.java @@ -131,7 +131,7 @@ public void testAddToDBBatch(int numberOfKeys) throws Exception { omMetadataManager.getStore().commitBatchOperation(batchOperation); // Confirm snapshot directory was created - String snapshotDir = getSnapshotPath(ozoneConfiguration, snapshotInfo); + String snapshotDir = getSnapshotPath(ozoneConfiguration, snapshotInfo, 0); assertTrue((new File(snapshotDir)).exists()); // Confirm table has 1 entry diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotDeleteResponse.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotDeleteResponse.java index 2d5d7b2870f7..bdb23b65f2c8 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotDeleteResponse.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotDeleteResponse.java @@ -117,7 +117,7 @@ public void testAddToDBBatch() throws Exception { // Confirm snapshot directory was created String snapshotDir = OmSnapshotManager.getSnapshotPath(ozoneConfiguration, - snapshotInfo); + snapshotInfo, 0); assertTrue((new File(snapshotDir)).exists()); // Confirm table has 1 entry diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java index 8554d1684e26..df26fa742e84 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java @@ -256,7 +256,7 @@ private List createSnapshotLocalData(OmSnapshotLocalDataManager snapshotLo private void mockSnapshotStore(UUID snapshotId, List sstFiles) throws RocksDatabaseException { // Setup snapshot store mock - File snapshotDbLocation = OmSnapshotManager.getSnapshotPath(omMetadataManager, snapshotId).toFile(); + File snapshotDbLocation = OmSnapshotManager.getSnapshotPath(omMetadataManager, snapshotId, 0).toFile(); assertTrue(snapshotDbLocation.exists() || snapshotDbLocation.mkdirs()); when(snapshotStore.getDbLocation()).thenReturn(snapshotDbLocation); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotChain.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotChain.java index 3f53a66f4f95..e62b64893254 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotChain.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotChain.java @@ -93,7 +93,6 @@ private SnapshotInfo createSnapshotInfo(UUID snapshotID, .setPathPreviousSnapshotId(pathPrevID) .setGlobalPreviousSnapshotId(globalPrevID) .setSnapshotPath(String.join("/", "vol1", "bucket1")) - .setCheckpointDir("checkpoint.testdir") .build(); } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotDiffManager.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotDiffManager.java index 0ea625a0e064..ec896cb3dda3 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotDiffManager.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotDiffManager.java @@ -289,7 +289,6 @@ public void init() throws RocksDBException, IOException, ExecutionException { .setBucketName(BUCKET_NAME) .setName(baseSnapshotName) .setSnapshotPath(snapshotPath) - .setCheckpointDir(snapshotCheckpointDir) .build(); for (JobStatus jobStatus : jobStatuses) { @@ -302,7 +301,6 @@ public void init() throws RocksDBException, IOException, ExecutionException { .setBucketName(BUCKET_NAME) .setName(targetSnapshotName) .setSnapshotPath(snapshotPath) - .setCheckpointDir(snapshotCheckpointDir) .build(); SnapshotDiffJob diffJob = new SnapshotDiffJob(System.currentTimeMillis(), @@ -1395,7 +1393,6 @@ public void testThreadPoolIsFull(String description, .setBucketName(BUCKET_NAME) .setName(snapshotName) .setSnapshotPath("fromSnapshotPath") - .setCheckpointDir("fromSnapshotCheckpointDir") .build(); snapshotInfos.add(snapInfo); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotInfo.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotInfo.java index ca27d9bc8938..a39d907038fb 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotInfo.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotInfo.java @@ -75,7 +75,6 @@ private SnapshotInfo createSnapshotInfo() { .setPathPreviousSnapshotId(EXPECTED_PREVIOUS_SNAPSHOT_ID) .setGlobalPreviousSnapshotId(EXPECTED_PREVIOUS_SNAPSHOT_ID) .setSnapshotPath("test/path") - .setCheckpointDir("checkpoint.testdir") .build(); } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java index 2e0abc07da25..9c6f033b907b 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java @@ -226,7 +226,7 @@ protected Path createSnapshotCheckpoint(String volume, String bucket, String sna RDBStore store = (RDBStore) omMetadataManager.getStore(); String checkpointPrefix = store.getDbLocation().getName(); Path snapshotDirPath = Paths.get(store.getSnapshotsParentDir(), - checkpointPrefix + snapshotInfo.getCheckpointDir()); + checkpointPrefix + SnapshotInfo.getCheckpointDirName(snapshotInfo.getSnapshotId(), 0)); // Check the DB is still there assertTrue(Files.exists(snapshotDirPath)); return snapshotDirPath; diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSstFilteringService.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSstFilteringService.java index e523f32ef7e2..108dd30c8222 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSstFilteringService.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSstFilteringService.java @@ -219,7 +219,7 @@ public void testIrrelevantSstFileDeletion() .get(SnapshotInfo.getTableKey(volumeName, bucketName2, snapshotName1)); String snapshotDirName = - OmSnapshotManager.getSnapshotPath(conf, snapshotInfo); + OmSnapshotManager.getSnapshotPath(conf, snapshotInfo, 0); for (LiveFileMetaData file : allFiles) { //Skipping the previous files from this check even those also works. @@ -294,11 +294,11 @@ public void testActiveAndDeletedSnapshotCleanup() throws Exception { SnapshotInfo snapshot1Info = om.getMetadataManager().getSnapshotInfoTable() .get(SnapshotInfo.getTableKey(volumeName, bucketNames.get(0), "snap1")); File snapshot1Dir = - new File(OmSnapshotManager.getSnapshotPath(conf, snapshot1Info)); + new File(OmSnapshotManager.getSnapshotPath(conf, snapshot1Info, 0)); SnapshotInfo snapshot2Info = om.getMetadataManager().getSnapshotInfoTable() .get(SnapshotInfo.getTableKey(volumeName, bucketNames.get(0), "snap2")); File snapshot2Dir = - new File(OmSnapshotManager.getSnapshotPath(conf, snapshot2Info)); + new File(OmSnapshotManager.getSnapshotPath(conf, snapshot2Info, 0)); File snap1Current = new File(snapshot1Dir, "CURRENT"); File snap2Current = new File(snapshot2Dir, "CURRENT");