github-actions[bot] commented on code in PR #66913:
URL: https://github.com/apache/doris/pull/66913#discussion_r3831225091


##########
fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java:
##########
@@ -984,21 +984,84 @@ public PlSqlOperation getPlSqlOperation() {
     // with "Split source X is released". These executors are finalized when 
the next query starts
     // on this connection, or when the connection is torn down. See #62259.
     private final List<StmtExecutor> flightSqlDeferredExecutors = new 
ArrayList<>();
+    private boolean flightSqlDeferredExecutorsSealed;
+    private int flightSqlResultPublishers;
 
-    public void addFlightSqlDeferredExecutor(StmtExecutor executor) {
+    public boolean addFlightSqlDeferredExecutor(StmtExecutor executor) {
         synchronized (flightSqlDeferredExecutors) {
+            if (flightSqlDeferredExecutorsSealed) {
+                return false;
+            }
             flightSqlDeferredExecutors.add(executor);
+            return true;
+        }
+    }
+
+    /** Linearizes GetFlightInfo publication with the terminal session seal. */
+    public boolean canPublishFlightSqlResult() {
+        synchronized (flightSqlDeferredExecutors) {
+            return !flightSqlDeferredExecutorsSealed;
+        }
+    }
+
+    public boolean beginFlightSqlResultPublication() {
+        synchronized (flightSqlDeferredExecutors) {
+            if (flightSqlDeferredExecutorsSealed) {
+                return false;
+            }
+            flightSqlResultPublishers++;
+            return true;
+        }
+    }
+
+    public void endFlightSqlResultPublication() {
+        List<StmtExecutor> toClose = null;
+        synchronized (flightSqlDeferredExecutors) {
+            if (--flightSqlResultPublishers == 0 && 
flightSqlDeferredExecutorsSealed) {

Review Comment:
   [P1] Do not return a FlightInfo after teardown wins publication
   
   There is still a seal window after the producer's final 
`canPublishFlightSqlResult()` check: Java evaluates the return expression 
before running its `finally`. If teardown seals while this publisher is active, 
it defers its drain; this decrement then reaches zero and finalizes the 
registered executor, coordinator, and detached Hudi/Iceberg resources, but the 
already-evaluated `FlightInfo` is still returned. The client therefore receives 
a ticket whose DoGet query is already released. Make publication completion 
report when teardown won (or atomically commit publication so teardown cannot 
drain it), and add a barrier test that seals after the final check succeeds but 
before this decrement.



##########
fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalMetaCache.java:
##########
@@ -105,12 +113,46 @@ public IcebergExternalMetaCache(ExecutorService 
refreshExecutor) {
 
     public Table getIcebergTable(ExternalTable dorisTable) {
         NameMapping nameMapping = dorisTable.getOrBuildNameMapping();
-        return 
tableEntry.get(nameMapping.getCtlId()).get(nameMapping).getIcebergTable();
+        IcebergTableCacheValue.Lease lease = statementLease(nameMapping);
+        if (lease != null) {
+            return lease.getIcebergTable();
+        }
+        // Background/bootstrap callers without a StatementContext have no 
deterministic release boundary.
+        // Load directly instead of borrowing a cache generation that could be 
evicted while they use it.
+        return loadTable(nameMapping);
+    }
+
+    /** Returns the executor owned by the exact table generation retained by 
this statement. */
+    ThreadPoolExecutor getIcebergTableExecutor(ExternalTable dorisTable) {
+        NameMapping nameMapping = dorisTable.getOrBuildNameMapping();
+        IcebergTableCacheValue.Lease lease = statementLease(nameMapping);
+        if (lease == null || lease.getPlanningExecutor() == null) {
+            return dorisTable.getCatalog().getThreadPoolWithPreAuth();
+        }
+        return lease.getPlanningExecutor();
+    }
+
+    /** Runs a bounded metadata operation while retaining the exact table 
generation it uses. */
+    <T> T withIcebergTable(ExternalTable dorisTable, Function<Table, T> 
action) {
+        NameMapping nameMapping = dorisTable.getOrBuildNameMapping();
+        IcebergTableCacheValue.Lease statementLease = 
statementLease(nameMapping);
+        if (statementLease != null) {
+            return action.apply(statementLease.getIcebergTable());
+        }
+        try (IcebergTableCacheValue.Lease operationLease = 
borrow(nameMapping)) {
+            return action.apply(operationLease.getIcebergTable());
+        }
     }
 
     public IcebergSnapshotCacheValue getSnapshotCache(ExternalTable 
dorisTable) {
         NameMapping nameMapping = dorisTable.getOrBuildNameMapping();
-        return 
tableEntry.get(nameMapping.getCtlId()).get(nameMapping).getLatestSnapshotCacheValue();
+        IcebergTableCacheValue.Lease lease = statementLease(nameMapping);
+        if (lease != null) {
+            return lease.getLatestSnapshotCacheValue();
+        }
+        Table table = loadTable(nameMapping);

Review Comment:
   [P1] Give background snapshot loads a bounded generation owner
   
   `DictionaryManager` polls Iceberg source versions without a 
`ConnectContext`, so every poll reaches this branch. It loads a raw table 
outside both `TableLoadContext` and `IcebergTableCacheValue`, then resolves the 
planning executor separately. A concurrent reset can therefore close G1 while 
the projection still uses it or pair the G1 table with G2's executor, and 
per-table FileIO created by recurring direct loads never reaches the cached 
value's retirement callback. Run the projection under one exact native/HMS load 
lease and close it after deriving non-runtime metadata (or return an explicit 
owner), with a no-context polling/reset regression.



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