yandrey321 opened a new pull request, #11942:
URL: https://github.com/apache/ozone/pull/11942

   ## What changes were proposed in this pull request?
   
   **Problem.** Guava recommends Caffeine over its own 
`com.google.common.cache`. Ozone used the Guava cache in 14
   classes and 5 tests, across `hdds-common`, `hdds-server-framework`, 
`hdds-client`, `container-service`,
   `ozone-client`, `cli-debug` and `ozone-manager`.
   
   **Change.**
   - **Caffeine everywhere:** every Guava cache is now a Caffeine cache.
     - `XceiverClientManager`, `RpcClient` (KMS key providers), `ScmClient` 
(container locations and datanodes),
       `FilePerBlockStrategy` (open files), `DefaultSecretKeyVerifierClient`, 
`PrometheusMetricsSinkUtil`,
       `DefaultContainerChoosingPolicy`, `S3InMemoryCache`, 
`ContainerStateVerifier`, `StateMachine` and `CacheMetrics`.
     - `SnapshotCache` / `OmSnapshotManager` take a Caffeine `CacheLoader`.
   - **`ResourceCache` is a weighted FIFO without a cache library.** This is 
the Ratis leader's cache of state machine
     data in `ContainerStateMachine`. See Key decisions.
   - **Caffeine is a managed, direct dependency:** `caffeine.version` 2.9.3 in 
the root pom, declared in each module that
     uses it.
   - **No new Guava cache:** the enforcer's `ban-imports` bans 
`com.google.common.cache.**`, in main and test code.
   
   **Key decisions.**
   - **Caffeine 2.9.3, not 3.x.**
     - `hdds-common`, `hdds-client`, `ozone-client` and `hdds-server-framework` 
compile for Java 8, and Caffeine 3
       needs Java 11. One version must serve both those modules and the 
servers, since they share the classpath.
     - 2.9.3 is also the version the distribution already ships, through 
iceberg-core. Its `checker-qual` (annotations
       only) is excluded, so the shipped jars don't change.
   - **Removal listeners run on the calling thread,** as Guava's did: 
`executor(Runnable::run)`. Caffeine's default runs
     maintenance and listeners on `ForkJoinPool.commonPool()`. Three caches 
depend on the old behaviour:
     - `XceiverClientManager.close()` collects the unreferenced clients in its 
listener, to close them in parallel
       (HDDS-15255);
     - `RpcClient.close()` and `FilePerBlockStrategy.close(File)` must have 
closed the key providers and files when they
       return.
   - **`ResourceCache` keeps FIFO eviction instead of moving to Caffeine.**
     - Its Javadoc and its caller ask for FIFO: the newest log entries are the 
ones that followers read next.
     - Caffeine's TinyLFU admission policy works against that. A new entry, 
read only a few times, loses to older ones.
     - Simulated (16 entries; every entry written once and read right away):
   
       | cache | newest entry missing after its put | read of the entry 8 
behind misses |
       |---|---|---|
       | Guava (before) | 0% | 27% (its 4 segments evict per segment) |
       | Caffeine | 0.6–1.2% | 68–82% |
       | this PR's FIFO | 0% | 0% |
   
     - So `ResourceCache` is now a small synchronized `LinkedHashMap` in 
insertion order, with weights. It evicts the
       eldest entries until within the limit, and reports `REPLACED`, 
`EXPLICIT` and `SIZE` causes to the listener,
       called outside the lock.
   - **Exceptions:** Caffeine wraps a checked loader exception in 
`CompletionException`, not `ExecutionException`.
     - `DefaultSecretKeyVerifierClient` and `ScmClient` unwrap it as before.
     - `XceiverClientManager` and `RpcClient` wrap their loader's `IOException` 
in `UncheckedIOException`, which their
       existing `catch (Exception)` handles as before.
   - **`ScmClient.getContainerLocations`:** Caffeine's `getAll` leaves out 
containers that SCM did not return. Guava
     threw `InvalidCacheLoadException`, which the code caught to return the 
cached ones. The result is the same, without
     the exception.
   
   **Side effects.**
   - **Unchecked loader exceptions propagate unwrapped,** where Guava wrapped 
them in `UncheckedExecutionException`:
     - `FilePerBlockStrategy.getChannel` throws the `UncheckedIOException` of a 
failed open;
     - `ScmClient` throws a `RuntimeException` from SCM as is.
   
     Nothing caught Guava's wrapper there (`TestScmClient` asserted on it, and 
is updated).
   - **`CacheMetrics`:** `LoadExceptionCount` now reports Caffeine's 
`loadFailureCount`, and `Size` reports
     `estimatedSize()`.
   - **Eviction policy:** the other size-bounded caches now use TinyLFU instead 
of Guava's segmented LRU. They are keyed
     by pipeline, container, datanode, secret key or metric name, and looked up 
repeatedly, which TinyLFU handles well.
   - **Public signatures:**
     - `XceiverClientManager#getClientCache()` and 
`RpcClient#getKeyProviderCache()`, both `@VisibleForTesting`, return
       Caffeine's `Cache`;
     - `ResourceCache`'s constructor takes Caffeine's `Weigher` and 
`RemovalListener`.
   - **Distribution:** no change in the shipped jars. A `-Pdist` build matches 
`jar-report.txt` exactly, with the same
     `caffeine-2.9.3.jar` as before and no `checker-qual`.
   
   Co-authored-by: Claude Opus 5.5 <[email protected]>
   
   ## What is the link to the Apache JIRA
   
   https://issues.apache.org/jira/browse/HDDS-15309
   
   ## How was this patch tested?
   
   Unit + integration tests.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to