CalvinKirs commented on code in PR #66717:
URL: https://github.com/apache/doris/pull/66717#discussion_r3836645366


##########
fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/source/IcebergScanNode.java:
##########
@@ -792,8 +792,9 @@ private Table useFrozenTableGeneration(Table currentTable) {
         if 
(snapshot.filter(IcebergMvccSnapshot.class::isInstance).isPresent()) {
             IcebergSnapshotCacheValue cacheValue =
                     ((IcebergMvccSnapshot) 
snapshot.get()).getSnapshotCacheValue();
-            if (cacheValue.getIcebergTable().isPresent()) {
-                Table frozenBaseTable = cacheValue.getIcebergTable().get();
+            Optional<Table> frozenTable = cacheValue.getIcebergTable();

Review Comment:
   Fixed in 246b5445097: Iceberg snapshot projections now carry the 
ExecutionAuthenticator captured from the table generation that built them 
(bound at both projection branches in getSnapshotCache), and 
IcebergScanNode.useFrozenTableGeneration - the shared entry for regular 
relations and snapshot-selectable system tables, called from both doInitialize 
and createTableScan - validates the pinned projection against the catalog 
current context via ensurePlannableUnder before any frozen table is planned. A 
statement bound before a credential/storage ALTER now fails retryably before 
planning instead of running G1 FrozenTableOperations/FileIO under the replaced 
authenticator, storage state and executor. Regressions cover context 
propagation from the published generation and the fence accepting the captured 
context while rejecting a replaced one (system tables share the same validated 
path).



##########
fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalMetaCache.java:
##########
@@ -139,45 +312,116 @@ public ManifestCacheValue 
getManifestCacheValue(ExternalTable dorisTable,
         MetaCacheEntry<IcebergManifestEntryKey, ManifestCacheValue> 
manifestEntry =
                 this.manifestEntry.get(nameMapping.getCtlId());
         IcebergManifestEntryKey key = IcebergManifestEntryKey.of(manifest);
-        boolean hit = manifestEntry.getIfPresent(key) != null;
+        boolean hit = manifestEntry.peekIfPresent(key) != null;
         if (cacheHitRecorder != null) {
             cacheHitRecorder.accept(hit);
         }
-        return manifestEntry.get(key, ignored -> 
loadManifestCacheValue(manifest, icebergTable, key.getContent()));
+        return manifestEntry.get(key,
+                ignored -> loadManifestCacheValue(
+                        manifest, icebergTable, key.getContent(), 
manifestEntry.isWeightAccounting()));
     }
 
     @Override
     public void invalidateCatalog(long catalogId) {
-        dropManifestFileIoCacheForCatalog(catalogId);
+        // Collect while the entries are still enumerable, drop only after the 
entries are
+        // detached: a load racing a pre-detach drop could repopulate the SDK 
content cache
+        // for a FileIO this reset already cleaned.
+        List<FileIO> retainedFileIos = collectManifestFileIos(catalogId);
         super.invalidateCatalog(catalogId);
+        dropManifestFileIoCaches(retainedFileIos);
     }
 
     @Override
     public void invalidateCatalogEntries(long catalogId) {
-        dropManifestFileIoCacheForCatalog(catalogId);
+        List<FileIO> retainedFileIos = collectManifestFileIos(catalogId);
         super.invalidateCatalogEntries(catalogId);
+        dropManifestFileIoCaches(retainedFileIos);
     }
 
     private IcebergTableCacheValue loadTableCacheValue(NameMapping 
nameMapping) {
-        CatalogIf catalog = 
Env.getCurrentEnv().getCatalogMgr().getCatalog(nameMapping.getCtlId());
+        CatalogIf catalog = getCatalog(nameMapping.getCtlId());
         if (catalog == null) {
             throw new RuntimeException(String.format("Cannot find catalog %d 
when loading table %s/%s.",
                     nameMapping.getCtlId(), nameMapping.getLocalDbName(), 
nameMapping.getLocalTblName()));
         }
 
+        // One catalog generation must supply the ops, the loaded table and 
the bound
+        // authenticator together: re-reading the mutable catalog after the 
load could bind a
+        // handle of the old generation to the execution context a concurrent 
ALTER installed.
+        // The acquisition is re-validated before publication; a mid-flight 
reset fails the miss
+        // (the caller retries against the reinitialized catalog) instead of 
publishing a splice.
+        ExecutionAuthenticator authenticator = 
requireExecutionAuthenticator(catalog);
         IcebergMetadataOps ops = resolveMetadataOps(catalog);
+        IcebergTableCacheValue value = execute(authenticator, () -> {
+            Table table = ops.loadTable(nameMapping.getRemoteDbName(), 
nameMapping.getRemoteTblName());
+            IcebergTableCacheValue loaded = new IcebergTableCacheValue(table);
+            loaded.bindAuthenticator(authenticator);

Review Comment:
   Fixed in 246b5445097: both the Iceberg and Paimon estimators now add a flat 
rounded-up retained-context allowance (AUTHENTICATION_CONTEXT_WEIGHT = 16KB, 
mirroring the existing per-owner FileIO and encryption-manager allowances of 
the coarse model) to every admitted table or snapshot value that carries a 
bound execution context, so a retired authentication generation kept alive only 
by old cached values is never entirely unaccounted; per-value charging matches 
the established independent-owner-lifetimes accounting stance. Regression 
asserts the exact allowance delta for bound vs unbound table and snapshot 
values in both engines.



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