wenzhenghu commented on code in PR #65126:
URL: https://github.com/apache/doris/pull/65126#discussion_r3601512877
##########
fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java:
##########
@@ -599,10 +589,148 @@ private String getLocalTableName(String tableName,
boolean isReplay) {
return finalName;
}
+ private NameCacheValue getTableNamesValue(boolean allowLoad) {
+ if (tableNames == null) {
+ return null;
+ }
+ return allowLoad ? tableNames.get("") : tableNames.getIfPresent("");
+ }
+
+ // Centralize names-negative-lookup handling so all table lookup paths
share the same config-driven policy.
+ @Nullable
+ private <R> R resolveTableNameFromSnapshot(String lookupName, boolean
isReplay,
+ Function<NameCacheValue, R> resolver) {
+ NameCacheValue cached = getTableNamesValue(false);
+ if (cached == null) {
+ if (isReplay) {
+ return null;
+ }
+ NameCacheValue loaded = getTableNamesValue(true);
+ return loaded == null ? null : resolver.apply(loaded);
+ }
+ R resolved = resolver.apply(cached);
+ if (resolved != null || isReplay ||
!Config.enable_external_meta_cache_name_miss_refresh) {
+ return resolved;
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("refresh table names after hot-snapshot miss, catalog:
{}, db: {}, lookup: {}",
+ getCatalog().getName(), getFullName(), lookupName);
+ }
+ resetMetaCacheNames();
+ NameCacheValue refreshed = getTableNamesValue(true);
+ return refreshed == null ? null : resolver.apply(refreshed);
+ }
+
+ private List<String> listLocalTableNamesFromCache() {
+ NameCacheValue namesValue = java.util.Objects.requireNonNull(
+ getTableNamesValue(true), "table names cache can not be null");
+ return namesValue.localNames();
+ }
+
+ private List<String> listLocalTableNamesWithoutCache(SessionContext
sessionContext) {
+ return
listTableNames(sessionContext).stream().map(Pair::value).collect(Collectors.toList());
+ }
+
+ @Nullable
+ private String getRemoteTableName(String localTableName, boolean isReplay)
{
+ // Route local-to-remote resolution through the shared helper so miss
reload stays consistent with lookups.
+ return resolveTableNameFromSnapshot(localTableName, isReplay,
+ namesValue ->
namesValue.remoteNameOfLocalName(localTableName));
+ }
+
+ private Optional<Pair<String, String>>
findTableNamePairWithoutCache(SessionContext sessionContext,
+ String requestedTableName) {
+ return listTableNames(sessionContext).stream()
+ .filter(pair -> matchesLocalTableName(pair.value(),
requestedTableName))
+ .findFirst();
+ }
+
+ private boolean matchesLocalTableName(String localTableName, String
requestedTableName) {
+ if (isStoredTableNamesLowerCase()) {
+ return
localTableName.equals(requestedTableName.toLowerCase(Locale.ROOT));
+ }
+ if (isTableNamesCaseInsensitive()) {
+ return localTableName.equalsIgnoreCase(requestedTableName);
+ }
+ return localTableName.equals(requestedTableName);
+ }
+
+ private String resolveTableNameForInvalidation(String tableName) {
+ if (isStoredTableNamesLowerCase()) {
+ return tableName.toLowerCase(Locale.ROOT);
+ }
+ if (!isTableNamesCaseInsensitive()) {
+ return tableName;
+ }
+
+ String localTableName = getLocalTableName(tableName, true);
+ if (localTableName != null) {
+ return localTableName;
+ }
+ T cachedTable = tables.findIfPresent(key ->
key.equalsIgnoreCase(tableName));
+ if (cachedTable != null) {
+ return cachedTable.getName();
+ }
+ return tableIdToName.values().stream()
+ .filter(name -> name.equalsIgnoreCase(tableName))
+ .findFirst()
+ .orElse(tableName);
+ }
+
+ private void updateTableCache(T table, String remoteTableName, String
localTableName) {
+ updateTableCache(table, remoteTableName, localTableName, false);
+ }
+
+ protected void updateTableCache(T table, String remoteTableName, String
localTableName,
+ boolean forceUpdateCacheState) {
+ buildMetaCache();
+ // Runtime incremental events only maintain names and object entries
that are already hot. The ID map is a
+ // lightweight lookup index and must always track registered objects
so normal by-ID lookup can load on demand.
+ if (forceUpdateCacheState) {
+ tableNames.compute("", (ignored, current) ->
+ (current == null ? NameCacheValue.empty() :
current).withName(remoteTableName, localTableName));
+ } else if (tableNames.getIfPresent("") != null) {
+ // The outer hot-entry check only skips a pointless compute on
cold state. current may still
+ // become null here if another thread invalidates the names entry
between getIfPresent and compute.
+ tableNames.compute("", (ignored, current) ->
+ current == null ? null : current.withName(remoteTableName,
localTableName));
+ }
+ if (forceUpdateCacheState || tables.getIfPresent(localTableName) !=
null) {
+ tables.put(localTableName, table);
+ }
+ tableIdToName.put(table.getId(), localTableName);
Review Comment:
Fixed in ccd4022e3c9. The ignored HMS event path no longer requires a
successful load-through lookup. For ignoreIfExists=true, CatalogMgr now
canonicalizes the local table key first and always calls unregisterTable(), so
names/object/ID/engine cache cleanup still runs when the remote table is
already gone and the object cache is cold. I also added deterministic FE UT
coverage for the full CREATE-event -> remote drop -> DROP-event wrapper path,
including mode-2 and mapped-name cases. Relevant FE UTs pass locally.
--
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]