This is an automated email from the ASF dual-hosted git repository.
adoroszlai 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 aa68aec220 HDDS-10324. Metadata are not updated when keys are
overwritten. (#6273)
aa68aec220 is described below
commit aa68aec220e8f4f83ce3f2e4cbcd8df12f684bc5
Author: Arafat2198 <[email protected]>
AuthorDate: Wed Feb 28 18:48:49 2024 +0530
HDDS-10324. Metadata are not updated when keys are overwritten. (#6273)
---
.../hadoop/ozone/om/request/key/OMKeyRequest.java | 6 +
.../om/request/key/TestOMKeyCreateRequest.java | 151 +++++++++++++++++++--
2 files changed, 149 insertions(+), 8 deletions(-)
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRequest.java
index 100c2d842f..7e4e30316b 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRequest.java
@@ -775,6 +775,12 @@ public abstract class OMKeyRequest extends OMClientRequest
{
dbKeyInfo.setModificationTime(keyArgs.getModificationTime());
dbKeyInfo.setUpdateID(transactionLogIndex, isRatisEnabled);
dbKeyInfo.setReplicationConfig(replicationConfig);
+
+ // Construct a new metadata map from KeyArgs.
+ // Clear the old one when the key is overwritten.
+ dbKeyInfo.getMetadata().clear();
+ dbKeyInfo.getMetadata().putAll(KeyValueUtil.getFromProtobuf(
+ keyArgs.getMetadataList()));
return dbKeyInfo;
}
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java
index 5d79e77715..f61e947d2b 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java
@@ -25,10 +25,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-import java.util.UUID;
-import java.util.stream.Collectors;
import java.util.Map;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.UUID;
+import java.util.stream.Collectors;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
@@ -41,14 +42,16 @@ import org.apache.hadoop.ozone.om.PrefixManagerImpl;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
+
+import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
+import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
import org.apache.hadoop.ozone.om.lock.OzoneLockProvider;
import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos.KeyValue;
-import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
-import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
@@ -66,6 +69,7 @@ import static
org.apache.hadoop.ozone.OzoneConsts.OM_KEY_PREFIX;
import static org.apache.hadoop.ozone.OzoneConsts.OM_SNAPSHOT_INDICATOR;
import static
org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ENABLE_FILESYSTEM_PATHS;
import static
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.addVolumeAndBucketToDB;
+import static
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.createOmKeyInfo;
import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.NOT_A_FILE;
import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.OK;
import static org.assertj.core.api.Assertions.assertThat;
@@ -464,6 +468,107 @@ public class TestOMKeyCreateRequest extends
TestOMKeyRequest {
assertNull(omKeyInfo);
}
+
+ @ParameterizedTest
+ @MethodSource("data")
+ public void testOverwritingExistingMetadata(
+ boolean setKeyPathLock, boolean setFileSystemPaths) throws Exception {
+ when(ozoneManager.getOzoneLockProvider()).thenReturn(
+ new OzoneLockProvider(setKeyPathLock, setFileSystemPaths));
+
+ addVolumeAndBucketToDB(volumeName, bucketName, omMetadataManager,
+ getBucketLayout());
+
+ Map<String, String> initialMetadata =
+ Collections.singletonMap("initialKey", "initialValue");
+ OMRequest initialRequest =
+ createKeyRequest(false, 0, keyName, initialMetadata);
+ OMKeyCreateRequest initialOmKeyCreateRequest =
+ new OMKeyCreateRequest(initialRequest, getBucketLayout());
+ OMClientResponse initialResponse =
+ initialOmKeyCreateRequest.validateAndUpdateCache(ozoneManager, 100L);
+ verifyMetadataInResponse(initialResponse, initialMetadata);
+
+ // We have to add the key to the key table, as validateAndUpdateCache only
+ // updates the cache and not the DB.
+ OmKeyInfo keyInfo = createOmKeyInfo(volumeName, bucketName, keyName,
+ replicationConfig).build();
+ keyInfo.setMetadata(initialMetadata);
+ omMetadataManager.getKeyTable(initialOmKeyCreateRequest.getBucketLayout())
+ .put(getOzoneKey(), keyInfo);
+
+ Map<String, String> updatedMetadata =
+ Collections.singletonMap("initialKey", "updatedValue");
+ OMRequest updatedRequest =
+ createKeyRequest(false, 0, keyName, updatedMetadata);
+ OMKeyCreateRequest updatedOmKeyCreateRequest =
+ new OMKeyCreateRequest(updatedRequest, getBucketLayout());
+
+ OMClientResponse updatedResponse =
+ updatedOmKeyCreateRequest.validateAndUpdateCache(ozoneManager, 101L);
+ verifyMetadataInResponse(updatedResponse, updatedMetadata);
+ }
+
+ @ParameterizedTest
+ @MethodSource("data")
+ public void testCreationWithoutMetadataFollowedByOverwriteWithMetadata(
+ boolean setKeyPathLock, boolean setFileSystemPaths) throws Exception {
+ when(ozoneManager.getOzoneLockProvider()).thenReturn(
+ new OzoneLockProvider(setKeyPathLock, setFileSystemPaths));
+ addVolumeAndBucketToDB(volumeName, bucketName, omMetadataManager,
+ getBucketLayout());
+
+ // Create the key request without any initial metadata
+ OMRequest createRequestWithoutMetadata = createKeyRequest(false, 0,
keyName,
+ null); // Passing 'null' for metadata
+ OMKeyCreateRequest createOmKeyCreateRequest =
+ new OMKeyCreateRequest(createRequestWithoutMetadata,
getBucketLayout());
+
+ // Perform the create operation without any metadata
+ OMClientResponse createResponse =
+ createOmKeyCreateRequest.validateAndUpdateCache(ozoneManager, 100L);
+ // Verify that no metadata exists in the response
+ assertThat(
+ createResponse.getOMResponse().getCreateKeyResponse().getKeyInfo()
+ .getMetadataList()).isEmpty();
+
+ OmKeyInfo keyInfo = createOmKeyInfo(volumeName, bucketName, keyName,
+ replicationConfig).build();
+ omMetadataManager.getKeyTable(createOmKeyCreateRequest.getBucketLayout())
+ .put(getOzoneKey(), keyInfo);
+
+ // Define new metadata for the overwrite operation
+ Map<String, String> overwriteMetadata = new HashMap<>();
+ overwriteMetadata.put("newKey", "newValue");
+
+ // Overwrite the previously created key with new metadata
+ OMRequest overwriteRequestWithMetadata =
+ createKeyRequest(false, 0, keyName, overwriteMetadata);
+ OMKeyCreateRequest overwriteOmKeyCreateRequest =
+ new OMKeyCreateRequest(overwriteRequestWithMetadata,
getBucketLayout());
+
+ // Perform the overwrite operation and capture the response
+ OMClientResponse overwriteResponse =
+ overwriteOmKeyCreateRequest.validateAndUpdateCache(ozoneManager, 101L);
+ // Verify the new metadata is correctly applied in the response
+ verifyMetadataInResponse(overwriteResponse, overwriteMetadata);
+ }
+
+
+ private void verifyMetadataInResponse(OMClientResponse response,
+ Map<String, String> expectedMetadata) {
+ // Extract metadata from the response
+ List<KeyValue> metadataList =
+ response.getOMResponse().getCreateKeyResponse().getKeyInfo()
+ .getMetadataList();
+ assertEquals(expectedMetadata.size(), metadataList.size());
+ metadataList.forEach(kv -> {
+ String expectedValue = expectedMetadata.get(kv.getKey());
+ assertEquals(expectedValue, kv.getValue(),
+ "Metadata value mismatch for key: " + kv.getKey());
+ });
+ }
+
/**
* This method calls preExecute and verify the modified request.
* @param originalOMRequest
@@ -543,25 +648,55 @@ public class TestOMKeyCreateRequest extends
TestOMKeyRequest {
private OMRequest createKeyRequest(boolean isMultipartKey, int partNumber,
String keyName) {
+ return createKeyRequest(isMultipartKey, partNumber, keyName, null);
+ }
+ /**
+ * Create OMRequest which encapsulates a CreateKeyRequest, optionally
+ * with metadata.
+ *
+ * @param isMultipartKey Indicates if the key is part of a multipart upload.
+ * @param partNumber The part number for multipart uploads, ignored if
+ * isMultipartKey is false.
+ * @param keyName The name of the key to create or update.
+ * @param metadata Optional metadata for the key. Pass null or an empty
+ * map if no metadata is to be set.
+ * @return OMRequest configured with the provided parameters.
+ */
+ protected OMRequest createKeyRequest(boolean isMultipartKey, int partNumber,
+ String keyName,
+ Map<String, String> metadata) {
KeyArgs.Builder keyArgs = KeyArgs.newBuilder()
- .setVolumeName(volumeName).setBucketName(bucketName)
- .setKeyName(keyName).setIsMultipartKey(isMultipartKey)
- .setFactor(((RatisReplicationConfig)
replicationConfig).getReplicationFactor())
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setKeyName(keyName)
+ .setIsMultipartKey(isMultipartKey)
+ .setFactor(
+ ((RatisReplicationConfig)
replicationConfig).getReplicationFactor())
.setType(replicationConfig.getReplicationType())
.setLatestVersionLocation(true);
+ // Configure for multipart upload, if applicable
if (isMultipartKey) {
keyArgs.setDataSize(dataSize).setMultipartNumber(partNumber);
}
+ // Include metadata, if provided
+ if (metadata != null && !metadata.isEmpty()) {
+ metadata.forEach((key, value) ->
keyArgs.addMetadata(KeyValue.newBuilder()
+ .setKey(key)
+ .setValue(value)
+ .build()));
+ }
+
OzoneManagerProtocolProtos.CreateKeyRequest createKeyRequest =
CreateKeyRequest.newBuilder().setKeyArgs(keyArgs).build();
return OMRequest.newBuilder()
.setCmdType(OzoneManagerProtocolProtos.Type.CreateKey)
.setClientId(UUID.randomUUID().toString())
- .setCreateKeyRequest(createKeyRequest).build();
+ .setCreateKeyRequest(createKeyRequest)
+ .build();
}
private OMRequest createKeyRequest(
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]