You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by na...@apache.org on 2022/08/03 11:41:53 UTC
[ozone] branch HDDS-6517-Snapshot updated: HDDS-6849. OM changes for tracking Snapshot Metadata. (#3582)
This is an automated email from the ASF dual-hosted git repository.
nanda pushed a commit to branch HDDS-6517-Snapshot
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/HDDS-6517-Snapshot by this push:
new 2410551d2e HDDS-6849. OM changes for tracking Snapshot Metadata. (#3582)
2410551d2e is described below
commit 2410551d2ecdafb3b8ef044e11249a10d522f345
Author: Neil Joshi <ne...@gmail.com>
AuthorDate: Wed Aug 3 05:41:46 2022 -0600
HDDS-6849. OM changes for tracking Snapshot Metadata. (#3582)
---
.../hadoop/ozone/om/helpers/SnapshotInfo.java | 368 +++++++++++++++++++++
.../ozone/om/helpers/TestOmSnapshotInfo.java | 134 ++++++++
.../src/main/proto/OmClientProtocol.proto | 27 ++
.../apache/hadoop/ozone/om/OMMetadataManager.java | 3 +
.../ozone/om/codec/OmDBSnapshotInfoCodec.java | 58 ++++
.../hadoop/ozone/om/OmMetadataManagerImpl.java | 23 +-
.../hadoop/ozone/om/codec/OMDBDefinition.java | 13 +-
.../apache/hadoop/ozone/om/TestSnapshotInfo.java | 102 ++++++
8 files changed, 725 insertions(+), 3 deletions(-)
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
new file mode 100644
index 0000000000..37273f2f59
--- /dev/null
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/SnapshotInfo.java
@@ -0,0 +1,368 @@
+package org.apache.hadoop.ozone.om.helpers;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SnapshotStatusProto;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * This class is used for storing info related to Snapshots.
+ *
+ * Each snapshot created has an associated SnapshotInfo entry
+ * containing the snapshotid, snapshot path,
+ * snapshot checkpoint directory, previous snapshotid
+ * for the snapshot path & global amongst other necessary fields.
+ */
+public final class SnapshotInfo {
+
+ /**
+ * SnapshotStatus enum composed of
+ * active, deleted and reclaimed statues.
+ */
+ public enum SnapshotStatus {
+ SNAPSHOT_ACTIVE,
+ SNAPSHOT_DELETED,
+ SNAPSHOT_RECLAIMED;
+
+ public static final SnapshotStatus DEFAULT = SNAPSHOT_ACTIVE;
+
+ public SnapshotStatusProto toProto() {
+ switch (this) {
+ case SNAPSHOT_ACTIVE:
+ return SnapshotStatusProto.SNAPSHOT_ACTIVE;
+ case SNAPSHOT_DELETED:
+ return SnapshotStatusProto.SNAPSHOT_DELETED;
+ case SNAPSHOT_RECLAIMED:
+ return SnapshotStatusProto.SNAPSHOT_RECLAIMED;
+ default:
+ throw new IllegalStateException(
+ "BUG: missing valid SnapshotStatus, found status=" + this);
+ }
+ }
+
+ public static SnapshotStatus valueOf(SnapshotStatusProto status) {
+ switch (status) {
+ case SNAPSHOT_ACTIVE:
+ return SNAPSHOT_ACTIVE;
+ case SNAPSHOT_DELETED:
+ return SNAPSHOT_DELETED;
+ case SNAPSHOT_RECLAIMED:
+ return SNAPSHOT_RECLAIMED;
+ default:
+ throw new IllegalStateException(
+ "BUG: missing valid SnapshotStatus, found status=" + status);
+ }
+ }
+ };
+
+ private final String snapshotID; // UUID
+ private String name;
+ private String volumeName;
+ private String bucketName;
+ private SnapshotStatus snapshotStatus;
+ private final long creationTime;
+ private long deletionTime;
+ private String pathPreviousSnapshotID;
+ private String globalPreviousSnapshotID;
+ private String snapshotPath; // snapshot mask
+ private String checkpointDir;
+
+ /**
+ * Private constructor, constructed via builder.
+ * @param snapshotID - Snapshot UUID.
+ * @param name - snapshot name.
+ * @param volumeName - volume name.
+ * @param bucketName - bucket name.
+ * @param snapshotStatus - status: SNAPSHOT_ACTIVE, SNAPSHOT_DELETED,
+ * SNAPSHOT_RECLAIMED
+ * @param creationTime - Snapshot creation time.
+ * @param deletionTime - Snapshot deletion time.
+ * @param pathPreviousSnapshotID - Snapshot path previous snapshot id.
+ * @param globalPreviousSnapshotID - Snapshot global previous snapshot id.
+ * @param snapshotPath - Snapshot path, bucket .snapshot path.
+ * @param checkpointDir - Snapshot checkpoint directory.
+ */
+ @SuppressWarnings("checkstyle:ParameterNumber")
+ private SnapshotInfo(String snapshotID,
+ String name,
+ String volumeName,
+ String bucketName,
+ SnapshotStatus snapshotStatus,
+ long creationTime,
+ long deletionTime,
+ String pathPreviousSnapshotID,
+ String globalPreviousSnapshotID,
+ String snapshotPath,
+ String checkpointDir) {
+ this.snapshotID = snapshotID;
+ this.name = name;
+ this.volumeName = volumeName;
+ this.bucketName = bucketName;
+ this.snapshotStatus = snapshotStatus;
+ this.creationTime = creationTime;
+ this.deletionTime = deletionTime;
+ this.pathPreviousSnapshotID = pathPreviousSnapshotID;
+ this.globalPreviousSnapshotID = globalPreviousSnapshotID;
+ this.snapshotPath = snapshotPath;
+ this.checkpointDir = checkpointDir;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setVolumeName(String volumeName) {
+ this.volumeName = volumeName;
+ }
+
+ public void setBucketName(String bucketName) {
+ this.bucketName = bucketName;
+ }
+
+ public void setSnapshotStatus(SnapshotStatus snapshotStatus) {
+ this.snapshotStatus = snapshotStatus;
+ }
+
+ public void setDeletionTime(long delTime) {
+ this.deletionTime = delTime;
+ }
+
+ public void setPathPreviousSnapshotID(String pathPreviousSnapshotID) {
+ this.pathPreviousSnapshotID = pathPreviousSnapshotID;
+ }
+
+ public void setGlobalPreviousSnapshotID(String globalPreviousSnapshotID) {
+ this.globalPreviousSnapshotID = globalPreviousSnapshotID;
+ }
+
+ public void setSnapshotPath(String snapshotPath) {
+ this.snapshotPath = snapshotPath;
+ }
+
+ public void setCheckpointDir(String checkpointDir) {
+ this.checkpointDir = checkpointDir;
+ }
+
+ public String getSnapshotID() {
+ return snapshotID;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVolumeName() {
+ return volumeName;
+ }
+
+ public String getBucketName() {
+ return bucketName;
+ }
+
+ public SnapshotStatus getSnapshotStatus() {
+ return snapshotStatus;
+ }
+
+ public long getCreationTime() {
+ return creationTime;
+ }
+
+ public long getDeletionTime() {
+ return deletionTime;
+ }
+
+ public String getPathPreviousSnapshotID() {
+ return pathPreviousSnapshotID;
+ }
+
+ public String getGlobalPreviousSnapshotID() {
+ return globalPreviousSnapshotID;
+ }
+
+ public String getSnapshotPath() {
+ return snapshotPath;
+ }
+
+ public String getCheckpointDir() {
+ return checkpointDir;
+ }
+
+ public static org.apache.hadoop.ozone.om.helpers.SnapshotInfo.Builder
+ newBuilder() {
+ return new org.apache.hadoop.ozone.om.helpers.SnapshotInfo.Builder();
+ }
+
+ public SnapshotInfo.Builder toBuilder() {
+ return new SnapshotInfo.Builder()
+ .setSnapshotID(snapshotID)
+ .setName(name)
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setSnapshotStatus(snapshotStatus)
+ .setCreationTime(creationTime)
+ .setDeletionTime(deletionTime)
+ .setPathPreviousSnapshotID(pathPreviousSnapshotID)
+ .setGlobalPreviousSnapshotID(globalPreviousSnapshotID)
+ .setSnapshotPath(snapshotPath)
+ .setCheckpointDir(checkpointDir);
+ }
+
+ /**
+ * Builder of SnapshotInfo.
+ */
+ public static class Builder {
+ private String snapshotID;
+ private String name;
+ private String volumeName;
+ private String bucketName;
+ private SnapshotStatus snapshotStatus;
+ private long creationTime;
+ private long deletionTime;
+ private String pathPreviousSnapshotID;
+ private String globalPreviousSnapshotID;
+ private String snapshotPath;
+ private String checkpointDir;
+
+ public Builder() {
+ // default values
+ this.snapshotStatus = SnapshotStatus.DEFAULT;
+ }
+
+ public Builder setSnapshotID(String snapshotID) {
+ this.snapshotID = snapshotID;
+ return this;
+ }
+
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder setVolumeName(String volumeName) {
+ this.volumeName = volumeName;
+ return this;
+ }
+
+ public Builder setBucketName(String bucketName) {
+ this.bucketName = bucketName;
+ return this;
+ }
+
+ public Builder setSnapshotStatus(SnapshotStatus snapshotStatus) {
+ this.snapshotStatus = snapshotStatus;
+ return this;
+ }
+
+ public Builder setCreationTime(long crTime) {
+ this.creationTime = crTime;
+ return this;
+ }
+
+ public Builder setDeletionTime(long delTime) {
+ this.deletionTime = delTime;
+ return this;
+ }
+
+ public Builder setPathPreviousSnapshotID(String pathPreviousSnapshotID) {
+ this.pathPreviousSnapshotID = pathPreviousSnapshotID;
+ return this;
+ }
+
+ public Builder setGlobalPreviousSnapshotID(
+ String globalPreviousSnapshotID) {
+ this.globalPreviousSnapshotID = globalPreviousSnapshotID;
+ return this;
+ }
+
+ public Builder setSnapshotPath(String snapshotPath) {
+ this.snapshotPath = snapshotPath;
+ return this;
+ }
+
+ public Builder setCheckpointDir(String checkpointDir) {
+ this.checkpointDir = checkpointDir;
+ return this;
+ }
+
+ public SnapshotInfo build() {
+ Preconditions.checkNotNull(name);
+ return new SnapshotInfo(
+ snapshotID,
+ name,
+ volumeName,
+ bucketName,
+ snapshotStatus,
+ creationTime,
+ deletionTime,
+ pathPreviousSnapshotID,
+ globalPreviousSnapshotID,
+ snapshotPath,
+ checkpointDir
+ );
+ }
+ }
+
+ /**
+ * Creates SnapshotInfo protobuf from SnapshotInfo.
+ */
+ public OzoneManagerProtocolProtos.SnapshotInfo getProtobuf() {
+ OzoneManagerProtocolProtos.SnapshotInfo.Builder sib =
+ OzoneManagerProtocolProtos.SnapshotInfo.newBuilder()
+ .setSnapshotID(snapshotID)
+ .setName(name)
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setSnapshotStatus(snapshotStatus.toProto())
+ .setCreationTime(creationTime)
+ .setDeletionTime(deletionTime)
+ .setPathPreviousSnapshotID(pathPreviousSnapshotID)
+ .setGlobalPreviousSnapshotID(globalPreviousSnapshotID)
+ .setSnapshotPath(snapshotPath)
+ .setCheckpointDir(checkpointDir);
+ return sib.build();
+ }
+
+ /**
+ * Parses SnapshotInfo protobuf and creates SnapshotInfo.
+ * @param snapshotInfo protobuf
+ * @return instance of SnapshotInfo
+ */
+ public static SnapshotInfo getFromProtobuf(
+ OzoneManagerProtocolProtos.SnapshotInfo snapshotInfoProto) {
+ SnapshotInfo.Builder osib = SnapshotInfo.newBuilder()
+ .setSnapshotID(snapshotInfoProto.getSnapshotID())
+ .setName(snapshotInfoProto.getName())
+ .setVolumeName(snapshotInfoProto.getVolumeName())
+ .setBucketName(snapshotInfoProto.getBucketName())
+ .setSnapshotStatus(SnapshotStatus.valueOf(snapshotInfoProto
+ .getSnapshotStatus()))
+ .setCreationTime(snapshotInfoProto.getCreationTime())
+ .setDeletionTime(snapshotInfoProto.getDeletionTime())
+ .setPathPreviousSnapshotID(snapshotInfoProto.
+ getPathPreviousSnapshotID())
+ .setGlobalPreviousSnapshotID(snapshotInfoProto.
+ getGlobalPreviousSnapshotID())
+ .setSnapshotPath(snapshotInfoProto.getSnapshotPath())
+ .setCheckpointDir(snapshotInfoProto.getCheckpointDir());
+
+ return osib.build();
+ }
+}
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
new file mode 100644
index 0000000000..d70522ba95
--- /dev/null
+++ b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmSnapshotInfo.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.om.helpers;
+
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo.SnapshotStatus;
+
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SnapshotStatusProto;
+
+import org.apache.hadoop.util.Time;
+import org.junit.Test;
+import org.junit.Assert;
+
+import java.util.UUID;
+
+/**
+ * Tests SnapshotInfo metadata data structure holding state info for
+ * object storage snapshots.
+ */
+public class TestOmSnapshotInfo {
+
+ private static final String SNAPSHOT_ID = UUID.randomUUID().toString();
+ private static final String NAME = "snapshot1";
+ private static final String VOLUME_NAME = "vol1";
+ private static final String BUCKET_NAME = "bucket1";
+ private static final SnapshotStatus SNAPSHOT_STATUS =
+ SnapshotStatus.SNAPSHOT_ACTIVE;
+ private static final long CREATION_TIME = Time.now();
+ private static final long DELETION_TIME = -1;
+ private static final String PATH_PREVIOUS_SNAPSHOT_ID =
+ UUID.randomUUID().toString();
+ private static final String 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 SnapshotInfo createSnapshotInfo() {
+ return new SnapshotInfo.Builder()
+ .setSnapshotID(SNAPSHOT_ID)
+ .setName(NAME)
+ .setVolumeName(VOLUME_NAME)
+ .setBucketName(BUCKET_NAME)
+ .setSnapshotStatus(SNAPSHOT_STATUS)
+ .setCreationTime(CREATION_TIME)
+ .setDeletionTime(DELETION_TIME)
+ .setPathPreviousSnapshotID(PATH_PREVIOUS_SNAPSHOT_ID)
+ .setGlobalPreviousSnapshotID(GLOBAL_PREVIOUS_SNAPSHOT_ID)
+ .setSnapshotPath(SNAPSHOT_PATH)
+ .setCheckpointDir(CHECKPOINT_DIR)
+ .build();
+ }
+
+ private OzoneManagerProtocolProtos.SnapshotInfo createSnapshotInfoProto() {
+ return OzoneManagerProtocolProtos.SnapshotInfo.newBuilder()
+ .setSnapshotID(SNAPSHOT_ID)
+ .setName(NAME)
+ .setVolumeName(VOLUME_NAME)
+ .setBucketName(BUCKET_NAME)
+ .setSnapshotStatus(SnapshotStatusProto.SNAPSHOT_ACTIVE)
+ .setCreationTime(CREATION_TIME)
+ .setDeletionTime(DELETION_TIME)
+ .setPathPreviousSnapshotID(PATH_PREVIOUS_SNAPSHOT_ID)
+ .setGlobalPreviousSnapshotID(GLOBAL_PREVIOUS_SNAPSHOT_ID)
+ .setSnapshotPath(SNAPSHOT_PATH)
+ .setCheckpointDir(CHECKPOINT_DIR)
+ .build();
+ }
+
+ @Test
+ public void testSnapshotStatusProtoToObject() {
+ OzoneManagerProtocolProtos.SnapshotInfo snapshotInfoEntry =
+ createSnapshotInfoProto();
+ Assert.assertEquals(SNAPSHOT_STATUS,
+ SnapshotStatus.valueOf(snapshotInfoEntry.getSnapshotStatus()));
+ }
+
+ @Test
+ public void testSnapshotInfoToProto() {
+ SnapshotInfo snapshotInfo = createSnapshotInfo();
+ OzoneManagerProtocolProtos.SnapshotInfo snapshotInfoEntryExpected =
+ createSnapshotInfoProto();
+
+ OzoneManagerProtocolProtos.SnapshotInfo snapshotInfoEntryActual =
+ snapshotInfo.getProtobuf();
+ Assert.assertEquals(snapshotInfoEntryExpected.getSnapshotID(),
+ snapshotInfoEntryActual.getSnapshotID());
+ Assert.assertEquals(snapshotInfoEntryExpected.getName(),
+ snapshotInfoEntryActual.getName());
+ Assert.assertEquals(snapshotInfoEntryExpected.getVolumeName(),
+ snapshotInfoEntryActual.getVolumeName());
+ Assert.assertEquals(snapshotInfoEntryExpected.getBucketName(),
+ snapshotInfoEntryActual.getBucketName());
+ Assert.assertEquals(snapshotInfoEntryExpected.getSnapshotStatus(),
+ snapshotInfoEntryActual.getSnapshotStatus());
+
+ }
+
+ @Test
+ public void testSnapshotInfoProtoToSnapshotInfo() {
+ SnapshotInfo snapshotInfoExpected = createSnapshotInfo();
+ OzoneManagerProtocolProtos.SnapshotInfo snapshotInfoEntry =
+ createSnapshotInfoProto();
+
+ SnapshotInfo snapshotInfoActual = SnapshotInfo
+ .getFromProtobuf(snapshotInfoEntry);
+ Assert.assertEquals(snapshotInfoExpected.getSnapshotID(),
+ snapshotInfoActual.getSnapshotID());
+ Assert.assertEquals(snapshotInfoExpected.getName(),
+ snapshotInfoActual.getName());
+ Assert.assertEquals(snapshotInfoExpected.getVolumeName(),
+ snapshotInfoActual.getVolumeName());
+ Assert.assertEquals(snapshotInfoExpected.getBucketName(),
+ snapshotInfoActual.getBucketName());
+ Assert.assertEquals(snapshotInfoExpected.getSnapshotStatus(),
+ snapshotInfoActual.getSnapshotStatus());
+
+ }
+}
diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 4b6a8dd342..6f6467247e 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -711,6 +711,33 @@ message PrefixInfo {
optional uint64 updateID = 5;
}
+/**
+ * SnapshotStatus - snapshot states.
+ * Snapshot in one of : active, deleted, or reclaimed state
+ */
+enum SnapshotStatusProto {
+ SNAPSHOT_ACTIVE = 1;
+ SNAPSHOT_DELETED = 2;
+ SNAPSHOT_RECLAIMED = 3;
+}
+
+/**
+ * SnapshotInfo table entry for Bucket/Volume snapshot metadata
+ */
+message SnapshotInfo {
+ required string snapshotID = 1;
+ required string name = 2;
+ required string volumeName = 3;
+ required string bucketName = 4;
+ required SnapshotStatusProto snapshotStatus = 5;
+ required uint64 creationTime = 6;
+ required uint64 deletionTime = 7;
+ required string pathPreviousSnapshotID = 8;
+ required string globalPreviousSnapshotID = 9;
+ required string snapshotPath = 10;
+ required string checkpointDir = 11;
+ }
+
message OzoneObj {
enum ObjectType {
VOLUME = 1;
diff --git a/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/OMMetadataManager.java b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/OMMetadataManager.java
index 67356a88f3..d92110775a 100644
--- a/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/OMMetadataManager.java
+++ b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/OMMetadataManager.java
@@ -40,6 +40,7 @@ import org.apache.hadoop.ozone.om.helpers.OmDBTenantState;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.RepeatedOmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.lock.OzoneManagerLock;
import org.apache.hadoop.hdds.utils.TransactionInfo;
@@ -370,6 +371,8 @@ public interface OMMetadataManager extends DBStoreHAManager {
Table<String, OmDBTenantState> getTenantStateTable();
+ Table<String, SnapshotInfo> getSnapshotInfoTable();
+
/**
* Gets the OM Meta table.
* @return meta table reference.
diff --git a/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/codec/OmDBSnapshotInfoCodec.java b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/codec/OmDBSnapshotInfoCodec.java
new file mode 100644
index 0000000000..d7da0daf96
--- /dev/null
+++ b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/codec/OmDBSnapshotInfoCodec.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.om.codec;
+
+import org.apache.hadoop.hdds.utils.db.Codec;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Codec to encode SnapshotInfo as byte array.
+ */
+public class OmDBSnapshotInfoCodec implements Codec<SnapshotInfo> {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(OmDBSnapshotInfoCodec.class);
+
+ @Override
+ public byte[] toPersistedFormat(SnapshotInfo object) throws IOException {
+ checkNotNull(object, "Null object can't be converted to byte array.");
+ return object.getProtobuf().toByteArray();
+ }
+
+ @Override
+ public SnapshotInfo fromPersistedFormat(byte[] rawData)
+ throws IOException {
+ checkNotNull(rawData, "Null byte array can't be converted to " +
+ "real object.");
+ return SnapshotInfo.getFromProtobuf(
+ OzoneManagerProtocolProtos.SnapshotInfo.parseFrom(rawData));
+ }
+
+ @Override
+ public SnapshotInfo copyObject(SnapshotInfo object) {
+ // Note: Not really a "copy". from OMDBSnapshotInfoCodec
+ return object;
+ }
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataManagerImpl.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataManagerImpl.java
index 8e9ddd7c01..792696a4ed 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataManagerImpl.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OmMetadataManagerImpl.java
@@ -58,6 +58,7 @@ import org.apache.hadoop.ozone.om.codec.OmDBTenantStateCodec;
import org.apache.hadoop.ozone.om.codec.OmVolumeArgsCodec;
import org.apache.hadoop.ozone.om.codec.RepeatedOmKeyInfoCodec;
import org.apache.hadoop.ozone.om.codec.S3SecretValueCodec;
+import org.apache.hadoop.ozone.om.codec.OmDBSnapshotInfoCodec;
import org.apache.hadoop.ozone.om.codec.TokenIdentifierCodec;
import org.apache.hadoop.ozone.om.codec.UserVolumeInfoCodec;
import org.apache.hadoop.ozone.om.exceptions.OMException;
@@ -76,6 +77,7 @@ import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.ozone.om.helpers.RepeatedOmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.lock.OzoneManagerLock;
import org.apache.hadoop.hdds.utils.TransactionInfo;
@@ -194,6 +196,7 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
public static final String PRINCIPAL_TO_ACCESS_IDS_TABLE =
"principalToAccessIdsTable";
public static final String TENANT_STATE_TABLE = "tenantStateTable";
+ public static final String SNAPSHOT_INFO_TABLE = "snapshotInfoTable";
static final String[] ALL_TABLES = new String[] {
USER_TABLE,
@@ -214,7 +217,8 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
META_TABLE,
TENANT_ACCESS_ID_TABLE,
PRINCIPAL_TO_ACCESS_IDS_TABLE,
- TENANT_STATE_TABLE
+ TENANT_STATE_TABLE,
+ SNAPSHOT_INFO_TABLE
};
private DBStore store;
@@ -241,6 +245,7 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
private Table tenantAccessIdTable;
private Table principalToAccessIdsTable;
private Table tenantStateTable;
+ private Table snapshotInfoTable;
private boolean isRatisEnabled;
private boolean ignorePipelineinKey;
@@ -443,6 +448,7 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
.addTable(TENANT_ACCESS_ID_TABLE)
.addTable(PRINCIPAL_TO_ACCESS_IDS_TABLE)
.addTable(TENANT_STATE_TABLE)
+ .addTable(SNAPSHOT_INFO_TABLE)
.addCodec(OzoneTokenIdentifier.class, new TokenIdentifierCodec())
.addCodec(OmKeyInfo.class, new OmKeyInfoCodec(true))
.addCodec(RepeatedOmKeyInfo.class,
@@ -458,7 +464,9 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
.addCodec(OmDBTenantState.class, new OmDBTenantStateCodec())
.addCodec(OmDBAccessIdInfo.class, new OmDBAccessIdInfoCodec())
.addCodec(OmDBUserPrincipalInfo.class,
- new OmDBUserPrincipalInfoCodec());
+ new OmDBUserPrincipalInfoCodec())
+ .addCodec(SnapshotInfo.class,
+ new OmDBSnapshotInfoCodec());
}
/**
@@ -550,6 +558,12 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
tenantStateTable = this.store.getTable(TENANT_STATE_TABLE,
String.class, OmDBTenantState.class);
checkTableStatus(tenantStateTable, TENANT_STATE_TABLE);
+
+ // path -> snapshotInfo (snapshot info for snapshot)
+ snapshotInfoTable = this.store.getTable(SNAPSHOT_INFO_TABLE,
+ String.class, SnapshotInfo.class);
+ checkTableStatus(snapshotInfoTable, SNAPSHOT_INFO_TABLE);
+
}
/**
@@ -1400,6 +1414,11 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
return tenantStateTable;
}
+ @Override
+ public Table<String, SnapshotInfo> getSnapshotInfoTable() {
+ return snapshotInfoTable;
+ }
+
/**
* Update store used by subclass.
*
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/codec/OMDBDefinition.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/codec/OMDBDefinition.java
index 0df19af147..aa40cc87ad 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/codec/OMDBDefinition.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/codec/OMDBDefinition.java
@@ -36,6 +36,7 @@ import org.apache.hadoop.ozone.om.helpers.RepeatedOmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OmMultipartKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OmPrefixInfo;
import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
import org.apache.hadoop.ozone.om.helpers.OmDirectoryInfo;
import org.apache.hadoop.hdds.utils.TransactionInfo;
@@ -219,6 +220,15 @@ public class OMDBDefinition implements DBDefinition {
// End tables for S3 multi-tenancy
+ public static final DBColumnFamilyDefinition<String, SnapshotInfo>
+ SNAPSHOT_INFO_TABLE =
+ new DBColumnFamilyDefinition<>(
+ OmMetadataManagerImpl.SNAPSHOT_INFO_TABLE,
+ String.class, // snapshot path
+ new StringCodec(),
+ SnapshotInfo.class,
+ new OmDBSnapshotInfoCodec());
+
@Override
public String getName() {
return OzoneConsts.OM_DB_NAME;
@@ -237,7 +247,8 @@ public class OMDBDefinition implements DBDefinition {
S3_SECRET_TABLE, TRANSACTION_INFO_TABLE, DIRECTORY_TABLE,
FILE_TABLE, OPEN_FILE_TABLE, DELETED_DIR_TABLE, META_TABLE,
TENANT_ACCESS_ID_TABLE,
- PRINCIPAL_TO_ACCESS_IDS_TABLE, TENANT_STATE_TABLE};
+ PRINCIPAL_TO_ACCESS_IDS_TABLE, TENANT_STATE_TABLE,
+ SNAPSHOT_INFO_TABLE};
}
}
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestSnapshotInfo.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestSnapshotInfo.java
new file mode 100644
index 0000000000..bafe1d33eb
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestSnapshotInfo.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.om;
+
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo.SnapshotStatus;
+import org.apache.hadoop.hdds.utils.db.Table;
+import org.apache.hadoop.util.Time;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.util.UUID;
+
+import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_DB_DIRS;
+
+/**
+ * Tests SnapshotInfo om database table for Ozone object storage snapshots.
+ */
+public class TestSnapshotInfo {
+
+ private OMMetadataManager omMetadataManager;
+ private static final String EXPECTED_SNAPSHOT_KEY = "snapshot1";
+ private static final String EXPECTED_SNAPSHOT_ID =
+ UUID.randomUUID().toString();
+ private static final String EXPECTED_PREVIOUS_SNAPSHOT_ID =
+ UUID.randomUUID().toString();
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ @Before
+ public void setup() throws Exception {
+ OzoneConfiguration conf = new OzoneConfiguration();
+ conf.set(OZONE_OM_DB_DIRS,
+ folder.getRoot().getAbsolutePath());
+ omMetadataManager = new OmMetadataManagerImpl(conf);
+ }
+
+ private SnapshotInfo createSnapshotInfo() {
+ return new SnapshotInfo.Builder()
+ .setSnapshotID(EXPECTED_SNAPSHOT_ID)
+ .setName("snapshot1")
+ .setVolumeName("vol1")
+ .setBucketName("bucket1")
+ .setSnapshotStatus(SnapshotStatus.SNAPSHOT_ACTIVE)
+ .setCreationTime(Time.now())
+ .setDeletionTime(-1L)
+ .setPathPreviousSnapshotID(EXPECTED_PREVIOUS_SNAPSHOT_ID)
+ .setGlobalPreviousSnapshotID(EXPECTED_PREVIOUS_SNAPSHOT_ID)
+ .setSnapshotPath("test/path")
+ .setCheckpointDir("checkpoint.testdir")
+ .build();
+ }
+
+ @Test
+ public void testTableExists() throws Exception {
+ Table<String, SnapshotInfo> snapshotInfo =
+ omMetadataManager.getSnapshotInfoTable();
+ Assert.assertTrue(snapshotInfo.isEmpty());
+ }
+
+ @Test
+ public void testAddNewSnapshot() throws Exception {
+ Table<String, SnapshotInfo> snapshotInfo =
+ omMetadataManager.getSnapshotInfoTable();
+ snapshotInfo.put(EXPECTED_SNAPSHOT_KEY, createSnapshotInfo());
+ Assert.assertEquals(EXPECTED_SNAPSHOT_ID,
+ snapshotInfo.get(EXPECTED_SNAPSHOT_KEY).getSnapshotID());
+ }
+
+ @Test
+ public void testDeleteSnapshotInfo() throws Exception {
+ Table<String, SnapshotInfo> snapshotInfo =
+ omMetadataManager.getSnapshotInfoTable();
+
+ Assert.assertFalse(snapshotInfo.isExist(EXPECTED_SNAPSHOT_KEY));
+ snapshotInfo.put(EXPECTED_SNAPSHOT_KEY, createSnapshotInfo());
+ Assert.assertTrue(snapshotInfo.isExist(EXPECTED_SNAPSHOT_KEY));
+ snapshotInfo.delete(EXPECTED_SNAPSHOT_KEY);
+ Assert.assertFalse(snapshotInfo.isExist(EXPECTED_SNAPSHOT_KEY));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org