[
https://issues.apache.org/jira/browse/HDDS-16950?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Andrey Yarovoy reassigned HDDS-16950:
-------------------------------------
Assignee: Andrey Yarovoy
> Remove the per-call InfoBucket from rooted-ofs mkdirs
> -----------------------------------------------------
>
> Key: HDDS-16950
> URL: https://issues.apache.org/jira/browse/HDDS-16950
> Project: Apache Ozone
> Issue Type: Improvement
> Components: Ozone Client
> Reporter: Andrey Yarovoy
> Assignee: Andrey Yarovoy
> Priority: Major
>
> `BasicRootedOzoneClientAdapterImpl.createDirectory` (behind
> `FileSystem.mkdirs`) calls
> `getBucket(ofsPath, createIfNotExist=true)` and then
> `OzoneBucket.createDirectory`. So every `mkdirs` below bucket level sends at
> least 2 OM requests: `InfoBucket` + `CreateDirectory`, plus `InfoVolume` +
> `InfoBucket` per link hop.
> The fetch does two jobs:
> 1. **Layout check.** `OzoneFSUtils.validateBucketLayout` rejects OBJECT_STORE.
> 2. **Auto-create.** When the volume or bucket is missing, `getBucket` creates
> it (`InfoVolume` /
> `CreateVolume` / `CreateBucket`), so `mkdirs /vol/bucket/dir` works on an
> empty namespace. When the path
> is only `/vol/bucket`, this is the whole operation.
> Both must be handled before the fetch can be dropped, the same way HDDS-16760
> handled listStatus's two
> jobs.
> ### Why the rejection is opt-in
> `OMDirectoryCreateRequest` is registered for `BucketLayout.OBJECT_STORE`
> (that registration also serves
> LEGACY), so `CreateDirectory` succeeds on an OBJECT_STORE bucket today. Its
> callers:
> * The S3 Gateway's `ObjectEndpoint` creates directories for a zero-byte key
> ending in `/`, but only when
> `bucket.getBucketLayout() == FILE_SYSTEM_OPTIMIZED`.
> * `KeyLifecycleService`, on non-OBJECT_STORE buckets.
> * `cli-shell`'s `DeleteKeyHandler`, on FSO buckets.
> * Direct Java API callers of `OzoneBucket.createDirectory`, which may target
> OBJECT_STORE.
> the client asks for the check:
> {code}
> message CreateDirectoryRequest {
> required KeyArgs keyArgs = 1;
> // Set by file system clients: OM rejects the request with
> // NOT_SUPPORTED_OPERATION if the resolved bucket layout is OBJECT_STORE.
> optional bool requireFileSystemLayout = 2;
> }
> {code}
> ### Proposed change
> *OM.* Check on the leader before Ratis, in
> `OMDirectoryCreateRequest.preExecute` /
> `OMDirectoryCreateRequestWithFSO.preExecute`
> or right after `createClientRequest` in
> `OMExecutionFlow.submitExecutionToRatis`. Use the link-resolved layout that
> `BucketLayoutAwareOMKeyRequestFactory.createRequest` already read, so there
> is no new lookup. Use the
> `validateBucketLayout` message, wrapped in
> `OMException(NOT_SUPPORTED_OPERATION)`. Do not put the check
> in `createRequest` itself, because that also runs at apply time on every OM.
> See the setTimes Jira for
> the reasoning.
> *Client.*
> * For a path below bucket level, when `proxy.getOmVersion() >=` a new
> `OzoneManagerVersion` constant
> (placed after `LIST_STATUS_REJECTS_OBS(101)`, never below `ZDU(100)`), the
> adapter sends `CreateDirectory`
> with the field set, using a locally built handle or a `ClientProtocol` call.
> No `getBucket()` first.
> * **Auto-create on the error path:** on `VOLUME_NOT_FOUND` /
> `BUCKET_NOT_FOUND`, call today's
> `getBucket(ofsPath, true)`. It creates what is missing and applies the
> client-side layout check. Then
> retry `CreateDirectory` once. Only an `mkdirs` that creates a bucket pays the
> extra round trip, and it
> already pays several.
> * A link whose source is missing must keep its current behaviour.
> `getBucket(…, true)` on an orphan link
> must not create a bucket under the link's name. The error path calls
> `getBucket()` as a whole, so it
> behaves exactly as today. The HDDS-16760 orphan-link handling has the same
> property.
> * `NOT_SUPPORTED_OPERATION` maps to `IllegalArgumentException`.
> `FILE_ALREADY_EXISTS` keeps mapping to
> `FileAlreadyExistsException`.
> * `mkdirs /vol/bucket` (no key) keeps calling `getBucket(…, true)`, because
> that call is the operation.
> * Against any older OM, including one that reports ZDU, keep the current path.
> ### Compatibility
> | | Behavior |
> |---|---|
> | New client, new OM, bucket exists | 1 RPC; OM rejects OBJECT_STORE |
> | New client, new OM, bucket missing | failed `CreateDirectory` →
> `getBucket(…, true)` (creates) → `CreateDirectory` |
> | New client, older OM (incl. ZDU) | as today |
> | Old client / S3 Gateway / lifecycle / direct `createDirectory`, new OM |
> field absent ⇒ unchanged |
> There is one new optional proto field, no new result code and no new
> configuration.
> Points for review:
> * The BUCKET/READ ACL check from `getBucketDetails` is dropped.
> `CreateDirectory` keeps its own ACL
> checks (bucket WRITE / key CREATE).
> * The audit log shows a failed `CREATE_DIRECTORY` before the `CREATE_BUCKET`
> in the auto-create case.
> ## Testing
> * Adapter (Mockito):
> * Existing bucket: exactly one `CreateDirectory`, carrying the field, and no
> `getBucket()`.
> * Missing bucket: `CreateDirectory` fails, then `getBucket(…, true)`, then
> one retry.
> * Orphan link: today's result.
> *`NOT_SUPPORTED_OPERATION` maps to `IllegalArgumentException`, and
> `FILE_ALREADY_EXISTS` to
> `FileAlreadyExistsException`.
> * An older OM, including one reporting `ZDU`, falls back.
> * OM request tests (both the FSO and non-FSO classes):
> * With the field set, OBJECT_STORE is rejected before Ratis, and FSO and
> **LEGACY** succeed.
> * Without the field, OBJECT_STORE succeeds.
> * A link to an OBJECT_STORE bucket is rejected.
> * `AbstractRootedOzoneFileSystemTest`: `mkdirs` into a missing volume/bucket
> still auto-creates both, and
> `mkdirs` on an OBJECT_STORE bucket still fails with
> `IllegalArgumentException`. Count RPCs in the
> adapter test, not with OMMetrics deltas (HDDS-16513).
> * Benchmark `TestOfsMkdirsRpcBenchmark`, same shape as
> `TestOfsListStatusRpcBenchmark`:
> * 200 FSO buckets, unique directory names, single-threaded and 10 threads.
> * n=3 per arm, built and run strictly one after the other.
> * Invariant: exactly 1 OM RPC per `mkdirs` into an existing bucket, instead
> of 2.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]