zclllyybb commented on code in PR #65476:
URL: https://github.com/apache/doris/pull/65476#discussion_r3632155142


##########
regression-test/suites/dictionary_p0/test_create_drop_sync.groovy:
##########
@@ -105,4 +132,40 @@ suite('test_create_drop_sync') {
         LAYOUT(HASH_MAP)
         properties('data_lifetime'='600');
     """
-}
\ No newline at end of file
+
+    waitAllDictionariesReady()
+    long originalVersion = (sql "SHOW DICTIONARIES")[0][3].toLong()
+    def commitFailureFuture
+    try {
+        
GetDebugPoint().enableDebugPointForAllFEs('DictionaryManager.dataLoad.blockBeforeCommit')

Review Comment:
   Fixed. Both dictionary debug points are now disabled in the same outer 
finally that covers setup, waiting, DROP, and future completion, so an early 
assertion or timeout cannot leak forceFailure.



##########
fe/fe-core/src/main/java/org/apache/doris/dictionary/DictionaryManager.java:
##########
@@ -282,6 +285,19 @@ private boolean hasDictionaryWithoutLock(String dbName, 
String dictName) {
         return dbDictIds != null && dbDictIds.containsKey(dictName);
     }
 
+    public boolean isCurrentDictionary(Dictionary dictionary) {
+        lockRead();

Review Comment:
   Fixed. The unnecessary dictionary-manager read lock was removed; 
isCurrentDictionary now relies on the ConcurrentMap lookup and object identity 
only.



##########
fe/fe-core/src/main/java/org/apache/doris/dictionary/DictionaryManager.java:
##########
@@ -556,45 +643,109 @@ private boolean commitNowVersion(ConnectContext ctx, 
Dictionary dictionary) {
                     if (status.getErrorCode() != TStatusCode.OK) {
                         LOG.warn("Failed to commit dictionary " + 
dictionary.getId() + " on be " + be.getAddress()
                                 + " because " + status.getErrorMsg());
-                        allSucceed = false;
+                        allSucceeded = false;
+                    } else {
+                        anySucceeded = true;
                     }
                 } else {
                     LOG.warn("Failed to commit dictionary " + 
dictionary.getId() + " on be " + be.getAddress());
-                    allSucceed = false;
+                    allSucceeded = false;
+                    outcomeUnknown = true;
                 }
+            } catch (Exception e) {
+                dictionary.setLastUpdateResult("commit failed: " + 
e.getMessage());
+                LOG.warn("Failed to commit dictionary {} on BE {}", 
dictionary.getId(), be.getId(), e);
+                allSucceeded = false;
+                outcomeUnknown = true;
             }
-        } catch (Exception e) {
-            dictionary.setLastUpdateResult("commit failed: " + e.getMessage());
-            LOG.warn("Failed to commit dictionary " + dictionary.getId(), e);
-            allSucceed = false;
         }
-        return allSucceed;
+        return new CommitResult(allSucceeded, anySucceeded, outcomeUnknown);
     }
 
-    // abort could to all BE. swallow any failures.
-    private void abortSpecificVersion(ConnectContext ctx, Dictionary 
dictionary, long versionId) {
+    private void abortFailedLoad(ConnectContext ctx, Dictionary dictionary, 
DictionaryStatus oldStatus) {
+        if (ctx.getStatementContext() == null) {
+            dictionary.trySetStatus(oldStatus);
+            return;
+        }
+        boolean partialLoad = 
ctx.getStatementContext().isPartialLoadDictionary();
+        long stagedVersion = partialLoad
+                ? dictionary.getVersion() : dictionary.getVersion() + 1;
+        boolean versionFenced = false;
+        if (!partialLoad && 
ctx.getStatementContext().getUsedBackendsDistributing() != null
+                && 
!ctx.getStatementContext().getUsedBackendsDistributing().isEmpty()) {
+            // Persist the fence before abort so failover cannot reuse a 
version targeted by a delayed RPC.
+            lockRead();
+            try {
+                if (isCurrentDictionary(dictionary)) {
+                    dictionary.increaseVersion();
+                    
Env.getCurrentEnv().getEditLog().logDictionaryIncVersion(dictionary);
+                    versionFenced = true;
+                }
+            } finally {
+                unlockRead();
+            }
+        }
+
+        AbortResult abortResult = abortSpecificVersion(ctx, dictionary, 
stagedVersion);
+        lockRead();
+        try {
+            if (isCurrentDictionary(dictionary)) {
+                if (versionFenced && !abortResult.outcomeUnknown) {
+                    dictionary.decreaseVersion();

Review Comment:
   Fixed. Cancel and abort acknowledgements are no longer treated as proof that 
late EOS is fenced. A used full-load version remains monotonically consumed, so 
a retry uses V+2 and cannot be overwritten by delayed V+1 sink work.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertIntoTableCommand.java:
##########
@@ -354,6 +411,37 @@ public void beforeComplete(AbstractInsertExecutor 
insertExecutor, StmtExecutor e
         throw new AnalysisException("Insert plan failed. Could not get target 
table lock.");
     }
 
+    private void lockCurrentTarget(ConnectContext ctx, DatabaseIf<?> database, 
TableIf table) {
+        if (!(database instanceof Database) || table instanceof Dictionary) {
+            table.readLock();

Review Comment:
   This is a valid existing limitation, but it cannot be made correct by the 
local wrapper lock or ID check: external wrappers use deterministic 
name-derived IDs, and RemoteOlapTable does not carry a remote object-generation 
token. This PR therefore keeps existing external-table semantics and scopes the 
strong object-identity guarantee to InternalCatalog. A complete fix needs 
connector-level generation metadata propagated into the planned sink. I am 
leaving this thread unresolved rather than claiming the local check solves it.



##########
fe/fe-core/src/main/java/org/apache/doris/planner/GroupCommitPlanner.java:
##########
@@ -193,26 +194,34 @@ public static void 
executeGroupCommitInsert(ConnectContext ctx, PreparedStatemen
             StatementContext statementContext) throws Exception {
         PrepareCommand prepareCommand = preparedStmtCtx.command;
         InsertIntoTableCommand command = (InsertIntoTableCommand) 
(prepareCommand.getLogicalPlan());
-        OlapTable table = (OlapTable) command.getTable(ctx);
         for (int retry = 0; retry < MAX_RETRY; retry++) {
-            if 
(Env.getCurrentEnv().getGroupCommitManager().isBlock(table.getId())) {
-                String msg = "insert table " + table.getId() + SCHEMA_CHANGE;
-                LOG.info(msg);
-                throw new DdlException(msg);
-            }
             boolean reuse = false;
             GroupCommitPlanner groupCommitPlanner;
-            if (preparedStmtCtx.groupCommitPlanner.isPresent()
-                    && table.getId() == 
preparedStmtCtx.groupCommitPlanner.get().table.getId()
-                    && table.getBaseSchemaVersion() == 
preparedStmtCtx.groupCommitPlanner.get().baseSchemaVersion) {
-                groupCommitPlanner = preparedStmtCtx.groupCommitPlanner.get();
-                reuse = true;
+            OlapTable currentTable = (OlapTable) command.getTable(ctx);
+            checkGroupCommitBlocked(currentTable);

Review Comment:
   Fixed. Prepared group commit now acquires ref-counted admission atomically 
with exact target validation and holds it through planner reuse/build and the 
BE RPC. DDL blocks new admissions, waits for active requests, then drains WAL 
before switching metadata. Follower BE selection is also rejected by the master 
while the table is blocked.



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