This is an automated email from the ASF dual-hosted git repository.
weichiu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 5c35ebb54f0 HDDS-13830. Snapshot Rocks DB directory path computation
based on local version of snapshot (#9208)
5c35ebb54f0 is described below
commit 5c35ebb54f0d0c9217e921d6ce90d587096bde78
Author: Swaminathan Balachandran <[email protected]>
AuthorDate: Mon Nov 3 11:16:16 2025 -0500
HDDS-13830. Snapshot Rocks DB directory path computation based on local
version of snapshot (#9208)
---
.../apache/hadoop/ozone/client/OzoneSnapshot.java | 20 ++++++-
.../hadoop/ozone/client/TestOzoneSnapshot.java | 3 +-
.../hadoop/ozone/om/helpers/SnapshotInfo.java | 39 +++---------
.../ozone/om/helpers/TestOmSnapshotInfo.java | 3 -
.../hadoop/fs/ozone/TestOzoneFsSnapshot.java | 2 +-
.../hadoop/ozone/freon/TestOMSnapshotDAG.java | 2 +-
.../hadoop/ozone/om/TestOMDbCheckpointServlet.java | 2 +-
.../TestOMDbCheckpointServletInodeBasedXfer.java | 4 +-
.../hadoop/ozone/om/TestOMRatisSnapshots.java | 6 +-
.../hadoop/ozone/om/snapshot/TestOmSnapshot.java | 2 +-
.../om/snapshot/TestOmSnapshotFileSystem.java | 2 +-
.../om/snapshot/TestOzoneManagerHASnapshot.java | 2 +-
.../om/snapshot/TestOzoneManagerSnapshotAcl.java | 2 +-
.../om/snapshot/TestOzoneSnapshotRestore.java | 2 +-
.../snapshot/TestSnapshotBackgroundServices.java | 2 +-
.../src/main/proto/OmClientProtocol.proto | 2 +-
.../hadoop/ozone/om/OMDBCheckpointServlet.java | 15 +++--
.../om/OMDBCheckpointServletInodeBasedXfer.java | 22 ++++---
.../apache/hadoop/ozone/om/OmSnapshotManager.java | 32 +++++-----
.../hadoop/ozone/om/SnapshotDefragService.java | 12 +++-
.../hadoop/ozone/om/SstFilteringService.java | 5 +-
.../response/snapshot/OMSnapshotPurgeResponse.java | 25 ++++----
.../om/snapshot/OmSnapshotLocalDataManager.java | 69 +++++++++++++++++-----
.../hadoop/ozone/om/TestOmSnapshotManager.java | 42 +++++++++++++
.../snapshot/TestOMSnapshotCreateResponse.java | 2 +-
.../snapshot/TestOMSnapshotDeleteResponse.java | 2 +-
.../snapshot/TestOmSnapshotLocalDataManager.java | 2 +-
.../ozone/om/snapshot/TestSnapshotChain.java | 1 -
.../ozone/om/snapshot/TestSnapshotDiffManager.java | 3 -
.../hadoop/ozone/om/snapshot/TestSnapshotInfo.java | 1 -
.../snapshot/TestSnapshotRequestAndResponse.java | 2 +-
.../ozone/om/snapshot/TestSstFilteringService.java | 6 +-
32 files changed, 213 insertions(+), 123 deletions(-)
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 b7bf7051cae..360fd4cef6d 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 8980e28b59b..028e937a9c2 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 cbc3709ea1e..a26422cd81f 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<SnapshotInfo> {
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<String, String> 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 98cc035b3c0..e7695debd61 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 d02319a4cab..6a97796af32 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 5429dc0f4a1..9f69ed51b7c 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 3d542785e11..d0b38116d5f 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 f2b94182c80..a6ae3eaab21 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 a1de8fc377a..3609703c7ef 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 93dba945d46..19b237fe260 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 fca8b137b72..964513702a0 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 bae852ae336..b6008ab3d2e 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 f735ad15d29..455f1430d99 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 6c67554d7b8..b2fde1f0196 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 a67a4599bee..eacde483d2a 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 61a3c1d6792..1e5675f612e 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 4d85e9f0747..efe9fc0aeea 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<Path> getSnapshotDirs(DBCheckpoint checkpoint,
boolean waitForDir)
OzoneConfiguration conf = getConf();
Set<Path> 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<Path> getSnapshotDirs(DBCheckpoint
checkpoint, boolean waitForDir)
// For each entry, wait for corresponding directory.
while (iterator.hasNext()) {
Table.KeyValue<String, SnapshotInfo> 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 0c120ba080d..748329be83a 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<Path> getSnapshotDirsFromDB(OMMetadataManager omMetadataManager) throws
IOException {
+ Set<Path> getSnapshotDirsFromDB(OMMetadataManager activeOMMetadataManager,
OMMetadataManager omMetadataManager,
+ OmSnapshotLocalDataManager localDataManager) throws IOException {
Set<Path> snapshotPaths = new HashSet<>();
try (TableIterator<String, ? extends Table.KeyValue<String, SnapshotInfo>>
iter =
omMetadataManager.getSnapshotInfoTable().iterator()) {
while (iter.hasNext()) {
Table.KeyValue<String, SnapshotInfo> 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 7b9beb80cf6..0954b029ab6 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 b99bb973931..61b6cba6801 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 522ea7df6de..4b5002eb6c4 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 8a370cb975e..3bc8a8dc27b 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 8298ba35544..33caddc9232 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<Integer, LocalDataVersionNode> snapshotVersions;
private int version;
@@ -828,16 +867,16 @@ private Map<Integer, LocalDataVersionNode>
getVersionNodes(OmSnapshotLocalData s
return versionNodes;
}
- UUID getPreviousSnapshotId() {
+ public UUID getPreviousSnapshotId() {
return previousSnapshotId;
}
- int getVersion() {
+ public int getVersion() {
return version;
}
- Map<Integer, LocalDataVersionNode> getSnapshotVersions() {
- return snapshotVersions;
+ private Map<Integer, LocalDataVersionNode> 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 8f9375f3962..8c5ec7e5ab4 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<OMStorage> 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 2cafae138fd..6bef4b84247 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 2d5d7b2870f..bdb23b65f2c 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 8554d1684e2..df26fa742e8 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<UUID>
createSnapshotLocalData(OmSnapshotLocalDataManager snapshotLo
private void mockSnapshotStore(UUID snapshotId, List<LiveFileMetaData>
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 3f53a66f4f9..e62b6489325 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 0ea625a0e06..ec896cb3dda 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 ca27d9bc893..a39d907038f 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 2e0abc07da2..9c6f033b907 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 e523f32ef7e..108dd30c822 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");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]