Skip to content

HDDS-12983. Validator Registry Changes for Supporting Version based validations - #8404

Closed
swamirishi wants to merge 15 commits into
apache:masterfrom
swamirishi:HDDS-12983
Closed

HDDS-12983. Validator Registry Changes for Supporting Version based validations#8404
swamirishi wants to merge 15 commits into
apache:masterfrom
swamirishi:HDDS-12983

Conversation

@swamirishi

@swamirishiswamirishi commented May 6, 2025

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Making changes to the ValidatorRegistry class to be able to pull the validators registered and inturn being able to get all the underlying validator methods based on the usage of the registered feature validator based on a specified version, request processing phase and request type efficiently.
This is the last PR for completing the request validator fixes after breaking down
#6932 into smaller PRs

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-12983

How was this patch tested?

Adding unit tests

…alidations
Change-Id: I939888c989eaec0a62884aa564e2f24a594122ef
Change-Id: Icec10ce7bb452753db0936212b0757c01279b533
Change-Id: I9a010c86d0128da8140fa33b46eaeef9da0dc283

@adoroszlaiadoroszlai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @swamirishi for the patch.

Comment on lines +138 to +140
public List<Method> validationsFor(RequestType requestType,
RequestProcessingPhase phase,
Map<Class<? extends Annotation>, ? extends Versioned> requestVersions) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not format method signature like this. Whenever visibility / return type / method name / other modifiers are changed, we would have to reindent all parameters.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +177 to +179
Validator validator, String methodName, Class<ReturnValue> returnValueType) {
try {
return (ReturnValue) validator.getClass().getMethod(methodName).invoke(validator);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use returnValueType (currently unused) to cast the result, instead of using unchecked cast (ReturnValue).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

processingPhase = RequestProcessingPhase.PRE_PROCESS,
requestType = Type.CreateBucket
requestType = Type.CreateBucket,
applyBefore = ClientVersion.BUCKET_LAYOUT_SUPPORT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
applyBefore = ClientVersion.BUCKET_LAYOUT_SUPPORT
applyBefore = ClientVersion.BUCKET_LAYOUT_SUPPORT

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +50 to +52
* One validator can be applied in multiple, E.g.
* {@link org.apache.hadoop.ozone.om.request.validation.OMClientVersionValidator},
* {@link org.apache.hadoop.ozone.om.request.validation.OMLayoutVersionValidator}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this sentence makes sense.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the sentence lmk if it is ok now

Comment on lines +143 to +146
ValidatorRegistry<OzoneManagerProtocolProtos.Type> registry =
new ValidatorRegistry<>(OzoneManagerProtocolProtos.Type.class, PACKAGE,
Arrays.stream(VersionExtractor.values()).map(VersionExtractor::getValidatorClass).collect(Collectors.toSet()),
REQUEST_PROCESSING_PHASES);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid duplicating this logic in each test case?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +309 to +311
* @return All the items which has an index value greater than given index value.
*/
public List<T> getItemsEqualToIdx(IDX indexValue) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Javadoc mismatch ("greater than" vs. EqualTo)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

*/
private static final class IndexedItems<T, IDX extends Comparable<IDX>> {
private final List<T> items;
private final TreeMap<IDX, Integer> indexMap;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare as interface: NavigableMap.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +246 to +249
.sorted((validatorMethodPair1, validatorMethodPair2) ->
Integer.compare(
this.getApplyBeforeVersion(validatorMethodPair1.getKey()).version(),
this.getApplyBeforeVersion(validatorMethodPair2.getKey()).version()))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract this lambda to a static method.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +78 to +79
List<Method> validations = registry.validationsFor(request.getCmdType(), PRE_PROCESS,
this.getVersions(request));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove this. and do not wrap line.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Change-Id: Ibf524d42e3d8535377105a07f8ca3213c8c62199
Change-Id: I67634e5517239bdec3965ed8819f9af6ecf577dd
Change-Id: Idf26bbc7e83877a71f46bafdf0216d70733a92ee
Change-Id: Idecefb392dbf5c01227d7c3702db1781b9edb073
Change-Id: I174cea546d6fd021e58966b3a5bca3672e9d567e
# Conflicts:
#	hadoop-ozone/client/pom.xml
#	hadoop-ozone/interface-storage/pom.xml
#	hadoop-ozone/recon-codegen/pom.xml
#	hadoop-ozone/s3gateway/pom.xml
Change-Id: I132006b2b5a638e7f19d9ec1beb33b332d105e98
@github-actions

Copy link
Copy Markdown

This PR has been marked as stale due to 21 days of inactivity. Please comment or remove the stale label to keep it open. Otherwise, it will be automatically closed in 7 days.

@github-actions

Copy link
Copy Markdown

Thank you for your contribution. This PR is being closed due to inactivity. If needed, feel free to reopen it.

Change-Id: Ie1076419cae849563efc8a14ac97e5c0c83828a9
# Conflicts:
#	hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMDirectoryCreateRequest.java
#	hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileCreateRequest.java
#	hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java
#	hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java
#	hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java
@swamirishiswamirishi reopened this Dec 17, 2025
Change-Id: I461d46461905d041a613b101182d24e18a143d5c
Comment on lines +266 to +269
@OMLayoutVersionValidator(
processingPhase = RequestProcessingPhase.PRE_PROCESS,
requestType = Type.CreateDirectory
requestType = Type.CreateDirectory,
applyBefore = OMLayoutFeature.ERASURE_CODED_STORAGE_SUPPORT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please simply replace the two changed lines instead of moving things around.

- @RequestFeatureValidator(- conditions = ValidationCondition.CLUSTER_NEEDS_FINALIZATION,+ @OMLayoutVersionValidator(+ applyBefore = OMLayoutFeature.ERASURE_CODED_STORAGE_SUPPORT,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment threadhadoop-hdds/client/pom.xml Outdated
Comment on lines +140 to +141
<bannedImport>org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator</bannedImport>
<bannedImport>org.apache.hadoop.ozone.om.request.validation.OMLayoutVersionValidator</bannedImport>
<bannedImport>org.apache.hadoop.ozone.om.request.validation.OMClientVersionValidator</bannedImport>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #9530 to reduce the change that this PR needs to make in POM files. The other PR:

  1. adds the new annotations, since they were already introduced in HDDS-11981
  2. more importantly, removes RequestFeatureValidator from modules where it's not even accessible

So this PR will only need to update POMs for the removal of RequestFeatureValidator, and only in fewer modules.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merged with master branch

Change-Id: Ie6717a5c5e5e6821c2ec8d7abc7a5d4a20d6767f
# Conflicts:
#	hadoop-hdds/client/pom.xml
#	hadoop-hdds/common/pom.xml
#	hadoop-hdds/container-service/pom.xml
#	hadoop-hdds/framework/pom.xml
#	hadoop-hdds/server-scm/pom.xml
#	hadoop-ozone/cli-admin/pom.xml
#	hadoop-ozone/cli-shell/pom.xml
#	hadoop-ozone/common/pom.xml
#	hadoop-ozone/csi/pom.xml
#	hadoop-ozone/freon/pom.xml
#	hadoop-ozone/insight/pom.xml
#	hadoop-ozone/recon/pom.xml
#	hadoop-ozone/tools/pom.xml
#	pom.xml
Change-Id: Ia2f6792669628c67088b8b5a273fb271476e8848
@swamirishi

Copy link
Copy Markdown
ContributorAuthor

@adoroszlai I have addressed all your review comments. Can you take a look at the change now.

OMResponse validatedResponse = response;
List<Method> validations = registry.validationsFor(request.getCmdType(), POST_PROCESS, this.getVersions(request));

OMResponse validatedResponse = response.toBuilder().build();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is response being copied here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just wanted to ensure the validators don't change the original object passed so that the caller can get both the objects. I can remove it if you want me to. It is inconsequential

@adoroszlaiadoroszlaiJan 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please remove, it is unnecessary. OMResponse (as a protobuf message) is immutable, so validators cannot change it.

@adoroszlai

Copy link
Copy Markdown
Contributor

@errose28@fapifta please take a look

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request refactors the request validation framework in Ozone Manager to support version-based validations instead of condition-based validations. The changes replace the ValidationCondition enum and RequestFeatureValidator annotation with a more flexible version-based system using OMClientVersionValidator and OMLayoutVersionValidator annotations.

Changes:

  • Introduced version-based validator registration using @RegisterValidator meta-annotation
  • Replaced condition-based validation with version comparison logic in ValidatorRegistry
  • Updated all validator usages across S3, key, file, and bucket request handlers
  • Added support for both client version and layout version validators
  • Implemented IndexedItems data structure for efficient version-range lookups

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 12 comments.

Show a summary per file
FileDescription
ValidatorRegistry.javaCore refactoring to support version-based validator lookups with IndexedItems for efficient range queries
RequestValidations.javaUpdated to extract versions from requests and lookup validators based on version ranges
ValidationCondition.javaRemoved - replaced by version-based approach
RequestFeatureValidator.javaRemoved - replaced by OMClientVersionValidator and OMLayoutVersionValidator
VersionExtractor.javaNew enum to extract client and layout versions from OM requests
package-info.javaUpdated documentation to reflect new version-based validation approach
Versioned.javaAdded versionComparator() utility method
OzoneManagerRequestHandler.javaUpdated validators to use OMClientVersionValidator
S3 multipart request handlersUpdated validators to use new annotations with explicit version parameters
Key/file/bucket request handlersUpdated validators to use new annotations with explicit version parameters
Test filesUpdated tests to work with version-based validation logic

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* applyBeforeVersion: Enum extending Version
* RequestType: Enum signifying the type of request.
* RequestProcessingPhase: Signifying if the validator is supposed to run pre or post submitting the request.
* Based on the afforementioned parameters a complete map is built which stores the validators in a sorted order of

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in "afforementioned". It should be "aforementioned".

Suggested change
* Basedontheafforementionedparametersacompletemapisbuiltwhichstoresthevalidatorsinasortedorderof
* Basedontheaforementionedparametersacompletemapisbuiltwhichstoresthevalidatorsinasortedorderof

Copilot uses AI. Check for mistakes.
return new EnumMap<>(RequestProcessingPhase.class);
}
/**
* Class responsible for maintaining indexs of items. Here each item should have an index corresponding to it.

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the word "indexs". It should be "indexes" or "indices".

Suggested change
* Classresponsibleformaintainingindexsofitems. Hereeachitemshouldhaveanindexcorrespondingtoit.
* Classresponsibleformaintainingindexesofitems. Hereeachitemshouldhaveanindexcorrespondingtoit.

Copilot uses AI. Check for mistakes.
applyBefore = OMLayoutFeature.QUOTA,
processingPhase = PRE_PROCESS,
requestType = CreateVolume)
public static OMRequest multiPurposePreProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator(

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the method name "multiPurposePreProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator". The word "CLient" should be "Client" (lowercase 'l').

Copilot uses AI. Check for mistakes.
assertEquals(1, oldClientValidators.size());
String expectedMethodName = "multiPurposePostProcessCreateVolumeValidator";
assertEquals(1, combinedValidators.size());
String expectedMethodName = "multiPurposePostProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator";

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the expected method name "multiPurposePostProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator". The word "CLient" should be "Client" (lowercase 'l').

Copilot uses AI. Check for mistakes.
Comment on lines +284 to +285
* @param item
* @param idx

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Javadoc for parameters. The add method should document what the item and idx parameters represent.

Suggested change
* @paramitem
* @paramidx
* @paramitemtheitemtoaddtothiscollection
* @paramidxtheindexassociatedwiththeitem; indicesmustbeprovidedinincreasingorder

Copilot uses AI. Check for mistakes.
public static OMRequest multiPurposePreProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator(
OMRequest req, ValidationContext ctx) {
fireValidationEvent("multiPurposePreProcessCreateVolumeValidator");
fireValidationEvent("multiPurposePreProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator");

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the method name "multiPurposePreProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator". The word "CLient" should be "Client" (lowercase 'l').

Copilot uses AI. Check for mistakes.
requestType = CreateKey)
public static OMResponse oldClientPostProcessCreateKeyValidator2(
requestType = CreateVolume)
public static OMResponse multiPurposePostProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator(

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the method name "multiPurposePostProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator". The word "CLient" should be "Client" (lowercase 'l').

Copilot uses AI. Check for mistakes.
public static OMResponse multiPurposePostProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator(
OMRequest req, OMResponse resp, ValidationContext ctx) {
fireValidationEvent("oldClientPostProcessCreateKeyValidator2");
fireValidationEvent("multiPurposePostProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator");

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the method name "multiPurposePostProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator". The word "CLient" should be "Client" (lowercase 'l').

Copilot uses AI. Check for mistakes.
assertEquals(1, preFinalizeValidators.size());
assertEquals(1, newClientValidators.size());
String expectedMethodName = "multiPurposePreProcessCreateVolumeValidator";
String expectedMethodName = "multiPurposePreProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator";

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the expected method name "multiPurposePreProcessCreateVolumeBucketLayoutCLientQuotaLayoutValidator". The word "CLient" should be "Client" (lowercase 'l').

Copilot uses AI. Check for mistakes.
*
* The main reason to avoid validating multiple request types with the same
* validator, is that these validators have to be simple methods without state
* any complex validation has to happen in the reql request handling.

CopilotAIJan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in "reql". It should be "real".

Suggested change
* anycomplexvalidationhastohappeninthereqlrequesthandling.
* anycomplexvalidationhastohappenintherealrequesthandling.

Copilot uses AI. Check for mistakes.
@github-actions

Copy link
Copy Markdown

This PR has been marked as stale due to 21 days of inactivity. Please comment or remove the stale label to keep it open. Otherwise, it will be automatically closed in 7 days.

@github-actions

Copy link
Copy Markdown

This PR has been marked as stale due to 21 days of inactivity. Please comment or remove the stale label to keep it open. Otherwise, it will be automatically closed in 7 days.

@adoroszlai

Copy link
Copy Markdown
Contributor

@errose28@fapifta can we wrap this up?

@swamirishi
swamirishi marked this pull request as ready for review March 1, 2026 16:26
@github-actions

Copy link
Copy Markdown

This PR has been marked as stale due to 21 days of inactivity. Please comment or remove the stale label to keep it open. Otherwise, it will be automatically closed in 7 days.

@github-actions

Copy link
Copy Markdown

Thank you for your contribution. This PR is being closed due to inactivity. Please contact a maintainer if you would like to reopen it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@swamirishi@adoroszlai