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

Andrey Yarovoy reassigned HDDS-17714:
-------------------------------------

    Assignee: Andrey Yarovoy

> OFS getFileStatus should not refresh pipelines or return block locations
> ------------------------------------------------------------------------
>
>                 Key: HDDS-17714
>                 URL: https://issues.apache.org/jira/browse/HDDS-17714
>             Project: Apache Ozone
>          Issue Type: Improvement
>          Components: Ozone Filesystem
>            Reporter: Andrey Yarovoy
>            Assignee: Andrey Yarovoy
>            Priority: Major
>
> *Description*
> `BasicRootedOzoneFileSystem.getFileStatus` sends `GetFileStatus` with 
> `headOp=false`. For a file, OM then:
> - calls `refresh(fileKeyInfo)`, which looks up every block's container 
> pipeline (`KeyManagerImpl.getOzoneFileStatusFSO`);
> - optionally sorts the datanodes;
> - returns the full `KeyLocationList`.
> The client parses it (`OmKeyInfo.getFromProtobuf` → 
> `OmKeyLocationInfo.getFromProtobuf` streams), builds a `BlockLocation[]`, and 
> returns a
> `LocatedFileStatus`.
> HDFS `getFileStatus` returns no block locations; callers that need them call 
> `getFileBlockLocations` or `listLocatedStatus`. Most
> `getFileStatus` callers use only length, type, mtime and owner. HBase is the 
> extreme case. Every `StoreScanner.trySwitchToStreamRead`
> reopens each store file, and `StoreFileInfo.createReaderContext` calls 
> `fs.getFileStatus(path)` only for `getLen()`.
> *Follow-up to HDDS-15678 / HDDS-15877*
> - **HDDS-15678** built the server side. With `headOp=true`, OM skips 
> `refresh`/`sortDatanodes`, and
> `OzoneManagerRequestHandler.getOzoneFileStatus` clears `KeyLocationList` from 
> the response. On the client it switched ofs
> `isFile`/`isDirectory` to head ops.
> - **HDDS-15877** did the same for o3fs and the remaining *type-only* callers 
> (trash roots, shell `DeleteKeyHandler`).
> - Both deliberately left the public `FileSystem.getFileStatus(Path)` on 
> `headOp=false`, because its result is a `LocatedFileStatus` that
> `getFileBlockLocations(FileStatus)` reads. That is the call HBase makes on 
> every store-file reopen, and still the call that pays the refresh and
> returns all block locations.
> This Jira finishes the job for `getFileStatus(Path)`. It returns a plain 
> `FileStatus` (like HDFS), and `getFileBlockLocations` fetches the
> locations only when they are actually requested.
> *Evidence (HBase YCSB on EC, RegionServer async-profiler, 6×60s per arm)*
> - `getFileStatus` is 12.5–14.6% of busy RS handler time, all spent waiting on 
> OM.
> - Client-side status conversion is 1.2–1.6% of RS CPU (`toFileStatusAdapter`, 
> `getBlockLocations`, `OmKeyInfo.getFromProtobuf` for the status).
> Parsing the `GetFileStatusResponse` `KeyLocationList` is ~3% of the reopen 
> subtree.
> - OM-side cost (`refresh` + response encode) is not visible from RS profiles. 
> **Measure on OM before and after.**
> *Proposed fix*
> 1. `BasicRootedOzoneFileSystem.getFileStatus(Path)` (and 
> `BasicOzoneFileSystem`) call the adapter with `headOp=true`. They return a 
> plain
> `FileStatus` (no `BlockLocation[]`). Length, mtime, owner, replication, EC 
> policy and encryption flags come from the same `KeyInfo` fields as
> today.
> 2. `getFileBlockLocations(FileStatus, start, len)`: when the status is not a 
> `LocatedFileStatus` and is a file, fetch a full status (`headOp=false`)
> and compute the range from it, instead of `super.getFileBlockLocations` 
> (which returns a fake `localhost` location).
> 3. Override `getFileBlockLocations(Path, start, len)` to fetch the full 
> status directly, so a path-based call stays at **1** RPC.
> 4. `listStatus` / `listLocatedStatus` / `listFiles` are unchanged; they keep 
> their own location handling.
> 5. Optional escape hatch: `ozone.fs.getfilestatus.include.block.locations` 
> (default `false`) restores today's `LocatedFileStatus` from
> `getFileStatus`.
> {code:java}
> // BasicRootedOzoneFileSystem
> public FileStatus getFileStatus(Path f) throws IOException {
> return TracingUtil.executeInNewSpan("ofs getFileStatus",
> () -> convertFileStatus(getFileStatusAdapter(f, !includeBlockLocations)));
> }
> {code}
> *Old OM compatibility*
> An OM without HDDS-15678's response stripping still returns locations on a 
> head op, but they are unrefreshed (no pipeline). The client must
> ignore `KeyLocationList` whenever it sent `headOp=true`, whatever the OM 
> version. With that rule no version gate is needed. Old OMs still
> skip `refresh` on head ops (that check predates HDDS-15678).
> *Compatibility / side effects*
> - **Behavior change:** `getFileStatus` no longer returns a 
> `LocatedFileStatus`.
> - A caller that casts the result to `LocatedFileStatus` breaks; in-tree, 
> check `ozonefs` tests and the `BasicOzoneFileSystem` copy.
> - A caller that does `getFileStatus` then `getFileBlockLocations(status)` now 
> pays 2 OM RPCs instead of 1. MapReduce/Spark/Hive split
> planning uses `listLocatedStatus`, so it is unaffected; one-off single-file 
> planners pay +1 RPC.
> - No proto change. No new OM version.
> *Tests*
> - Unit (adapter, Mockito): `getFileStatus` sends `headOp=true`. The result 
> has the correct length/mtime/owner/EC fields and is not a
> `LocatedFileStatus`. `getFileBlockLocations(status)` sends exactly one 
> `GetFileStatus` with `headOp=false` and returns real locations.
> `getFileBlockLocations(path)` sends exactly one RPC.
> - Integration: `TestRootedOzoneFileSystem` / `TestOzoneFileSystem` locality 
> tests still return real datanode hosts. EC and Ratis keys,
> encrypted keys.
> - Benchmark: `getFileStatus` latency/throughput A/B on a multi-block EC key 
> (n=3 per arm, sequential), with OM CPU per call.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

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

Reply via email to