This is an automated email from the ASF dual-hosted git repository.
ChenSammi 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 c50d89a4550 HDDS-16162. Fail lifecycle task when KeyLifecycleService
cannot prepare trash root (#11021)
c50d89a4550 is described below
commit c50d89a4550a9c39a10e89bfcd2caad8e57149ee
Author: Aryan Gupta <[email protected]>
AuthorDate: Fri Aug 21 13:11:11 2026 +0530
HDDS-16162. Fail lifecycle task when KeyLifecycleService cannot prepare
trash root (#11021)
---
.../ozone/om/service/KeyLifecycleService.java | 13 ++++-
.../ozone/om/service/TestKeyLifecycleService.java | 67 ++++++++++++++++++++++
2 files changed, 77 insertions(+), 3 deletions(-)
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
index 9ff0929c3a3..f3c86851a85 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/KeyLifecycleService.java
@@ -1555,8 +1555,10 @@ private void moveToTrash(OmBucketInfo bucket,
LimitedExpiredObjectList keysList,
try {
checkAndCreateTrashDirIfNeeded(bucket, trashCurrent);
} catch (IOException e) {
- keysList.clear();
- return;
+ String message =
+ "Failed to prepare trash root " + trashCurrent + " for bucket " +
volumeName + "/" + bucketName;
+ LOG.error(message, e);
+ throw new IllegalStateException(message, e);
}
for (int i = 0; i < keysList.size(); i++) {
@@ -1607,8 +1609,10 @@ public OzoneManagerProtocolProtos.OMResponse run()
throws Exception {
});
if (omResponse != null) {
if (!omResponse.getSuccess()) {
+ OzoneManagerProtocolProtos.Status status =
omResponse.getStatus();
// log the failure and continue the iterating
- LOG.error("RenameKey request failed with source key: {}, dest
key: {}", keyName, targetKeyName);
+ LOG.error("RenameKey request failed with source key: {}, dest
key: {}, status: {}",
+ keyName, targetKeyName, status);
continue;
}
}
@@ -1624,6 +1628,9 @@ public OzoneManagerProtocolProtos.OMResponse run() throws
Exception {
metrics.incrSizeKeyRenamed(keysList.getReplicatedSize(i));
}
} catch (IOException | InterruptedException e) {
+ if (e instanceof InterruptedException) {
+ Thread.currentThread().interrupt();
+ }
LOG.error("Failed to send RenameKeysRequest", e);
}
}
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
index ab725ba4800..ccc3275af87 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestKeyLifecycleService.java
@@ -88,6 +88,7 @@
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdds.client.BlockID;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
@@ -2681,6 +2682,72 @@ void testDisableMoveToTrashDeletesDirectly() throws
Exception {
deleteLifecyclePolicy(volumeName, bucketName);
}
+ @Test
+ void testMoveToTrashAbortTaskWhenTrashRootPrepareFails() throws Exception {
+ final String volumeName = getTestName();
+ final String bucketName = uniqueObjectName("bucket");
+ final String keyPrefix = "key";
+ String bucketOwner =
UserGroupInformation.getCurrentUser().getShortUserName() + "-test";
+ long initialKeyCount = getKeyCount(FILE_SYSTEM_OPTIMIZED);
+ long initialSuccessTaskCount = metrics.getNumSuccessTask().value();
+
+ createKeys(volumeName, bucketName, FILE_SYSTEM_OPTIMIZED, bucketOwner,
1, 1, keyPrefix, null);
+ Thread.sleep(SERVICE_INTERVAL);
+ GenericTestUtils.waitFor(() -> getKeyCount(FILE_SYSTEM_OPTIMIZED) -
initialKeyCount == 1,
+ WAIT_CHECK_INTERVAL, 1000);
+
+ keyLifecycleService.setMoveToTrashEnabled(true);
+ final float trashInterval = 0.5f;
+ conf.setFloat(FS_TRASH_INTERVAL_KEY, trashInterval);
+ FileSystem fs = SecurityUtil.doAsLoginUser(
+ (PrivilegedExceptionAction<FileSystem>)
+ () -> new TrashOzoneFileSystem(om));
+ keyLifecycleService.setOzoneTrash(new OzoneTrash(fs, conf, om));
+
+ OmLifecycleConfiguration policy = new OmLifecycleConfiguration.Builder()
+ .setVolume(volumeName)
+ .setBucket(bucketName)
+ .setBucketLayout(FILE_SYSTEM_OPTIMIZED)
+ .setBucketObjectID(bucketObjectID)
+ .setRules(Collections.singletonList(new OmLCRule.Builder()
+ .setId(String.valueOf(OBJECT_ID_COUNTER.getAndIncrement()))
+ .setEnabled(true)
+ .setPrefix("")
+ .setAction(new OmLCExpiration.Builder()
+
.setDate(ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(EXPIRE_SECONDS).toString())
+ .build())
+ .build()))
+ .build();
+
+ String expectedTrashRoot = new Path(TRASH_PREFIX + OM_KEY_PREFIX +
bucketOwner, CURRENT).toString();
+ OzoneManager omSpy = spy(om);
+ doThrow(new IOException("Injected trash root prepare failure"))
+ .when(omSpy).getFileStatus(argThat(key ->
+ key != null
+ && volumeName.equals(key.getVolumeName())
+ && bucketName.equals(key.getBucketName())
+ && expectedTrashRoot.equals(key.getKeyName())));
+
+ Field ozoneManagerField =
KeyLifecycleService.class.getDeclaredField("ozoneManager");
+ ozoneManagerField.setAccessible(true);
+ ozoneManagerField.set(keyLifecycleService, omSpy);
+
+ GenericTestUtils.LogCapturer log =
+
GenericTestUtils.LogCapturer.captureLogs(LoggerFactory.getLogger(KeyLifecycleService.class));
+ try {
+ KeyLifecycleService.LifecycleActionTask task = keyLifecycleService.new
LifecycleActionTask(policy);
+ task.call();
+
+ assertTrue(log.getOutput().contains("Failed to prepare trash root"));
+ assertTrue(log.getOutput().contains("Failed to evaluate lifecycle
configuration for bucket"));
+ assertEquals(initialSuccessTaskCount,
metrics.getNumSuccessTask().value());
+ assertEquals(1, getKeyCount(FILE_SYSTEM_OPTIMIZED) - initialKeyCount);
+ } finally {
+ ozoneManagerField.set(keyLifecycleService, om);
+ log.stopCapturing();
+ }
+ }
+
@Test
void testAbortIncompleteMultipartUploadWithFilters() throws Exception {
final String volumeName = getTestName();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]