[ 
https://issues.apache.org/jira/browse/HDDS-16948?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andrey Yarovoy reassigned HDDS-16948:
-------------------------------------

    Assignee: Andrey Yarovoy

> Remove the per-call InfoBucket from rooted-ofs open
> ---------------------------------------------------
>
>                 Key: HDDS-16948
>                 URL: https://issues.apache.org/jira/browse/HDDS-16948
>             Project: Apache Ozone
>          Issue Type: Improvement
>          Components: Ozone Client
>            Reporter: Andrey Yarovoy
>            Assignee: Andrey Yarovoy
>            Priority: Major
>
> `BasicRootedOzoneClientAdapterImpl.readFile` (behind `FileSystem.open`) calls 
> `getBucket()`, which is an
> `InfoBucket` RPC. For a link bucket it adds an `InfoVolume` and an 
> `InfoBucket` per hop. It then calls
> `OzoneBucket.readFile`. Every `open` therefore costs at least 2 OM requests. 
> On read-heavy file system
> workloads (Hive, Impala, Spark scans) `open` is one of the most frequent 
> metadata operations, so this is
> the largest single `InfoBucket` source left after HDDS-15925 and HDDS-16760.
> The fetch does one job: `OzoneFSUtils.validateBucketLayout`, which rejects 
> OBJECT_STORE. `readFile`
> reads nothing else from the bucket.
> ### Why HDDS-15951's lookupFile check does not cover this
> `RpcClient.readFile` uses `lookupFile` only for an OM older than 
> `OPTIMIZED_GET_KEY_INFO` (3). For every
> current OM it sends **`GetKeyInfo`**, then checks `isFile()` on the client. 
> Its read-retry path
> (`RpcClient.getKeyInfo`) also sends `GetKeyInfo`. So the OBJECT_STORE 
> rejection that HDDS-15951 added to
> `lookupFile` is never reached from `open`.
> ### Why the rejection is opt-in
> `GetKeyInfo` is the object store read RPC. It sits behind 
> `OzoneBucket.readKey`, `getKeyDetails`,
> `headObject` and the S3 key lookups (`assumeS3Context=true`), which the S3 
> Gateway uses for GetObject and
> HeadObject. `cli-shell`, `freon` and `cli-debug` call it as well. An 
> unconditional OBJECT_STORE rejection
> would break all of them. As in HDDS-16760, the client asks for the check:
> {code}
> message GetKeyInfoRequest {
> required KeyArgs keyArgs = 1;
> optional bool assumeS3Context = 2;
> // Set by file system clients: OM rejects the request with
> // NOT_SUPPORTED_OPERATION if the resolved bucket layout is OBJECT_STORE.
> optional bool requireFileSystemLayout = 3;
> }
> {code}
> ### Proposed change
> *OM.*
> * `OzoneManagerRequestHandler.getKeyInfo` copies the field into `OmKeyArgs`. 
> The `requireFileSystemLayout`
> field added there by HDDS-16760 is reused, and the builder already survives 
> `ResolvedBucket.update`.
> * `OmMetadataReader.getKeyInfo` already holds the link-resolved 
> `ResolvedBucket`. When the field is set,
> it calls the existing `validateFileSystemLayout(bucket)` before the ACL 
> check. This is the same
> placement as `listStatus` in HDDS-16760, so it adds no lookup.
> *Client.*
> * `RpcClient.readFile` sets the field on the `OmKeyArgs` it builds for 
> `GetKeyInfo`. The read-retry
> `getKeyInfo` call also sets it, so a retried read is checked too.
> * `OzoneManagerProtocolClientSideTranslatorPB.getKeyInfo` builds `KeyArgs` 
> through
> `OmKeyArgs.toProtobuf()` but sets the request-level field explicitly. Do not 
> set it unconditionally:
> `readKey` / `getKeyDetails` share this translator method.
> * The adapter needs a way to ask for it, mirroring HDDS-16760's 
> `ListStatusLightOptions`. Options are a
> `readFile` overload or an options object on `ClientProtocol`, or 
> `OzoneBucket.readFile` setting it
> itself. `OzoneBucket.readFile` is a file-oriented API, so it could always set 
> it; decide on review.
> * The adapter skips `getBucket()` when `proxy.getOmVersion() >=` a new 
> `OzoneManagerVersion` constant.
> Place it after `LIST_STATUS_REJECTS_OBS(101)` and never below `ZDU(100)`; the 
> number is assigned at
> merge. It maps `NOT_SUPPORTED_OPERATION` to `IllegalArgumentException`. 
> Against any older OM, including
> one that reports ZDU, it keeps the current path.
> * The `lookupFile` branch for OMs older than version 3 is unchanged, and such 
> OMs take the fallback anyway.
> ### Rejected alternative
> `GetKeyInfoResponse` already returns `bucketLayout` (HDDS-16362), so the 
> client could check that instead
> and need no new request field. Two problems:
> * It only works when the key exists. A missing key on an OBJECT_STORE bucket 
> would then report
> `FileNotFoundException` instead of today's `IllegalArgumentException`.
> * The field was added without a version gate, so an older OM leaves it unset, 
> and the client cannot
> tell "not OBJECT_STORE" from "not reported".
> ### Compatibility
> | | Behavior |
> |---|---|
> | New client, new OM | 1 RPC (`GetKeyInfo`); OM rejects OBJECT_STORE |
> | New client, older OM (incl. ZDU) | `getBucket()` + `GetKeyInfo`, as today |
> | Old client / S3 Gateway / `readKey` / `getKeyDetails`, new OM | field 
> absent ⇒ unchanged |
> There is one new optional proto field, no new result code and no new 
> configuration.
> ## Testing
> * Adapter (Mockito):
> *`open` makes exactly one OM call, carrying the field.
> *`NOT_SUPPORTED_OPERATION` maps to `IllegalArgumentException`; 
> `KEY_NOT_FOUND` / `FILE_NOT_FOUND` /
> `NOT_A_FILE` map to `FileNotFoundException`, as today.
> * An older OM, including `ZDU`, falls back to `getBucket()`.
> * `TestOMMetadataReader`:
> * With the field set, `getKeyInfo` rejects OBJECT_STORE without reaching 
> `KeyManager` and serves FSO
> and **LEGACY**.
> * Without the field, it still serves OBJECT_STORE: the S3 Gateway case, and 
> the guard against anyone
> making the check unconditional.
> * The same holds with `assumeS3Context=true`.
> * `TestOzoneManagerRequestHandler`: the field is forwarded into `OmKeyArgs`.
> * Existing S3 and object-store read suites pass unchanged.
> * `AbstractRootedOzoneFileSystemTest`: `open` on an OBJECT_STORE bucket fails 
> with
> `IllegalArgumentException`. Do RPC counting in the adapter test, not with 
> exact OMMetrics deltas
> (HDDS-16513).
> * Benchmark `TestOfsOpenRpcBenchmark`, same shape as 
> `TestOfsListStatusRpcBenchmark`:
> * 200 FSO buckets, open + close of a small file, single thread and 10 threads.
> * n=3 per arm, built and run strictly one after the other.
> * Invariant: exactly 1 OM RPC per `open` instead of 2. `open` alone, with no 
> data read, so DN reads do
> not mask the OM saving.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to