blob: e1b7ce1f27afdb17fdfe040d795c69003c2944ae [file] [log] [blame]
/**
* 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 java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.google.common.collect.ImmutableList;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.fs.FileChecksum;
import org.apache.hadoop.fs.FileEncryptionInfo;
import org.apache.hadoop.hdds.client.ContainerBlockID;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfig;
import org.apache.hadoop.hdds.utils.db.Codec;
import org.apache.hadoop.hdds.utils.db.DelegatedCodec;
import org.apache.hadoop.hdds.utils.db.CopyObject;
import org.apache.hadoop.hdds.utils.db.Proto2Codec;
import org.apache.hadoop.ozone.ClientVersion;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FileChecksumProto;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyInfo;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyLocationList;
import org.apache.hadoop.ozone.protocolPB.OMPBHelper;
import org.apache.hadoop.util.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Args for key block. The block instance for the key requested in putKey.
* This is returned from OM to client, and client use class to talk to
* datanode. Also, this is the metadata written to om.db on server side.
*/
public final class OmKeyInfo extends WithParentObjectId
implements CopyObject<OmKeyInfo> {
private static final Logger LOG = LoggerFactory.getLogger(OmKeyInfo.class);
private static final Codec<OmKeyInfo> CODEC_TRUE = newCodec(true);
private static final Codec<OmKeyInfo> CODEC_FALSE = newCodec(false);
private static Codec<OmKeyInfo> newCodec(boolean ignorePipeline) {
return new DelegatedCodec<>(
Proto2Codec.get(KeyInfo.getDefaultInstance()),
OmKeyInfo::getFromProtobuf,
k -> k.getProtobuf(ignorePipeline, ClientVersion.CURRENT_VERSION));
}
public static Codec<OmKeyInfo> getCodec(boolean ignorePipeline) {
LOG.info("OmKeyInfo.getCodec ignorePipeline = {}", ignorePipeline);
return ignorePipeline ? CODEC_TRUE : CODEC_FALSE;
}
private final String volumeName;
private final String bucketName;
// name of key client specified
private String keyName;
private long dataSize;
private List<OmKeyLocationInfoGroup> keyLocationVersions;
private final long creationTime;
private long modificationTime;
private ReplicationConfig replicationConfig;
private FileEncryptionInfo encInfo;
private final FileChecksum fileChecksum;
/**
* Support OFS use-case to identify if the key is a file or a directory.
*/
private boolean isFile;
/**
* Represents leaf node name. This also will be used when the keyName is
* created on a FileSystemOptimized(FSO) bucket. For example, the user given
* keyName is "a/b/key1" then the fileName stores "key1".
*/
private String fileName;
/**
* ACL Information.
*/
private final List<OzoneAcl> acls;
private OmKeyInfo(Builder b) {
setMetadata(b.metadata);
setObjectID(b.objectID);
setUpdateID(b.updateID);
setParentObjectID(b.parentObjectID);
this.volumeName = b.volumeName;
this.bucketName = b.bucketName;
this.keyName = b.keyName;
this.dataSize = b.dataSize;
this.keyLocationVersions = b.omKeyLocationInfoGroups;
this.creationTime = b.creationTime;
this.modificationTime = b.modificationTime;
this.replicationConfig = b.replicationConfig;
this.encInfo = b.encInfo;
this.acls = b.acls;
this.fileChecksum = b.fileChecksum;
this.fileName = b.fileName;
this.isFile = b.isFile;
}
public String getVolumeName() {
return volumeName;
}
public String getBucketName() {
return bucketName;
}
public ReplicationConfig getReplicationConfig() {
return replicationConfig;
}
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
public long getDataSize() {
return dataSize;
}
public long getReplicatedSize() {
return QuotaUtil.getReplicatedSize(getDataSize(), replicationConfig);
}
public void setDataSize(long size) {
this.dataSize = size;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public synchronized OmKeyLocationInfoGroup getLatestVersionLocations() {
return keyLocationVersions.size() == 0 ? null :
keyLocationVersions.get(keyLocationVersions.size() - 1);
}
public List<OmKeyLocationInfoGroup> getKeyLocationVersions() {
return keyLocationVersions;
}
public void setKeyLocationVersions(
List<OmKeyLocationInfoGroup> keyLocationVersions) {
this.keyLocationVersions = keyLocationVersions;
}
public void setFile(boolean file) {
isFile = file;
}
public boolean isFile() {
return isFile;
}
public boolean isHsync() {
return getMetadata().containsKey(OzoneConsts.HSYNC_CLIENT_ID);
}
/**
* updates the length of the each block in the list given.
* This will be called when the key is being committed to OzoneManager.
* Return the uncommitted locationInfo to be deleted.
*
* @param locationInfoList list of locationInfo
* @return allocated but uncommitted locationInfos
*/
public List<OmKeyLocationInfo> updateLocationInfoList(
List<OmKeyLocationInfo> locationInfoList, boolean isMpu) {
return updateLocationInfoList(locationInfoList, isMpu, false);
}
/**
* updates the length of the each block in the list given.
* This will be called when the key is being committed to OzoneManager.
* Return the uncommitted locationInfo to be deleted.
*
* @param locationInfoList list of locationInfo
* @param isMpu a true represents multi part key, false otherwise
* @param skipBlockIDCheck a true represents that the blockId verification
* check should be skipped, false represents that
* the blockId verification will be required
* @return allocated but uncommitted locationInfos
*/
public List<OmKeyLocationInfo> updateLocationInfoList(
List<OmKeyLocationInfo> locationInfoList,
boolean isMpu, boolean skipBlockIDCheck) {
long latestVersion = getLatestVersionLocations().getVersion();
OmKeyLocationInfoGroup keyLocationInfoGroup = getLatestVersionLocations();
keyLocationInfoGroup.setMultipartKey(isMpu);
// Compare user given block location against allocatedBlockLocations
// present in OmKeyInfo.
List<OmKeyLocationInfo> uncommittedBlocks;
List<OmKeyLocationInfo> updatedBlockLocations;
if (skipBlockIDCheck) {
updatedBlockLocations = locationInfoList;
uncommittedBlocks = new ArrayList<>();
} else {
Pair<List<OmKeyLocationInfo>, List<OmKeyLocationInfo>> verifiedResult =
verifyAndGetKeyLocations(locationInfoList, keyLocationInfoGroup);
updatedBlockLocations = verifiedResult.getLeft();
uncommittedBlocks = verifiedResult.getRight();
}
keyLocationInfoGroup.removeBlocks(latestVersion);
// set each of the locationInfo object to the latest version
updatedBlockLocations.forEach(omKeyLocationInfo -> omKeyLocationInfo
.setCreateVersion(latestVersion));
keyLocationInfoGroup.addAll(latestVersion, updatedBlockLocations);
return uncommittedBlocks;
}
/**
* 1. Verify committed KeyLocationInfos
* 2. Find out the allocated but uncommitted KeyLocationInfos.
*
* @param locationInfoList committed KeyLocationInfos
* @param keyLocationInfoGroup allocated KeyLocationInfoGroup
* @return Pair of updatedOmKeyLocationInfo and uncommittedOmKeyLocationInfo
*/
private Pair<List<OmKeyLocationInfo>, List<OmKeyLocationInfo>>
verifyAndGetKeyLocations(
List<OmKeyLocationInfo> locationInfoList,
OmKeyLocationInfoGroup keyLocationInfoGroup) {
// Only check ContainerBlockID here to avoid the mismatch of the pipeline
// field and BcsId in the OmKeyLocationInfo, as the OmKeyInfoCodec ignores
// the pipeline field by default and bcsId would be updated in Ratis mode.
Map<ContainerBlockID, OmKeyLocationInfo> allocatedBlockLocations =
new HashMap<>();
for (OmKeyLocationInfo existingLocationInfo : keyLocationInfoGroup.
getLocationList()) {
ContainerBlockID existingBlockID = existingLocationInfo.getBlockID().
getContainerBlockID();
// The case of overwriting value should never happen
allocatedBlockLocations.put(existingBlockID, existingLocationInfo);
}
List<OmKeyLocationInfo> updatedBlockLocations = new ArrayList<>();
for (OmKeyLocationInfo modifiedLocationInfo : locationInfoList) {
ContainerBlockID modifiedContainerBlockId =
modifiedLocationInfo.getBlockID().getContainerBlockID();
if (allocatedBlockLocations.containsKey(modifiedContainerBlockId)) {
updatedBlockLocations.add(modifiedLocationInfo);
allocatedBlockLocations.remove(modifiedContainerBlockId);
} else {
LOG.warn("Unknown BlockLocation:{}, where the blockID of given "
+ "location doesn't match with the stored/allocated block of"
+ " keyName:{}", modifiedLocationInfo, keyName);
}
}
List<OmKeyLocationInfo> uncommittedLocationInfos = new ArrayList<>(
allocatedBlockLocations.values());
return Pair.of(updatedBlockLocations, uncommittedLocationInfos);
}
/**
* Append a set of blocks to the latest version. Note that these blocks are
* part of the latest version, not a new version.
*
* @param newLocationList the list of new blocks to be added.
* @param updateTime if true, will update modification time.
* @throws IOException
*/
public synchronized void appendNewBlocks(
List<OmKeyLocationInfo> newLocationList, boolean updateTime)
throws IOException {
if (keyLocationVersions.size() == 0) {
throw new IOException("Appending new block, but no version exist");
}
OmKeyLocationInfoGroup currentLatestVersion =
keyLocationVersions.get(keyLocationVersions.size() - 1);
currentLatestVersion.appendNewBlocks(newLocationList);
if (updateTime) {
setModificationTime(Time.now());
}
}
/**
* Add a new set of blocks. The new blocks will be added as appending a new
* version to the all version list.
*
* @param newLocationList the list of new blocks to be added.
* @param updateTime if true, updates modification time.
* @param keepOldVersions if false, old blocks won't be kept
* and the new block versions will always be 0
* @throws IOException
*/
public synchronized long addNewVersion(
List<OmKeyLocationInfo> newLocationList, boolean updateTime,
boolean keepOldVersions) {
long latestVersionNum;
if (!keepOldVersions) {
// If old versions are cleared, new block version will always start at 0
keyLocationVersions.clear();
}
if (keyLocationVersions.size() == 0) {
// no version exist, these blocks are the very first version.
keyLocationVersions.add(new OmKeyLocationInfoGroup(0, newLocationList));
latestVersionNum = 0;
} else {
// it is important that the new version are always at the tail of the list
OmKeyLocationInfoGroup currentLatestVersion =
keyLocationVersions.get(keyLocationVersions.size() - 1);
// Create a new version here. When bucket versioning is enabled,
// It includes previous block versions. Otherwise, only the blocks
// of new version is included.
OmKeyLocationInfoGroup newVersion =
currentLatestVersion.generateNextVersion(newLocationList);
keyLocationVersions.add(newVersion);
latestVersionNum = newVersion.getVersion();
}
if (updateTime) {
setModificationTime(Time.now());
}
return latestVersionNum;
}
public long getCreationTime() {
return creationTime;
}
public long getModificationTime() {
return modificationTime;
}
public void setModificationTime(long modificationTime) {
this.modificationTime = modificationTime;
}
public FileEncryptionInfo getFileEncryptionInfo() {
return encInfo;
}
public List<OzoneAcl> getAcls() {
return ImmutableList.copyOf(acls);
}
public boolean addAcl(OzoneAcl acl) {
return OzoneAclUtil.addAcl(acls, acl);
}
public boolean removeAcl(OzoneAcl acl) {
return OzoneAclUtil.removeAcl(acls, acl);
}
public boolean setAcls(List<OzoneAcl> newAcls) {
return OzoneAclUtil.setAcl(acls, newAcls);
}
public void setReplicationConfig(ReplicationConfig repConfig) {
this.replicationConfig = repConfig;
}
public FileChecksum getFileChecksum() {
return fileChecksum;
}
@Override
public String toString() {
return "OmKeyInfo{" +
"volumeName='" + volumeName + '\'' +
", bucketName='" + bucketName + '\'' +
", keyName='" + keyName + '\'' +
", dataSize=" + dataSize +
", keyLocationVersions=" + keyLocationVersions +
", creationTime=" + creationTime +
", modificationTime=" + modificationTime +
", replicationConfig=" + replicationConfig +
", encInfo=" + (encInfo == null ? "null" : "<REDACTED>") +
", fileChecksum=" + fileChecksum +
", isFile=" + isFile +
", fileName='" + fileName + '\'' +
", acls=" + acls +
'}';
}
/**
* Builder of OmKeyInfo.
*/
public static class Builder {
private String volumeName;
private String bucketName;
private String keyName;
private long dataSize;
private final List<OmKeyLocationInfoGroup> omKeyLocationInfoGroups =
new ArrayList<>();
private long creationTime;
private long modificationTime;
private ReplicationConfig replicationConfig;
private final Map<String, String> metadata;
private FileEncryptionInfo encInfo;
private final List<OzoneAcl> acls;
private long objectID;
private long updateID;
// not persisted to DB. FileName will be the last element in path keyName.
private String fileName;
private long parentObjectID;
private FileChecksum fileChecksum;
private boolean isFile;
public Builder() {
this.metadata = new HashMap<>();
acls = new ArrayList<>();
}
public Builder setVolumeName(String volume) {
this.volumeName = volume;
return this;
}
public Builder setBucketName(String bucket) {
this.bucketName = bucket;
return this;
}
public Builder setKeyName(String key) {
this.keyName = key;
return this;
}
public Builder setOmKeyLocationInfos(
List<OmKeyLocationInfoGroup> omKeyLocationInfoList) {
if (omKeyLocationInfoList != null) {
this.omKeyLocationInfoGroups.addAll(omKeyLocationInfoList);
}
return this;
}
public Builder addOmKeyLocationInfoGroup(OmKeyLocationInfoGroup
omKeyLocationInfoGroup) {
if (omKeyLocationInfoGroup != null) {
this.omKeyLocationInfoGroups.add(omKeyLocationInfoGroup);
}
return this;
}
public Builder setDataSize(long size) {
this.dataSize = size;
return this;
}
public Builder setCreationTime(long crTime) {
this.creationTime = crTime;
return this;
}
public Builder setModificationTime(long mTime) {
this.modificationTime = mTime;
return this;
}
public Builder setReplicationConfig(ReplicationConfig replConfig) {
this.replicationConfig = replConfig;
return this;
}
public Builder addMetadata(String key, String value) {
metadata.put(key, value);
return this;
}
public Builder addAllMetadata(Map<String, String> newMetadata) {
metadata.putAll(newMetadata);
return this;
}
public Builder setFileEncryptionInfo(FileEncryptionInfo feInfo) {
this.encInfo = feInfo;
return this;
}
public Builder setAcls(List<OzoneAcl> listOfAcls) {
if (listOfAcls != null) {
this.acls.addAll(listOfAcls);
}
return this;
}
public Builder addAcl(OzoneAcl ozoneAcl) {
if (ozoneAcl != null) {
this.acls.add(ozoneAcl);
}
return this;
}
public Builder setObjectID(long obId) {
this.objectID = obId;
return this;
}
public Builder setUpdateID(long id) {
this.updateID = id;
return this;
}
public Builder setFileName(String keyFileName) {
this.fileName = keyFileName;
return this;
}
public Builder setParentObjectID(long parentID) {
this.parentObjectID = parentID;
return this;
}
public Builder setFileChecksum(FileChecksum checksum) {
this.fileChecksum = checksum;
return this;
}
public Builder setFile(boolean isAFile) {
this.isFile = isAFile;
return this;
}
public OmKeyInfo build() {
return new OmKeyInfo(this);
}
}
/**
* For network transmit.
* @return
*/
public KeyInfo getProtobuf(int clientVersion) {
return getProtobuf(false, clientVersion);
}
/**
* For network transmit to return KeyInfo.
* @param clientVersion
* @param latestVersion
* @return key info.
*/
public KeyInfo getNetworkProtobuf(int clientVersion, boolean latestVersion) {
return getProtobuf(false, null, clientVersion, latestVersion);
}
/**
* For network transmit to return KeyInfo.
*
* @param fullKeyName the user given full key name
* @param clientVersion
* @param latestVersion
* @return key info with the user given full key name
*/
public KeyInfo getNetworkProtobuf(String fullKeyName, int clientVersion,
boolean latestVersion) {
return getProtobuf(false, fullKeyName, clientVersion, latestVersion);
}
/**
*
* @param ignorePipeline true for persist to DB, false for network transmit.
* @return
*/
public KeyInfo getProtobuf(boolean ignorePipeline, int clientVersion) {
return getProtobuf(ignorePipeline, null, clientVersion, false);
}
/**
* Gets KeyInfo with the user given key name.
*
* @param ignorePipeline ignore pipeline flag
* @param fullKeyName user given key name
* @return key info object
*/
private KeyInfo getProtobuf(boolean ignorePipeline, String fullKeyName,
int clientVersion, boolean latestVersionBlocks) {
long latestVersion = keyLocationVersions.size() == 0 ? -1 :
keyLocationVersions.get(keyLocationVersions.size() - 1).getVersion();
List<KeyLocationList> keyLocations = new ArrayList<>();
if (!latestVersionBlocks) {
for (OmKeyLocationInfoGroup locationInfoGroup : keyLocationVersions) {
keyLocations.add(locationInfoGroup.getProtobuf(
ignorePipeline, clientVersion));
}
} else {
if (latestVersion != -1) {
keyLocations.add(keyLocationVersions.get(keyLocationVersions.size() - 1)
.getProtobuf(ignorePipeline, clientVersion));
}
}
KeyInfo.Builder kb = KeyInfo.newBuilder()
.setVolumeName(volumeName)
.setBucketName(bucketName)
.setDataSize(dataSize)
.setType(replicationConfig.getReplicationType());
if (replicationConfig instanceof ECReplicationConfig) {
kb.setEcReplicationConfig(
((ECReplicationConfig) replicationConfig).toProto());
} else {
kb.setFactor(ReplicationConfig.getLegacyFactor(replicationConfig));
}
kb.setLatestVersion(latestVersion)
.addAllKeyLocationList(keyLocations)
.setCreationTime(creationTime)
.setModificationTime(modificationTime)
.addAllMetadata(KeyValueUtil.toProtobuf(getMetadata()))
.addAllAcls(OzoneAclUtil.toProtobuf(acls))
.setObjectID(getObjectID())
.setUpdateID(getUpdateID())
.setParentID(getParentObjectID());
FileChecksumProto fileChecksumProto = OMPBHelper.convert(fileChecksum);
if (fileChecksumProto != null) {
kb.setFileChecksum(fileChecksumProto);
}
if (StringUtils.isNotBlank(fullKeyName)) {
kb.setKeyName(fullKeyName);
} else {
kb.setKeyName(keyName);
}
if (encInfo != null) {
kb.setFileEncryptionInfo(OMPBHelper.convert(encInfo));
}
kb.setIsFile(isFile);
return kb.build();
}
public static OmKeyInfo getFromProtobuf(KeyInfo keyInfo) throws IOException {
if (keyInfo == null) {
return null;
}
List<OmKeyLocationInfoGroup> omKeyLocationInfos = new ArrayList<>();
for (KeyLocationList keyLocationList : keyInfo.getKeyLocationListList()) {
omKeyLocationInfos.add(
OmKeyLocationInfoGroup.getFromProtobuf(keyLocationList));
}
Builder builder = new Builder()
.setVolumeName(keyInfo.getVolumeName())
.setBucketName(keyInfo.getBucketName())
.setKeyName(keyInfo.getKeyName())
.setOmKeyLocationInfos(omKeyLocationInfos)
.setDataSize(keyInfo.getDataSize())
.setCreationTime(keyInfo.getCreationTime())
.setModificationTime(keyInfo.getModificationTime())
.setReplicationConfig(ReplicationConfig
.fromProto(keyInfo.getType(), keyInfo.getFactor(),
keyInfo.getEcReplicationConfig()))
.addAllMetadata(KeyValueUtil.getFromProtobuf(keyInfo.getMetadataList()))
.setFileEncryptionInfo(keyInfo.hasFileEncryptionInfo() ?
OMPBHelper.convert(keyInfo.getFileEncryptionInfo()) : null)
.setAcls(OzoneAclUtil.fromProtobuf(keyInfo.getAclsList()));
if (keyInfo.hasObjectID()) {
builder.setObjectID(keyInfo.getObjectID());
}
if (keyInfo.hasUpdateID()) {
builder.setUpdateID(keyInfo.getUpdateID());
}
if (keyInfo.hasParentID()) {
builder.setParentObjectID(keyInfo.getParentID());
}
if (keyInfo.hasFileChecksum()) {
FileChecksum fileChecksum = OMPBHelper.convert(keyInfo.getFileChecksum());
builder.setFileChecksum(fileChecksum);
}
if (keyInfo.hasIsFile()) {
builder.setFile(keyInfo.getIsFile());
}
// not persisted to DB. FileName will be filtered out from keyName
builder.setFileName(OzoneFSUtils.getFileName(keyInfo.getKeyName()));
return builder.build();
}
@Override
public String getObjectInfo() {
return "OMKeyInfo{" +
"volume='" + volumeName + '\'' +
", bucket='" + bucketName + '\'' +
", key='" + keyName + '\'' +
", dataSize='" + dataSize + '\'' +
", creationTime='" + creationTime + '\'' +
", objectID='" + getObjectID() + '\'' +
", parentID='" + getParentObjectID() + '\'' +
", replication='" + replicationConfig + '\'' +
", fileChecksum='" + fileChecksum +
'}';
}
public boolean isKeyInfoSame(OmKeyInfo omKeyInfo, boolean checkPath,
boolean checkKeyLocationVersions,
boolean checkModificationTime,
boolean checkUpdateID) {
boolean isEqual = dataSize == omKeyInfo.dataSize &&
creationTime == omKeyInfo.creationTime &&
volumeName.equals(omKeyInfo.volumeName) &&
bucketName.equals(omKeyInfo.bucketName) &&
replicationConfig.equals(omKeyInfo.replicationConfig) &&
Objects.equals(getMetadata(), omKeyInfo.getMetadata()) &&
Objects.equals(acls, omKeyInfo.acls) &&
getObjectID() == omKeyInfo.getObjectID();
if (isEqual && checkUpdateID) {
isEqual = getUpdateID() == omKeyInfo.getUpdateID();
}
if (isEqual && checkModificationTime) {
isEqual = modificationTime == omKeyInfo.modificationTime;
}
if (isEqual && checkPath) {
isEqual = getParentObjectID() == omKeyInfo.getParentObjectID() &&
keyName.equals(omKeyInfo.keyName);
}
if (isEqual && checkKeyLocationVersions) {
isEqual = Objects
.equals(keyLocationVersions, omKeyInfo.keyLocationVersions);
}
return isEqual;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
return isKeyInfoSame((OmKeyInfo) o, true, true, true, true);
}
@Override
public int hashCode() {
return Objects.hash(volumeName, bucketName, keyName, getParentObjectID());
}
/**
* Return a new copy of the object.
*/
@Override
public OmKeyInfo copyObject() {
OmKeyInfo.Builder builder = new OmKeyInfo.Builder()
.setVolumeName(volumeName)
.setBucketName(bucketName)
.setKeyName(keyName)
.setCreationTime(creationTime)
.setModificationTime(modificationTime)
.setDataSize(dataSize)
.setReplicationConfig(replicationConfig)
.setFileEncryptionInfo(encInfo)
.setAcls(acls)
.setObjectID(getObjectID())
.setUpdateID(getUpdateID())
.setParentObjectID(getParentObjectID())
.setFileName(fileName)
.setFile(isFile);
keyLocationVersions.forEach(keyLocationVersion ->
builder.addOmKeyLocationInfoGroup(
new OmKeyLocationInfoGroup(keyLocationVersion.getVersion(),
keyLocationVersion.getLocationList(),
keyLocationVersion.isMultipartKey())));
if (getMetadata() != null) {
getMetadata().forEach((k, v) -> builder.addMetadata(k, v));
}
if (fileChecksum != null) {
builder.setFileChecksum(fileChecksum);
}
return builder.build();
}
/**
* Method to clear the fileEncryptionInfo.
* This method is called when a KeyDelete operation is performed.
* This ensures that when TDE is enabled and GDPR is enforced on a bucket,
* the encryption info is deleted from Key Metadata before the key is moved
* to deletedTable in OM Metadata.
*/
public void clearFileEncryptionInfo() {
this.encInfo = null;
}
/**
* Set the file encryption info.
* @param fileEncryptionInfo
*/
public void setFileEncryptionInfo(FileEncryptionInfo fileEncryptionInfo) {
this.encInfo = fileEncryptionInfo;
}
public String getPath() {
if (StringUtils.isBlank(getFileName())) {
return getKeyName();
}
return getParentObjectID() + OzoneConsts.OM_KEY_PREFIX + getFileName();
}
}