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


##########
fe/fe-core/src/main/java/org/apache/doris/datasource/metacache/MetaCache.java:
##########
@@ -662,6 +687,103 @@ public void invalidate(String localName, long id) {
         }
     }
 
+    /** Fences old objects while retaining unrelated numeric routes for fresh 
reload after wide retirement. */
+    public void invalidateLookup(String localName, boolean allObjects) {
+        metaObjLifecycleLock.writeLock().lock();
+        try {
+            synchronized (namesMutationLock) {
+                invalidateNames();
+                metaObjGeneration.incrementAndGet();
+                lookupObservationGeneration++;
+                if (allObjects) {
+                    metaObjCache.invalidateAll();
+                } else {
+                    metaObjCache.invalidate(localName);
+                }
+                // Only the target's routes retire. Surviving siblings must 
reload by ID without
+                // requiring a foreground named lookup to register their 
identities again.
+                String foldedName = allObjects ? 
localName.toLowerCase(Locale.ROOT) : localName;
+                idToName.entrySet().removeIf(entry -> allObjects
+                        ? 
entry.getValue().toLowerCase(Locale.ROOT).equals(foldedName)
+                        : entry.getValue().equals(localName));
+            }
+        } finally {
+            metaObjLifecycleLock.writeLock().unlock();
+        }
+    }
+
+    /** Blocks missing-result repair during a metadata-only refresh without 
evicting names or objects. */
+    public Runnable beginMetadataRefresh() {
+        metaObjLifecycleLock.writeLock().lock();
+        try {
+            metadataRefreshes++;
+            lookupObservationGeneration++;
+        } finally {
+            metaObjLifecycleLock.writeLock().unlock();
+        }
+        return () -> {
+            metaObjLifecycleLock.writeLock().lock();
+            try {
+                metadataRefreshes--;
+                lookupObservationGeneration++;
+            } finally {
+                metaObjLifecycleLock.writeLock().unlock();
+            }
+        };
+    }
+
+    /** Captures a complete names snapshot and matching resident object; never 
loads remote metadata. */
+    public Optional<Runnable> observeLookup(String localName, String 
remoteName, T expected,
+            boolean allObjects, Runnable invalidateMetadata) {
+        metaObjLifecycleLock.readLock().lock();
+        try {
+            synchronized (namesMutationLock) {
+                NamesCacheValue names = namesCache.getIfPresent("");
+                Optional<T> value = metaObjCache.getIfPresent(localName);
+                Pair<String, String> pair = names == null ? null : 
names.names.get(localName);
+                // A complete refresh may already omit a remotely dropped 
table while its object/ID
+                // remains hot. The retained object still authorizes repair; a 
conflicting live name does not.
+                if (metadataRefreshes != 0 || names == null || !names.complete
+                        || (pair != null && !pair.key().equals(remoteName)) || 
value == null || !value.isPresent()
+                        || value.get() != expected) {
+                    return Optional.empty();
+                }
+                long objectGeneration = metaObjGeneration.get();
+                long observationGeneration = lookupObservationGeneration;
+                return Optional.of(() -> {
+                    metaObjLifecycleLock.writeLock().lock();
+                    try {
+                        synchronized (namesMutationLock) {
+                            if (metadataRefreshes != 0 || objectGeneration != 
metaObjGeneration.get()
+                                    || observationGeneration != 
lookupObservationGeneration
+                                    || namesCache.getIfPresent("") != names
+                                    || metaObjCache.getIfPresent(localName) != 
value) {
+                                return;
+                            }
+                            // Case-folded catalogs can retain Foo's old 
object after a names refresh
+                            // has published a new FOO identity. Do not widen 
that old miss to the DB.
+                            if (pair == null && allObjects && 
names.names.values().stream().anyMatch(current ->
+                                    current.value().equalsIgnoreCase(localName)

Review Comment:
   [P2] Use the lookup identity's folding rule for replacement checks
   
   With `lower_case_table_names=2` on an English/ROOT-casing FE, `I` and 
dotless `ı` have distinct lowercase lookup keys (as the new 
`testWideInvalidationUsesRootLocaleForIdentityMatching` also expects). Warm 
both, drop `I` externally, and let a complete names-only refresh publish just 
`ı` while the old `I` object/ID remains hot. An ID-only statistics lookup can 
still reach `getColumn()` -> guarded Iceberg `getFullSchema()`; with 
`meta.cache.iceberg.table.ttl-second=0`, it confirms `NoSuchTableException`. 
Here `pair == null`, but `ı.equalsIgnoreCase("I")` is true, so repair returns 
before either metadata fencing or `invalidateLookup()`. The dropped object's 
numeric route survives, and hot ID readers can keep repeating the stale-object 
failure. Compare with the same ROOT-lowercase identity rule used by 
`invalidateLookup()` and cover this omitted-name observation case. This differs 
from the existing sibling-route-loss thread: it incorrectly retains the dropped 
target before retireme
 nt begins.



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