imbajin commented on code in PR #3418:
URL: https://github.com/apache/hugegraph/pull/3418#discussion_r4397192853


##########
hugegraph-pd/hg-pd-core/src/main/java/org/apache/hugegraph/pd/TaskScheduleService.java:
##########
@@ -449,22 +450,61 @@ public synchronized Map<Integer, KVPair<Long, Long>> 
balancePartitionShard() thr
             maxHeap.addAll(tmpList);
         }
 
-        kvService.put(BALANCE_SHARD_KEY, "DOING", 180 * 1000);
-
-        // Start the migration
-        movedPartitions.forEach((partId, storePair) -> {
-            // Neither the source nor destination storeID is 0
-            if (storePair.getKey() > 0 && storePair.getValue() > 0) {
-                partitionService.movePartitionsShard(partId, 
storePair.getKey(),
-                                                     storePair.getValue());
-            } else {
+        boolean submitted = false;
+        Iterator<Map.Entry<Integer, KVPair<Long, Long>>> submission =
+                movedPartitions.entrySet().iterator();
+        while (submission.hasNext()) {
+            Map.Entry<Integer, KVPair<Long, Long>> move = submission.next();
+            KVPair<Long, Long> stores = move.getValue();
+            if (stores.getKey() <= 0 || stores.getValue() <= 0) {
                 log.warn("balancePartitionShard key or value is zero, 
partId:{} storePair:{}",
-                         partId, storePair);
+                         move.getKey(), stores);
+                submission.remove();
+                continue;
             }
-        });
+            if (!movePartitionIfPlacementStore(move.getKey(), stores.getKey(),
+                                               stores.getValue())) {
+                submission.remove();
+                continue;
+            }
+            submitted = true;
+        }
+        if (submitted) {
+            kvService.put(BALANCE_SHARD_KEY, "DOING", 180 * 1000);
+        }
         return movedPartitions;
     }
 
+    /**
+     * Revalidate destination liveness and state while serializing with Store 
state changes.
+     * Preserve the existing service lock order: PartitionService then 
StoreNodeService.
+     */
+    private boolean movePartitionIfPlacementStore(int partitionId, long 
sourceStoreId,
+                                                  long destStoreId) {
+        synchronized (partitionService) {
+            synchronized (storeService) {

Review Comment:
   **[P1] Remove the remaining placement-versus-split lock inversion**
   
   Moving the Tombstone callback outside the Store monitor fixes that reported 
path, but the two monitors here still oppose the manual split path:
   
   * This helper holds `partitionService` at line 484 and then acquires 
`storeService` at line 485.
   * 
[`TaskScheduleService.splitPartition()`](https://github.com/apache/hugegraph/blob/50515cb821c0ce1afd5ec3fc373104431cb7a881/hugegraph-pd/hg-pd-core/src/main/java/org/apache/hugegraph/pd/TaskScheduleService.java#L649-L660)
 is not synchronized and calls 
[`StoreNodeService.splitShardGroups()`](https://github.com/apache/hugegraph/blob/50515cb821c0ce1afd5ec3fc373104431cb7a881/hugegraph-pd/hg-pd-core/src/main/java/org/apache/hugegraph/pd/StoreNodeService.java#L617-L626),
 which holds the Store monitor while calling 
[`PartitionService.splitPartition()`](https://github.com/apache/hugegraph/blob/50515cb821c0ce1afd5ec3fc373104431cb7a881/hugegraph-pd/hg-pd-core/src/main/java/org/apache/hugegraph/pd/PartitionService.java#L630-L645),
 synchronized on the Partition monitor.
   
   Consequently, concurrent placement and a split that passes its capacity 
check can each own one monitor and wait indefinitely for the other. The 
scheduler's synchronized balancing entry point does not exclude the 
unsynchronized split entry point. This can block both services, including Store 
heartbeat/state operations, rather than just one migration.
   
   Please establish a consistent lock order across these paths while retaining 
the final destination-state check. The new Tombstone-listener regression does 
not exercise this remaining split interleaving; add a controlled 
split-versus-placement regression that demonstrates both operations complete 
without opposite monitor acquisition.
   
   This is distinct from the now-fixed Tombstone callback cycle in [the earlier 
comment](https://github.com/apache/hugegraph/pull/3418#discussion_r4395010891). 
Validation here is static source tracing at 
`50515cb821c0ce1afd5ec3fc373104431cb7a881`, not an independently executed 
deadlock test or a data-loss claim.



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