BewareMyPower opened a new pull request, #23217:
URL: https://github.com/apache/pulsar/pull/23217

   ### Background Knowledge
   
   A concurrent hash map (no matter the `ConcurrentOpenHashMap` in Pulsar or 
the official `ConcurrentHashMap`) is not a synchronized hash map.
   
   For example, given a `ConcurrentHashMap<Integer, Integer>` object `m`,
   
   ```java
   synchronized (m) {
       m.computeIfAbsent(1, __ -> 100); // [1]
       m.computeIfAbsent(2, __ -> 200); // [2]
   }
   ```
   
   ```java
   m.computeIfAbsent(1, __ -> 300); // [3]
   ```
   
   If these two code blocks are called in two threads, `[1]->[3]->[2]` is a 
possible case.
   
   ### Motivation
   
   `SimpleLoadManagerImpl` and `ModularLoadManagerImpl` both maintain the 
bundle range cache:
   
   ```java
   // The 1st key is broker, the 2nd key is namespace
   private final ConcurrentOpenHashMap<String, ConcurrentOpenHashMap<String, 
ConcurrentOpenHashSet<String>>>
       brokerToNamespaceToBundleRange;
   ```
   
   However, when accessing the `namespace -> bundle` map, it still needs a 
synchronized code block:
   
   
https://github.com/apache/pulsar/blob/1c495e190b3c569e9dfd44acef2a697c93a1f771/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/impl/ModularLoadManagerImpl.java#L591-L595
   
   The code above is a composite operation of `clear()` and multiple 
`computeIfAbsent` operations on the `ConcurrentOpenHashMap<String, 
ConcurrentOpenHashSet<String>>` object.
   
   So the other place that access this map also requires the same lock even if 
the operation itself is thread safe:
   
   
https://github.com/apache/pulsar/blob/1c495e190b3c569e9dfd44acef2a697c93a1f771/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/impl/ModularLoadManagerImpl.java#L882-L886
   
   P.S. `SimpleLoadManagerImpl` does not apply the synchronized block.
   
   However, when accessing `brokerToNamespaceToBundleRange` in the static 
methods of `LoadManagerShared`, they are not synchronized. So the access on the 
`Map<String, Set<String>>` value is not thread safe.
   
   ### Modifications
   
   Add a `BundleRangeCache` abstraction to provide some methods to support 
required operations on the bundle range cache.
   
   ### Documentation
   
   <!-- DO NOT REMOVE THIS SECTION. CHECK THE PROPER BOX ONLY. -->
   
   - [ ] `doc` <!-- Your PR contains doc changes. -->
   - [ ] `doc-required` <!-- Your PR changes impact docs and you will update 
later -->
   - [x] `doc-not-needed` <!-- Your PR changes do not impact docs -->
   - [ ] `doc-complete` <!-- Docs have been already added -->
   
   ### Matching PR in forked repository
   
   PR in forked repository:


-- 
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]

Reply via email to