This is an automated email from the ASF dual-hosted git repository.
weichiu pushed a commit to branch HDDS-7593
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/HDDS-7593 by this push:
new 2651d4c208 HDDS-9930. Remove open keys as well when keys are deleted
from KeyTable (#6079)
2651d4c208 is described below
commit 2651d4c20851f78d5059a7145edc4e17a0b52608
Author: Siyao Meng <[email protected]>
AuthorDate: Fri Jan 26 14:42:08 2024 -0800
HDDS-9930. Remove open keys as well when keys are deleted from KeyTable
(#6079)
---
.../java/org/apache/hadoop/fs/ozone/TestHSync.java | 41 ++++++++++++++++++++++
.../apache/hadoop/ozone/om/OMMetadataManager.java | 33 +++++++++++++++--
.../hadoop/ozone/om/OmMetadataManagerImpl.java | 8 ++---
.../ozone/om/request/key/OMKeyCommitRequest.java | 2 +-
.../ozone/om/request/key/OMKeyDeleteRequest.java | 24 +++++++++----
.../om/request/key/OMKeyDeleteRequestWithFSO.java | 23 +++++++++---
.../ozone/om/request/key/OMKeysDeleteRequest.java | 36 ++++++++++++++-----
.../om/request/key/OmKeysDeleteRequestWithFSO.java | 36 +++++++++++++++----
.../ozone/om/response/key/OMKeyDeleteResponse.java | 18 ++++++++--
.../response/key/OMKeyDeleteResponseWithFSO.java | 12 +++++--
.../om/response/key/OMKeysDeleteResponse.java | 17 +++++++--
.../response/key/OMKeysDeleteResponseWithFSO.java | 13 +++++--
.../om/response/key/TestOMKeyDeleteResponse.java | 2 +-
.../key/TestOMKeyDeleteResponseWithFSO.java | 2 +-
.../om/response/key/TestOMKeysDeleteResponse.java | 3 +-
.../key/TestOMKeysDeleteResponseWithFSO.java | 3 +-
16 files changed, 225 insertions(+), 48 deletions(-)
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSync.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSync.java
index 7a1c055b00..c7a5c23164 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSync.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSync.java
@@ -63,6 +63,7 @@ import org.apache.hadoop.ozone.client.io.OzoneOutputStream;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OMMetrics;
import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.om.helpers.RepeatedOmKeyInfo;
@@ -231,6 +232,46 @@ public class TestHSync {
}
}
+ @Test
+ public void testHSyncDeletedKey() throws Exception {
+ // Verify that a key can't be successfully hsync'ed again after it's
deleted,
+ // and that key won't reappear after a failed hsync.
+
+ // Set the fs.defaultFS
+ final String rootPath = String.format("%s://%s/",
+ OZONE_OFS_URI_SCHEME, CONF.get(OZONE_OM_ADDRESS_KEY));
+ CONF.set(CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY, rootPath);
+
+ final String dir = OZONE_ROOT + bucket.getVolumeName()
+ + OZONE_URI_DELIMITER + bucket.getName();
+ final Path key1 = new Path(dir, "key-hsync-del");
+
+ try (FileSystem fs = FileSystem.get(CONF)) {
+ // Create key1
+ try (FSDataOutputStream os = fs.create(key1, true)) {
+ os.write(1);
+ os.hsync();
+ fs.delete(key1, false);
+
+ // getFileStatus should throw FNFE because the key is deleted
+ assertThrows(FileNotFoundException.class,
+ () -> fs.getFileStatus(key1));
+ // hsync should throw because the open key is gone
+ try {
+ os.hsync();
+ } catch (OMException omEx) {
+ assertEquals(OMException.ResultCodes.KEY_NOT_FOUND,
omEx.getResult());
+ }
+ // key1 should not reappear after failed hsync
+ assertThrows(FileNotFoundException.class,
+ () -> fs.getFileStatus(key1));
+ } catch (OMException ex) {
+ // os.close() throws OMException because the key is deleted
+ assertEquals(OMException.ResultCodes.KEY_NOT_FOUND, ex.getResult());
+ }
+ }
+ }
+
@Test
public void testUncommittedBlocks() throws Exception {
// Set the fs.defaultFS
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 bf61c037db..85af6e538d 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
@@ -158,7 +158,21 @@ public interface OMMetadataManager extends
DBStoreHAManager {
* @param id - the id for this open
* @return bytes of DB key.
*/
- String getOpenKey(String volume, String bucket, String key, long id);
+ default String getOpenKey(String volume, String bucket, String key, long id)
{
+ return getOpenKey(volume, bucket, key, String.valueOf(id));
+ }
+
+ /**
+ * Returns the DB key name of a open key in OM metadata store. Should be
+ * #open# prefix followed by actual key name.
+ *
+ * @param volume - volume name
+ * @param bucket - bucket name
+ * @param key - key name
+ * @param clientId - client Id String for this open key
+ * @return bytes of DB key.
+ */
+ String getOpenKey(String volume, String bucket, String key, String clientId);
/**
* Returns client ID in Long of an OpenKeyTable DB Key String.
@@ -572,9 +586,22 @@ public interface OMMetadataManager extends
DBStoreHAManager {
* @param id - client id for this open request
* @return DB directory key as String.
*/
- String getOpenFileName(long volumeId, long bucketId,
- long parentObjectId, String fileName, long id);
+ default String getOpenFileName(long volumeId, long bucketId, long
parentObjectId, String fileName, long id) {
+ return getOpenFileName(volumeId, bucketId, parentObjectId, fileName,
String.valueOf(id));
+ }
+ /**
+ * Returns DB key name of an open file in OM metadata store. Should be
+ * #open# prefix followed by actual leaf node name.
+ *
+ * @param volumeId - ID of the volume
+ * @param bucketId - ID of the bucket
+ * @param parentObjectId - parent object Id
+ * @param fileName - file name
+ * @param clientId - client id String for this open request
+ * @return DB directory key as String.
+ */
+ String getOpenFileName(long volumeId, long bucketId, long parentObjectId,
String fileName, String clientId);
/**
* Given a volume, bucket and a objectID, return the DB key name in
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 b340ce08a8..86ba834bc9 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
@@ -865,9 +865,9 @@ public class OmMetadataManagerImpl implements
OMMetadataManager,
@Override
public String getOpenKey(String volume, String bucket,
- String key, long id) {
+ String key, String clientId) {
String openKey = OM_KEY_PREFIX + volume + OM_KEY_PREFIX + bucket +
- OM_KEY_PREFIX + key + OM_KEY_PREFIX + id;
+ OM_KEY_PREFIX + key + OM_KEY_PREFIX + clientId;
return openKey;
}
@@ -2183,13 +2183,13 @@ public class OmMetadataManagerImpl implements
OMMetadataManager,
@Override
public String getOpenFileName(long volumeId, long bucketId,
long parentID, String fileName,
- long id) {
+ String clientId) {
StringBuilder openKey = new StringBuilder();
openKey.append(OM_KEY_PREFIX).append(volumeId);
openKey.append(OM_KEY_PREFIX).append(bucketId);
openKey.append(OM_KEY_PREFIX).append(parentID);
openKey.append(OM_KEY_PREFIX).append(fileName);
- openKey.append(OM_KEY_PREFIX).append(id);
+ openKey.append(OM_KEY_PREFIX).append(clientId);
return openKey.toString();
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java
index dbf50230ff..ab6357a01d 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java
@@ -251,7 +251,7 @@ public class OMKeyCommitRequest extends OMKeyRequest {
if (omKeyInfo == null) {
String action = isRecovery ? "recovery" : isHSync ? "hsync" : "commit";
throw new OMException("Failed to " + action + " key, as " + dbOpenKey +
- "entry is not found in the OpenKey table", KEY_NOT_FOUND);
+ " entry is not found in the OpenKey table", KEY_NOT_FOUND);
}
if (omKeyInfo.getMetadata().containsKey(OzoneConsts.LEASE_RECOVERY) &&
omKeyInfo.getMetadata().containsKey(OzoneConsts.HSYNC_CLIENT_ID)) {
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
index 82d3bdc9e8..61e5976f80 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java
@@ -22,6 +22,8 @@ import java.io.IOException;
import java.nio.file.InvalidPathException;
import java.util.Map;
+import org.apache.hadoop.hdds.utils.db.Table;
+import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.ratis.server.protocol.TermIndex;
import org.apache.hadoop.ozone.OmUtils;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
@@ -147,7 +149,7 @@ public class OMKeyDeleteRequest extends OMKeyRequest {
// Set the UpdateID to current transactionLogIndex
omKeyInfo.setUpdateID(trxnLogIndex, ozoneManager.isRatisEnabled());
- // Update table cache.
+ // Update table cache. Put a tombstone entry
omMetadataManager.getKeyTable(getBucketLayout()).addCacheEntry(
new CacheKey<>(
omMetadataManager.getOzoneKey(volumeName, bucketName, keyName)),
@@ -160,15 +162,25 @@ public class OMKeyDeleteRequest extends OMKeyRequest {
omBucketInfo.incrUsedBytes(-quotaReleased);
omBucketInfo.incrUsedNamespace(-1L);
- // No need to add cache entries to delete table. As delete table will
- // be used by DeleteKeyService only, not used for any client response
- // validation, so we don't need to add to cache.
- // TODO: Revisit if we need it later.
+ // If omKeyInfo has hsync metadata, delete its corresponding open key as
well
+ String dbOpenKey = null;
+ String hsyncClientId =
omKeyInfo.getMetadata().get(OzoneConsts.HSYNC_CLIENT_ID);
+ if (hsyncClientId != null) {
+ Table<String, OmKeyInfo> openKeyTable =
omMetadataManager.getOpenKeyTable(getBucketLayout());
+ dbOpenKey = omMetadataManager.getOpenKey(volumeName, bucketName,
keyName, hsyncClientId);
+ OmKeyInfo openKeyInfo = openKeyTable.get(dbOpenKey);
+ if (openKeyInfo != null) {
+ // Remove the open key by putting a tombstone entry
+ openKeyTable.addCacheEntry(dbOpenKey, trxnLogIndex);
+ } else {
+ LOG.warn("Potentially inconsistent DB state: open key not found with
dbOpenKey '{}'", dbOpenKey);
+ }
+ }
omClientResponse = new OMKeyDeleteResponse(
omResponse.setDeleteKeyResponse(DeleteKeyResponse.newBuilder())
.build(), omKeyInfo, ozoneManager.isRatisEnabled(),
- omBucketInfo.copyObject());
+ omBucketInfo.copyObject(), dbOpenKey);
result = Result.SUCCESS;
} catch (IOException | InvalidPathException ex) {
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
index a817c71165..a0b2cfcbb1 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequestWithFSO.java
@@ -18,6 +18,8 @@
package org.apache.hadoop.ozone.om.request.key;
+import org.apache.hadoop.hdds.utils.db.Table;
+import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.ratis.server.protocol.TermIndex;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
@@ -154,15 +156,26 @@ public class OMKeyDeleteRequestWithFSO extends
OMKeyDeleteRequest {
omBucketInfo.incrUsedBytes(-quotaReleased);
omBucketInfo.incrUsedNamespace(-1L);
- // No need to add cache entries to delete table. As delete table will
- // be used by DeleteKeyService only, not used for any client response
- // validation, so we don't need to add to cache.
- // TODO: Revisit if we need it later.
+ // If omKeyInfo has hsync metadata, delete its corresponding open key as
well
+ String dbOpenKey = null;
+ String hsyncClientId =
omKeyInfo.getMetadata().get(OzoneConsts.HSYNC_CLIENT_ID);
+ if (hsyncClientId != null) {
+ Table<String, OmKeyInfo> openKeyTable =
omMetadataManager.getOpenKeyTable(getBucketLayout());
+ long parentId = omKeyInfo.getParentObjectID();
+ dbOpenKey = omMetadataManager.getOpenFileName(volumeId, bucketId,
parentId, fileName, hsyncClientId);
+ OmKeyInfo openKeyInfo = openKeyTable.get(dbOpenKey);
+ if (openKeyInfo != null) {
+ // Remove the open key by putting a tombstone entry
+ openKeyTable.addCacheEntry(dbOpenKey, trxnLogIndex);
+ } else {
+ LOG.warn("Potentially inconsistent DB state: open key not found with
dbOpenKey '{}'", dbOpenKey);
+ }
+ }
omClientResponse = new OMKeyDeleteResponseWithFSO(omResponse
.setDeleteKeyResponse(DeleteKeyResponse.newBuilder()).build(),
keyName, omKeyInfo, ozoneManager.isRatisEnabled(),
- omBucketInfo.copyObject(), keyStatus.isDirectory(), volumeId);
+ omBucketInfo.copyObject(), keyStatus.isDirectory(), volumeId,
dbOpenKey);
result = Result.SUCCESS;
} catch (IOException | InvalidPathException ex) {
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java
index 20879a5094..6ddd257e22 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java
@@ -19,6 +19,8 @@
package org.apache.hadoop.ozone.om.request.key;
import org.apache.commons.lang3.tuple.Pair;
+import org.apache.hadoop.hdds.utils.db.Table;
+import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.ratis.server.protocol.TermIndex;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
@@ -172,17 +174,18 @@ public class OMKeysDeleteRequest extends OMKeyRequest {
OmBucketInfo omBucketInfo =
getBucketInfo(omMetadataManager, volumeName, bucketName);
+ List<String> dbOpenKeys = new ArrayList<>();
// Mark all keys which can be deleted, in cache as deleted.
quotaReleased =
markKeysAsDeletedInCache(ozoneManager, trxnLogIndex, omKeyInfoList,
- dirList, omMetadataManager, quotaReleased);
+ dirList, omMetadataManager, quotaReleased, dbOpenKeys);
omBucketInfo.incrUsedBytes(-quotaReleased);
omBucketInfo.incrUsedNamespace(-1L * omKeyInfoList.size());
final long volumeId = omMetadataManager.getVolumeId(volumeName);
omClientResponse =
getOmClientResponse(ozoneManager, omKeyInfoList, dirList, omResponse,
- unDeletedKeys, deleteStatus, omBucketInfo, volumeId);
+ unDeletedKeys, deleteStatus, omBucketInfo, volumeId, dbOpenKeys);
result = Result.SUCCESS;
@@ -257,7 +260,7 @@ public class OMKeysDeleteRequest extends OMKeyRequest {
List<OmKeyInfo> omKeyInfoList, List<OmKeyInfo> dirList,
OMResponse.Builder omResponse,
OzoneManagerProtocolProtos.DeleteKeyArgs.Builder unDeletedKeys,
- boolean deleteStatus, OmBucketInfo omBucketInfo, long volumeId) {
+ boolean deleteStatus, OmBucketInfo omBucketInfo, long volumeId,
List<String> dbOpenKeys) {
OMClientResponse omClientResponse;
omClientResponse = new OMKeysDeleteResponse(omResponse
.setDeleteKeysResponse(
@@ -265,23 +268,40 @@ public class OMKeysDeleteRequest extends OMKeyRequest {
.setUnDeletedKeys(unDeletedKeys))
.setStatus(deleteStatus ? OK : PARTIAL_DELETE).setSuccess(deleteStatus)
.build(), omKeyInfoList, ozoneManager.isRatisEnabled(),
- omBucketInfo.copyObject());
+ omBucketInfo.copyObject(), dbOpenKeys);
return omClientResponse;
}
protected long markKeysAsDeletedInCache(OzoneManager ozoneManager,
long trxnLogIndex, List<OmKeyInfo> omKeyInfoList, List<OmKeyInfo>
dirList,
- OMMetadataManager omMetadataManager, long quotaReleased)
+ OMMetadataManager omMetadataManager, long quotaReleased, List<String>
dbOpenKeys)
throws IOException {
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
+ String volumeName = omKeyInfo.getVolumeName();
+ String bucketName = omKeyInfo.getBucketName();
+ String keyName = omKeyInfo.getKeyName();
omMetadataManager.getKeyTable(getBucketLayout()).addCacheEntry(
- new CacheKey<>(omMetadataManager
- .getOzoneKey(omKeyInfo.getVolumeName(),
omKeyInfo.getBucketName(),
- omKeyInfo.getKeyName())),
+ new CacheKey<>(omMetadataManager.getOzoneKey(volumeName, bucketName,
keyName)),
CacheValue.get(trxnLogIndex));
omKeyInfo.setUpdateID(trxnLogIndex, ozoneManager.isRatisEnabled());
quotaReleased += sumBlockLengths(omKeyInfo);
+
+ // If omKeyInfo has hsync metadata, delete its corresponding open key as
well
+ String hsyncClientId =
omKeyInfo.getMetadata().get(OzoneConsts.HSYNC_CLIENT_ID);
+ if (hsyncClientId != null) {
+ Table<String, OmKeyInfo> openKeyTable =
omMetadataManager.getOpenKeyTable(getBucketLayout());
+ String dbOpenKey = omMetadataManager.getOpenKey(volumeName,
bucketName, keyName, hsyncClientId);
+ OmKeyInfo openKeyInfo = openKeyTable.get(dbOpenKey);
+ if (openKeyInfo != null) {
+ // Remove the open key by putting a tombstone entry
+ openKeyTable.addCacheEntry(dbOpenKey, trxnLogIndex);
+ // Append to the list of open keys to be deleted. The list is not
expected to be large.
+ dbOpenKeys.add(dbOpenKey);
+ } else {
+ LOG.warn("Potentially inconsistent DB state: open key not found with
dbOpenKey '{}'", dbOpenKey);
+ }
+ }
}
return quotaReleased;
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OmKeysDeleteRequestWithFSO.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OmKeysDeleteRequestWithFSO.java
index e71c178ba5..8858458f2c 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OmKeysDeleteRequestWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OmKeysDeleteRequestWithFSO.java
@@ -17,8 +17,10 @@
*/
package org.apache.hadoop.ozone.om.request.key;
+import org.apache.hadoop.hdds.utils.db.Table;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
+import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
@@ -30,6 +32,8 @@ import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.om.response.key.OMKeysDeleteResponseWithFSO;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
@@ -42,6 +46,8 @@ import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.
*/
public class OmKeysDeleteRequestWithFSO extends OMKeysDeleteRequest {
+ public static final Logger LOG =
LoggerFactory.getLogger(OmKeysDeleteRequestWithFSO.class);
+
public OmKeysDeleteRequestWithFSO(
OzoneManagerProtocolProtos.OMRequest omRequest,
BucketLayout bucketLayout) {
@@ -82,7 +88,7 @@ public class OmKeysDeleteRequestWithFSO extends
OMKeysDeleteRequest {
OzoneManager ozoneManager, long trxnLogIndex,
List<OmKeyInfo> omKeyInfoList,
List<OmKeyInfo> dirList, OMMetadataManager omMetadataManager,
- long quotaReleased) throws IOException {
+ long quotaReleased, List<String> dbOpenKeys) throws IOException {
// Mark all keys which can be deleted, in cache as deleted.
for (OmKeyInfo omKeyInfo : omKeyInfoList) {
@@ -90,16 +96,33 @@ public class OmKeysDeleteRequestWithFSO extends
OMKeysDeleteRequest {
omKeyInfo.getVolumeName());
final long bucketId = omMetadataManager.getBucketId(
omKeyInfo.getVolumeName(), omKeyInfo.getBucketName());
+ final long parentId = omKeyInfo.getParentObjectID();
+ final String fileName = omKeyInfo.getFileName();
omMetadataManager.getKeyTable(getBucketLayout()).addCacheEntry(
new CacheKey<>(omMetadataManager
- .getOzonePathKey(volumeId, bucketId,
- omKeyInfo.getParentObjectID(),
- omKeyInfo.getFileName())),
+ .getOzonePathKey(volumeId, bucketId, parentId, fileName)),
CacheValue.get(trxnLogIndex));
omKeyInfo.setUpdateID(trxnLogIndex, ozoneManager.isRatisEnabled());
quotaReleased += sumBlockLengths(omKeyInfo);
+
+ // If omKeyInfo has hsync metadata, delete its corresponding open key as
well
+ String hsyncClientId =
omKeyInfo.getMetadata().get(OzoneConsts.HSYNC_CLIENT_ID);
+ if (hsyncClientId != null) {
+ Table<String, OmKeyInfo> openKeyTable =
omMetadataManager.getOpenKeyTable(getBucketLayout());
+ String dbOpenKey = omMetadataManager.getOpenFileName(volumeId,
bucketId, parentId, fileName, hsyncClientId);
+ OmKeyInfo openKeyInfo = openKeyTable.get(dbOpenKey);
+ if (openKeyInfo != null) {
+ // Remove the open key by putting a tombstone entry
+ openKeyTable.addCacheEntry(dbOpenKey, trxnLogIndex);
+ // Append to the list of open keys to be deleted. The list is not
expected to be large.
+ dbOpenKeys.add(dbOpenKey);
+ } else {
+ LOG.warn("Potentially inconsistent DB state: open key not found with
dbOpenKey '{}'", dbOpenKey);
+ }
+ }
}
+
// Mark directory keys.
for (OmKeyInfo omKeyInfo : dirList) {
final long volumeId = omMetadataManager.getVolumeId(
@@ -123,7 +146,7 @@ public class OmKeysDeleteRequestWithFSO extends
OMKeysDeleteRequest {
List<OmKeyInfo> omKeyInfoList, List<OmKeyInfo> dirList,
OzoneManagerProtocolProtos.OMResponse.Builder omResponse,
OzoneManagerProtocolProtos.DeleteKeyArgs.Builder unDeletedKeys,
- boolean deleteStatus, OmBucketInfo omBucketInfo, long volumeId) {
+ boolean deleteStatus, OmBucketInfo omBucketInfo, long volumeId,
List<String> dbOpenKeys) {
OMClientResponse omClientResponse;
omClientResponse = new OMKeysDeleteResponseWithFSO(omResponse
.setDeleteKeysResponse(
@@ -131,8 +154,7 @@ public class OmKeysDeleteRequestWithFSO extends
OMKeysDeleteRequest {
.setStatus(deleteStatus).setUnDeletedKeys(unDeletedKeys))
.setStatus(deleteStatus ? OK : PARTIAL_DELETE).setSuccess(deleteStatus)
.build(), omKeyInfoList, dirList, ozoneManager.isRatisEnabled(),
- omBucketInfo.copyObject(), volumeId);
+ omBucketInfo.copyObject(), volumeId, dbOpenKeys);
return omClientResponse;
-
}
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponse.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponse.java
index 828f82d853..7e5339ee54 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponse.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponse.java
@@ -34,22 +34,26 @@ import javax.annotation.Nonnull;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.BUCKET_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DELETED_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.KEY_TABLE;
+import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.OPEN_KEY_TABLE;
/**
* Response for DeleteKey request.
*/
-@CleanupTableInfo(cleanupTables = {KEY_TABLE, DELETED_TABLE, BUCKET_TABLE})
+@CleanupTableInfo(cleanupTables = {KEY_TABLE, OPEN_KEY_TABLE, DELETED_TABLE,
BUCKET_TABLE})
public class OMKeyDeleteResponse extends AbstractOMKeyDeleteResponse {
private OmKeyInfo omKeyInfo;
private OmBucketInfo omBucketInfo;
+ // If not null, this key will be deleted from OpenKeyTable
+ private String dbOpenKey;
public OMKeyDeleteResponse(@Nonnull OMResponse omResponse,
@Nonnull OmKeyInfo omKeyInfo, boolean isRatisEnabled,
- @Nonnull OmBucketInfo omBucketInfo) {
+ @Nonnull OmBucketInfo omBucketInfo, String dbOpenKey) {
super(omResponse, isRatisEnabled, omBucketInfo.getBucketLayout());
this.omKeyInfo = omKeyInfo;
this.omBucketInfo = omBucketInfo;
+ this.dbOpenKey = dbOpenKey;
}
/**
@@ -78,6 +82,12 @@ public class OMKeyDeleteResponse extends
AbstractOMKeyDeleteResponse {
omMetadataManager.getBucketTable().putWithBatch(batchOperation,
omMetadataManager.getBucketKey(omBucketInfo.getVolumeName(),
omBucketInfo.getBucketName()), omBucketInfo);
+
+ // Remove open key (necessary when the file is hsync'ed but not committed)
+ if (dbOpenKey != null) {
+ omMetadataManager.getOpenKeyTable(getBucketLayout()).deleteWithBatch(
+ batchOperation, dbOpenKey);
+ }
}
protected OmKeyInfo getOmKeyInfo() {
@@ -87,4 +97,8 @@ public class OMKeyDeleteResponse extends
AbstractOMKeyDeleteResponse {
protected OmBucketInfo getOmBucketInfo() {
return omBucketInfo;
}
+
+ public String getDbOpenKey() {
+ return dbOpenKey;
+ }
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponseWithFSO.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponseWithFSO.java
index c2773429f4..b52e4f4476 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponseWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeyDeleteResponseWithFSO.java
@@ -35,11 +35,12 @@ import static
org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DELETED_DIR_TABLE
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DELETED_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DIRECTORY_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.FILE_TABLE;
+import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.OPEN_FILE_TABLE;
/**
* Response for DeleteKey request.
*/
-@CleanupTableInfo(cleanupTables = {FILE_TABLE, DIRECTORY_TABLE,
+@CleanupTableInfo(cleanupTables = {FILE_TABLE, OPEN_FILE_TABLE,
DIRECTORY_TABLE,
DELETED_TABLE, DELETED_DIR_TABLE, BUCKET_TABLE})
public class OMKeyDeleteResponseWithFSO extends OMKeyDeleteResponse {
@@ -51,8 +52,8 @@ public class OMKeyDeleteResponseWithFSO extends
OMKeyDeleteResponse {
public OMKeyDeleteResponseWithFSO(@Nonnull OMResponse omResponse,
@Nonnull String keyName, @Nonnull OmKeyInfo omKeyInfo,
boolean isRatisEnabled, @Nonnull OmBucketInfo omBucketInfo,
- @Nonnull boolean isDeleteDirectory, @Nonnull long volumeId) {
- super(omResponse, omKeyInfo, isRatisEnabled, omBucketInfo);
+ @Nonnull boolean isDeleteDirectory, @Nonnull long volumeId, String
dbOpenKey) {
+ super(omResponse, omKeyInfo, isRatisEnabled, omBucketInfo, dbOpenKey);
this.keyName = keyName;
this.isDeleteDirectory = isDeleteDirectory;
this.volumeId = volumeId;
@@ -108,6 +109,11 @@ public class OMKeyDeleteResponseWithFSO extends
OMKeyDeleteResponse {
omMetadataManager.getBucketTable().putWithBatch(batchOperation,
omMetadataManager.getBucketKey(getOmBucketInfo().getVolumeName(),
getOmBucketInfo().getBucketName()), getOmBucketInfo());
+
+ if (getDbOpenKey() != null) {
+ omMetadataManager.getOpenKeyTable(getBucketLayout()).deleteWithBatch(
+ batchOperation, getDbOpenKey());
+ }
}
@Override
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponse.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponse.java
index cf09247e69..3c51842199 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponse.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponse.java
@@ -34,23 +34,27 @@ import java.util.List;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.BUCKET_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DELETED_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.KEY_TABLE;
+import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.OPEN_KEY_TABLE;
import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.OK;
import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.PARTIAL_DELETE;
/**
* Response for DeleteKey request.
*/
-@CleanupTableInfo(cleanupTables = {KEY_TABLE, DELETED_TABLE, BUCKET_TABLE})
+@CleanupTableInfo(cleanupTables = {KEY_TABLE, OPEN_KEY_TABLE, DELETED_TABLE,
BUCKET_TABLE})
public class OMKeysDeleteResponse extends AbstractOMKeyDeleteResponse {
private List<OmKeyInfo> omKeyInfoList;
private OmBucketInfo omBucketInfo;
+ private List<String> dbOpenKeys;
public OMKeysDeleteResponse(@Nonnull OMResponse omResponse,
@Nonnull List<OmKeyInfo> keyDeleteList,
- boolean isRatisEnabled, @Nonnull OmBucketInfo omBucketInfo) {
+ boolean isRatisEnabled, @Nonnull OmBucketInfo omBucketInfo,
+ @Nonnull List<String> dbOpenKeys) {
super(omResponse, isRatisEnabled);
this.omKeyInfoList = keyDeleteList;
this.omBucketInfo = omBucketInfo;
+ this.dbOpenKeys = dbOpenKeys;
}
/**
@@ -95,6 +99,11 @@ public class OMKeysDeleteResponse extends
AbstractOMKeyDeleteResponse {
omMetadataManager.getBucketTable().putWithBatch(batchOperation,
omMetadataManager.getBucketKey(omBucketInfo.getVolumeName(),
omBucketInfo.getBucketName()), omBucketInfo);
+
+ for (String dbOpenKey : dbOpenKeys) {
+ omMetadataManager.getOpenKeyTable(getBucketLayout()).deleteWithBatch(
+ batchOperation, dbOpenKey);
+ }
}
public List<OmKeyInfo> getOmKeyInfoList() {
@@ -104,4 +113,8 @@ public class OMKeysDeleteResponse extends
AbstractOMKeyDeleteResponse {
public OmBucketInfo getOmBucketInfo() {
return omBucketInfo;
}
+
+ public List<String> getDbOpenKeys() {
+ return dbOpenKeys;
+ }
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponseWithFSO.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponseWithFSO.java
index a5f5787030..43fed7ad15 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponseWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/key/OMKeysDeleteResponseWithFSO.java
@@ -36,11 +36,12 @@ import static
org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DELETED_DIR_TABLE
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DELETED_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.DIRECTORY_TABLE;
import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.FILE_TABLE;
+import static org.apache.hadoop.ozone.om.OmMetadataManagerImpl.OPEN_FILE_TABLE;
/**
* Response for DeleteKeys request.
*/
-@CleanupTableInfo(cleanupTables = { FILE_TABLE, DIRECTORY_TABLE,
+@CleanupTableInfo(cleanupTables = { FILE_TABLE, OPEN_FILE_TABLE,
DIRECTORY_TABLE,
DELETED_DIR_TABLE, DELETED_TABLE, BUCKET_TABLE })
public class OMKeysDeleteResponseWithFSO extends OMKeysDeleteResponse {
@@ -51,8 +52,9 @@ public class OMKeysDeleteResponseWithFSO extends
OMKeysDeleteResponse {
@NotNull OzoneManagerProtocolProtos.OMResponse omResponse,
@NotNull List<OmKeyInfo> keyDeleteList,
@NotNull List<OmKeyInfo> dirDeleteList, boolean isRatisEnabled,
- @NotNull OmBucketInfo omBucketInfo, @Nonnull long volId) {
- super(omResponse, keyDeleteList, isRatisEnabled, omBucketInfo);
+ @NotNull OmBucketInfo omBucketInfo, @Nonnull long volId,
+ @Nonnull List<String> dbOpenKeys) {
+ super(omResponse, keyDeleteList, isRatisEnabled, omBucketInfo, dbOpenKeys);
this.dirsList = dirDeleteList;
this.volumeId = volId;
}
@@ -93,6 +95,11 @@ public class OMKeysDeleteResponseWithFSO extends
OMKeysDeleteResponse {
omMetadataManager.getBucketTable().putWithBatch(batchOperation,
omMetadataManager.getBucketKey(getOmBucketInfo().getVolumeName(),
getOmBucketInfo().getBucketName()), getOmBucketInfo());
+
+ for (String dbOpenKey : getDbOpenKeys()) {
+ omMetadataManager.getOpenKeyTable(getBucketLayout()).deleteWithBatch(
+ batchOperation, dbOpenKey);
+ }
}
@Override
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponse.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponse.java
index 4690b6f56f..a000c3f969 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponse.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponse.java
@@ -173,7 +173,7 @@ public class TestOMKeyDeleteResponse extends
TestOMKeyResponse {
protected OMKeyDeleteResponse getOmKeyDeleteResponse(OmKeyInfo omKeyInfo,
OzoneManagerProtocolProtos.OMResponse omResponse) throws Exception {
- return new OMKeyDeleteResponse(omResponse, omKeyInfo, true, omBucketInfo);
+ return new OMKeyDeleteResponse(omResponse, omKeyInfo, true, omBucketInfo,
null);
}
protected OmBucketInfo getOmBucketInfo() {
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponseWithFSO.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponseWithFSO.java
index fda72eb912..588907c6ce 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponseWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeyDeleteResponseWithFSO.java
@@ -36,7 +36,7 @@ public class TestOMKeyDeleteResponseWithFSO extends
TestOMKeyDeleteResponse {
OzoneManagerProtocolProtos.OMResponse omResponse) throws Exception {
return new OMKeyDeleteResponseWithFSO(omResponse, omKeyInfo.getKeyName(),
omKeyInfo, true, getOmBucketInfo(), false,
- omMetadataManager.getVolumeId(volumeName));
+ omMetadataManager.getVolumeId(volumeName), null);
}
@Override
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponse.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponse.java
index 0c9c725c1b..60f371ba1f 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponse.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponse.java
@@ -28,6 +28,7 @@ import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRespo
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import static
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE;
@@ -103,7 +104,7 @@ public class TestOMKeysDeleteResponse extends
TestOMKeyResponse {
protected OMClientResponse getOmKeysDeleteResponse(OMResponse omResponse,
OmBucketInfo omBucketInfo) {
return new OMKeysDeleteResponse(
- omResponse, omKeyInfoList, true, omBucketInfo);
+ omResponse, omKeyInfoList, true, omBucketInfo,
Collections.emptyList());
}
@Test
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponseWithFSO.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponseWithFSO.java
index fd70308c43..148a4e28c1 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponseWithFSO.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/key/TestOMKeysDeleteResponseWithFSO.java
@@ -38,6 +38,7 @@ import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.OK;
@@ -110,7 +111,7 @@ public class TestOMKeysDeleteResponseWithFSO
OmBucketInfo omBucketInfo) {
return new OMKeysDeleteResponseWithFSO(
omResponse, getOmKeyInfoList(), dirDeleteList, true, omBucketInfo,
- volId);
+ volId, Collections.emptyList());
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]