From 627cde74e34f489b3e2ea6a4eccccfd1f0b8ca58 Mon Sep 17 00:00:00 2001
From: Guus der Kinderen
Date: Sat, 2 Nov 2024 19:30:43 +0100
Subject: [PATCH] Fixes #12: Compatibility with Openfire 4.8.0
This commit disables the CoreThreadPoolEvaluator, which isn't compatible any more since the switch from MINA to Netty.
A new ticket has been created to restore this functionality in a future version (#16).
---
changelog.html | 2 +
pom.xml | 2 +-
.../jasper/runtime/JspSourceImports.java | 31 ----------
.../plugin/threaddump/ThreadDumpPlugin.java | 6 +-
.../evaluator/CoreThreadPoolsEvaluator.java | 60 ++++++++++++-------
.../DatabaseConnectionPoolEvaluator.java | 8 +--
src/main/web/threaddump.jsp | 7 ++-
src/plugin.xml | 2 +-
src/readme.html | 19 +++---
9 files changed, 64 insertions(+), 73 deletions(-)
delete mode 100644 src/main/java/org/apache/jasper/runtime/JspSourceImports.java
diff --git a/changelog.html b/changelog.html
index df0c1a2..1f95feb 100644
--- a/changelog.html
+++ b/changelog.html
@@ -48,6 +48,8 @@
1.2.0 -- (tbd)
- New minimum server requirement: 4.8.0
+ - Removed evaluator of core thread pools
+ - Issue 12: Fix compatibility with Openfire 4.8.0
1.1.1 -- August 31, 2023
diff --git a/pom.xml b/pom.xml
index a36afd7..589177c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
plugins
org.igniterealtime.openfire
- 4.3.0
+ 4.8.0
org.igniterealtime.openfire.plugins
diff --git a/src/main/java/org/apache/jasper/runtime/JspSourceImports.java b/src/main/java/org/apache/jasper/runtime/JspSourceImports.java
deleted file mode 100644
index cb9e441..0000000
--- a/src/main/java/org/apache/jasper/runtime/JspSourceImports.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// This class is added to the sources of this plugin to make the plugin executable in Openfire versions prior to 4.3.0.
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jasper.runtime;
-
-import java.util.Set;
-
-/**
- * The EL engine needs access to the imports used in the JSP page to configure
- * the ELContext. The imports are available at compile time but the ELContext
- * is created lazily per page. This interface exposes the imports at runtime so
- * that they may be added to the ELContext when it is created.
- */
-public interface JspSourceImports {
- Set getPackageImports();
- Set getClassImports();
-}
diff --git a/src/main/java/org/igniterealtime/openfire/plugin/threaddump/ThreadDumpPlugin.java b/src/main/java/org/igniterealtime/openfire/plugin/threaddump/ThreadDumpPlugin.java
index ed8105a..f676d73 100644
--- a/src/main/java/org/igniterealtime/openfire/plugin/threaddump/ThreadDumpPlugin.java
+++ b/src/main/java/org/igniterealtime/openfire/plugin/threaddump/ThreadDumpPlugin.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 Ignite Realtime Foundation. All rights reserved.
+ * Copyright (C) 2019-2024 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,7 +82,7 @@ public synchronized void configMonitor()
{
try
{
- final Evaluator evaluator = evaluatorClass.newInstance();
+ final Evaluator evaluator = evaluatorClass.getDeclaredConstructor().newInstance();
if (evaluator.isSupported()) {
evaluators.add(evaluator);
} else {
@@ -98,7 +98,7 @@ public synchronized void configMonitor()
if ( !evaluators.isEmpty() )
{
final Duration backoff = Duration.of( backoffMS, ChronoUnit.MILLIS );
- Log.info( "Scheduling a check for thread dump necessity evaluation every {}ms (starting after a delay of {}ms. No more than one dump per {} will be generated.", new Object[] {intervalMS, delayMS, backoff} );
+ Log.info( "Scheduling a check for thread dump necessity evaluation every {}ms (starting after a delay of {}ms. No more than one dump per {} will be generated.", intervalMS, delayMS, backoff);
evaluators.forEach( evaluator -> Log.info( "Enabled evaluator {}, running every {}", evaluator.getClass().getCanonicalName(), evaluator.getInterval() ) );
task = new DumpCheckTimerTask( backoff );
evaluators.forEach(task::add);
diff --git a/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/CoreThreadPoolsEvaluator.java b/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/CoreThreadPoolsEvaluator.java
index c71cec4..e5edc39 100644
--- a/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/CoreThreadPoolsEvaluator.java
+++ b/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/CoreThreadPoolsEvaluator.java
@@ -1,11 +1,25 @@
+/*
+ * Copyright (C) 2019-2024 Ignite Realtime Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.igniterealtime.openfire.plugin.threaddump.evaluator;
-import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
-import org.apache.mina.filter.executor.ExecutorFilter;
-import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.jivesoftware.openfire.XMPPServer;
+import org.jivesoftware.openfire.spi.ConnectionAcceptor;
import org.jivesoftware.openfire.spi.ConnectionListener;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
+import org.jivesoftware.openfire.spi.NettyConnectionAcceptor;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -13,7 +27,6 @@
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Set;
-import java.util.concurrent.ThreadPoolExecutor;
public class CoreThreadPoolsEvaluator implements Evaluator
{
@@ -60,31 +73,38 @@ protected boolean checkPools()
final Set listeners = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager()).getListeners();
for ( ConnectionListener listener : listeners )
{
- final NioSocketAcceptor socketAcceptor = listener.getSocketAcceptor();
+ final ConnectionAcceptor socketAcceptor = listener.getConnectionAcceptor();
if ( socketAcceptor == null )
{
continue;
}
- final DefaultIoFilterChainBuilder filterChain = socketAcceptor.getFilterChain();
- if ( filterChain == null )
+ if (!(socketAcceptor instanceof NettyConnectionAcceptor))
{
continue;
}
- if ( filterChain.contains( ConnectionManagerImpl.EXECUTOR_FILTER_NAME ) )
- {
- final ExecutorFilter executorFilter = (ExecutorFilter) filterChain.get( ConnectionManagerImpl.EXECUTOR_FILTER_NAME );
- final int max = ((ThreadPoolExecutor) executorFilter.getExecutor()).getMaximumPoolSize();
- final int act = ((ThreadPoolExecutor) executorFilter.getExecutor()).getActiveCount();
- final int busyPercentage = (int) Math.round( act * 100.0 / max );
-
- Log.trace( "{}% ({}/{}) thread running in pool {} {}. Threshold: {}%", new Object[] { busyPercentage, act, max, listener.getType(), listener.getTLSPolicy(), busyPercentageLimit });
- if ( busyPercentage > busyPercentageLimit )
- {
- return true;
- }
- }
+// FIXME: Replace the MINA-based implementation with one that is compatible with Netty. See https://github.com/igniterealtime/openfire-threaddump-plugin/issues/16
+// final EventLoopGroup childEventLoopGroup = ((NettyConnectionAcceptor) socketAcceptor)..getChildEventLoopGroup();
+// if (childEventLoopGroup == null)
+// {
+// continue;
+// }
+//
+// childEventLoopGroup.
+// if ( filterChain.contains( ConnectionManagerImpl.EXECUTOR_FILTER_NAME ) )
+// {
+// final ExecutorFilter executorFilter = (ExecutorFilter) filterChain.get( ConnectionManagerImpl.EXECUTOR_FILTER_NAME );
+// final int max = ((ThreadPoolExecutor) executorFilter.getExecutor()).getMaximumPoolSize();
+// final int act = ((ThreadPoolExecutor) executorFilter.getExecutor()).getActiveCount();
+// final int busyPercentage = (int) Math.round( act * 100.0 / max );
+//
+// Log.trace( "{}% ({}/{}) thread running in pool {} {}. Threshold: {}%", busyPercentage, act, max, listener.getType(), listener.getTLSPolicy(), busyPercentageLimit);
+// if ( busyPercentage > busyPercentageLimit )
+// {
+// return true;
+// }
+// }
}
return false;
diff --git a/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/DatabaseConnectionPoolEvaluator.java b/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/DatabaseConnectionPoolEvaluator.java
index ebc70c4..d928429 100755
--- a/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/DatabaseConnectionPoolEvaluator.java
+++ b/src/main/java/org/igniterealtime/openfire/plugin/threaddump/evaluator/DatabaseConnectionPoolEvaluator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) Ignite Realtime Foundation. All rights reserved.
+ * Copyright (C) 2022-2024 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,16 +18,12 @@
import org.jivesoftware.database.ConnectionProvider;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.database.DefaultConnectionProvider;
-import org.jivesoftware.database.EmbeddedConnectionProvider;
import org.jivesoftware.util.JiveGlobals;
-import org.jivesoftware.util.TaskEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.reflect.Field;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
-import java.util.concurrent.ThreadPoolExecutor;
public class DatabaseConnectionPoolEvaluator implements Evaluator
{
@@ -78,7 +74,7 @@ protected boolean checkPool()
final int activeConnections = defaultConnectionProvider.getActiveConnections();
final int maxConnections = defaultConnectionProvider.getMaxConnections();
final int busyPercentage = 100 * activeConnections / maxConnections;
- Log.trace( "{}% ({}/{}) connections of database pool are currently active. Threshold: {}%", new Object[] { busyPercentage, activeConnections, maxConnections, busyPercentageLimit });
+ Log.trace( "{}% ({}/{}) connections of database pool are currently active. Threshold: {}%", busyPercentage, activeConnections, maxConnections, busyPercentageLimit);
return busyPercentage > busyPercentageLimit;
} else {
Log.debug("This server is using {} as the database connection provider for Openfire, which is not supported by this evaluator.", connectionProvider.getClass().getSimpleName());
diff --git a/src/main/web/threaddump.jsp b/src/main/web/threaddump.jsp
index d13d514..7d2fc62 100644
--- a/src/main/web/threaddump.jsp
+++ b/src/main/web/threaddump.jsp
@@ -123,8 +123,11 @@
pageContext.setAttribute( "dump", new DefaultThreadDumpFormatter().format( dump ) );
pageContext.setAttribute( "plugin", plugin );
- pageContext.setAttribute( "isPoolEvaluatorEnabled", plugin.getTaskEvaluatorClasses().contains( CoreThreadPoolsEvaluator.class ) );
- pageContext.setAttribute( "isPoolEvaluatorSupported", new CoreThreadPoolsEvaluator().isSupported() );
+// pageContext.setAttribute( "isPoolEvaluatorEnabled", plugin.getTaskEvaluatorClasses().contains( CoreThreadPoolsEvaluator.class ) );
+// pageContext.setAttribute( "isPoolEvaluatorSupported", new CoreThreadPoolsEvaluator().isSupported() );
+ pageContext.setAttribute( "isPoolEvaluatorEnabled", false ); // FIXME re-enable when issue #12 is fixed.
+ pageContext.setAttribute( "isPoolEvaluatorSupported", false ); // FIXME re-enable when issue #12 is fixed.
+
pageContext.setAttribute( "isDBPoolEvaluatorEnabled", plugin.getTaskEvaluatorClasses().contains( DatabaseConnectionPoolEvaluator.class ) );
pageContext.setAttribute( "isDBPoolEvaluatorSupported", new DatabaseConnectionPoolEvaluator().isSupported() );
pageContext.setAttribute( "isDeadlockEvaluatorEnabled", plugin.getTaskEvaluatorClasses().contains( DeadlockEvaluator.class ) );
diff --git a/src/plugin.xml b/src/plugin.xml
index 6769b40..7ab0aac 100644
--- a/src/plugin.xml
+++ b/src/plugin.xml
@@ -6,7 +6,7 @@
${project.description}
Ignite Realtime
${project.version}
- 2023-08-31
+ 2024-11-02
4.8.0
diff --git a/src/readme.html b/src/readme.html
index f4c63ef..9aa5327 100644
--- a/src/readme.html
+++ b/src/readme.html
@@ -102,15 +102,16 @@ Configuration
The following evaluator classes are available:
-
+
+
+
+
+
+
+
+
+
+
org.igniterealtime.openfire.plugin.threaddump.evaluator.DatabaseConnectionPoolEvaluator
An evaluator that periodically checks the amount of active database connections in the pool that manages the total amount of available connections. This evaluator is only available when using the standard database connection provider. It does not support the embedded database.