FANNG1 commented on code in PR #8252:
URL: https://github.com/apache/gravitino/pull/8252#discussion_r2300364083


##########
catalogs/catalog-fileset/src/main/java/org/apache/gravitino/catalog/fileset/SecureFilesetCatalogOperations.java:
##########
@@ -271,6 +280,208 @@ public void close() throws IOException {
     catalogUserContext.close();
 
     UserContext.cleanAllUserContext();
+
+    boolean testEnv = System.getenv("GRAVITINO_TEST") != null;
+    if (testEnv) {
+      // In test environment, we do not need to clean up class loader related 
stuff
+      return;
+    }
+
+    try {
+      closeStatsDataClearerInFileSystem();
+
+      // Clear all thread references to the ClosableHiveCatalog class loader.
+      Thread[] threads = getAllThreads();
+      for (Thread thread : threads) {
+        // Clear thread local map for webserver threads in the current class 
loader. Why do we need
+        // this? Because the webserver threads are long-lived threads and will 
holds may thread
+        // local
+        // references to the current class loader. However, they can't be 
cleared as `Catalog.close`
+        // is called in the thread pool located in the Caffeine cache, which 
is not in the webserver
+        // threads. So we need to manually clear the thread local map for 
webserver threads.
+        clearThreadLocalMap(thread);
+
+        // Close all threads that are using the FilesetCatalogOperations class 
loader
+        if (runningWithCurrentClassLoader(thread)) {
+          LOG.info("Interrupting thread: {}", thread.getName());
+          thread.setContextClassLoader(null);
+          thread.interrupt();
+          try {
+            thread.join(5000);
+          } catch (InterruptedException e) {
+            LOG.warn("Failed to join thread: {}", thread.getName(), e);
+          }
+        }
+      }
+
+      // Release the LogFactory for the FilesetCatalogOperations class loader
+      unregisterLogFactory();
+
+      closeResourceInAWS();
+
+      closeResourceInGCP();
+
+      closeResourceInAzure();
+
+      clearShutdownHooks();
+    } catch (Exception e) {
+      LOG.warn("Failed to clear FileSystem statistics cleaner thread", e);
+    }
+  }
+
+  private void unregisterLogFactory() {
+    try {
+      
LogFactory.release(SecureFilesetCatalogOperations.class.getClassLoader());
+    } catch (Exception e) {
+      LOG.warn("Failed to unregister LogFactory", e);
+    }
+  }
+
+  private static void closeResourceInAzure() {
+    // For Azure
+    try {
+      Class<?> relocatedLogFactory =
+          
Class.forName("org.apache.gravitino.azure.shaded.org.apache.commons.logging.LogFactory");
+      MethodUtils.invokeStaticMethod(
+          relocatedLogFactory, "release", 
SecureFilesetCatalogOperations.class.getClassLoader());
+
+      // Clear timer in AbfsClientThrottlingAnalyzer
+      Class<?> abfsClientThrottlingInterceptClass =
+          
Class.forName("org.apache.hadoop.fs.azurebfs.services.AbfsClientThrottlingIntercept");
+      Object abfsClientThrottlingIntercept =
+          FieldUtils.readStaticField(abfsClientThrottlingInterceptClass, 
"singleton", true);
+
+      Object readThrottler =
+          FieldUtils.readField(abfsClientThrottlingIntercept, "readThrottler", 
true);
+      Object writeThrottler =
+          FieldUtils.readField(abfsClientThrottlingIntercept, 
"writeThrottler", true);
+
+      Timer readTimer = (Timer) FieldUtils.readField(readThrottler, "timer", 
true);
+      readTimer.cancel();
+      Timer writeTimer = (Timer) FieldUtils.readField(writeThrottler, "timer", 
true);
+      writeTimer.cancel();
+    } catch (Exception e) {
+      LOG.warn("Failed to handle Azure file system...", e);
+    }
+  }
+
+  private static void closeResourceInGCP() {
+    // For GCS
+    try {
+      Class<?> relocatedLogFactory =
+          
Class.forName("org.apache.gravitino.gcp.shaded.org.apache.commons.logging.LogFactory");
+      MethodUtils.invokeStaticMethod(
+          relocatedLogFactory, "release", 
SecureFilesetCatalogOperations.class.getClassLoader());
+    } catch (Exception e) {
+      LOG.warn("Failed to find GCS shaded LogFactory", e);
+    }
+  }
+
+  private static void closeResourceInAWS() {
+    // For Aws SDK metrics, unregister the metric admin MBean
+    try {
+      Class<?> methodUtilsClass = 
Class.forName("com.amazonaws.metrics.AwsSdkMetrics");
+      MethodUtils.invokeStaticMethod(methodUtilsClass, 
"unregisterMetricAdminMBean");
+    } catch (Exception e) {
+      LOG.warn("Failed to unregister AWS SDK metrics admin MBean", e);
+      // This is not critical, so we just log the warning
+    }
+  }
+
+  private static void clearThreadLocalMap(Thread thread) {
+    if (thread != null && thread.getName().startsWith("Gravitino-webserver-")) 
{
+      // Try to

Review Comment:
   Try to?



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

Reply via email to