yujun777 commented on code in PR #68193:
URL: https://github.com/apache/doris/pull/68193#discussion_r4057122054


##########
fe/fe-core/src/main/java/org/apache/doris/catalog/MTMV.java:
##########
@@ -598,6 +621,33 @@ public void alterIvmInfo(IvmInfo ivmInfo) {
         }
     }
 
+    /**
+     * Read under the MV lock, like {@link #getIvmInfo()}: the map may be null 
before
+     * {@link #gsonPostProcess()} has run, and a reader must never see a 
half-applied replay payload.
+     */
+    public Map<String, MTMVPartitionState> getPartitionStates() {
+        writeMvLock();
+        try {
+            if (partitionStates == null) {
+                partitionStates = Maps.newLinkedHashMap();
+            }
+            return partitionStates;

Review Comment:
   Addressed in 14e53728905.
   
   `getPartitionStates()` now takes the MV read lock and returns 
`Collections.unmodifiableMap(MTMVPartitionState.copyOf(...))`: the caller gets 
its own map and its own state objects, so an entry cannot be added or changed 
while `addTaskResult` is copying that same map into the journal, and a replay 
that replaces the field cannot leave a caller holding state the MV no longer 
owns. `MTMVTest.testPartitionStatesGetterReturnsAnUnmodifiableSnapshot` pins 
both halves -- the returned map rejects writes, and changing a returned value 
does not reach the MV. The tests that used to seed through the getter now use 
the replay setter, which takes the write lock and copies.
   
   Dropping the getter's lazy initialization turned out to matter beyond 
ownership. `addTaskResult` carries the field, so a getter call used to turn "no 
state yet" into an `emptyMap` in the payload, and a present-but-empty member is 
not the same as an absent one: its replay empties the states, which could wipe 
a mark that landed between the payload and the replay. With the field left 
alone, a payload taken while the states are empty carries no member and the 
replay leaves them as they are.
   
   The mutation methods are deliberately not in this PR: nothing populates the 
state yet, so they would be an unused live write path, and the mark 
(`latestEpoch++` plus the snapshot entry it drops) and the refresh write-back 
belong to the PR that starts using the state. They will mutate and enqueue 
their `ALTER_PARTITION_STATES` record under the same write lock the replay side 
takes.



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