Skip to content

Commit

Permalink
Fixes #12: Compatibility with Openfire 4.8.0
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
guusdk committed Nov 2, 2024
1 parent b683326 commit 627cde7
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 73 deletions.
2 changes: 2 additions & 0 deletions changelog.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ <h1>
<p><b>1.2.0</b> -- (tbd)</p>
<ul>
<li>New minimum server requirement: 4.8.0</li>
<li>Removed evaluator of core thread pools</li>
<li><a href="https://github.com/igniterealtime/openfire-threaddump-plugin/pull/12">Issue 12</a>: Fix compatibility with Openfire 4.8.0</li>
</ul>

<p><b>1.1.1</b> -- August 31, 2023</p>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>plugins</artifactId>
<groupId>org.igniterealtime.openfire</groupId>
<version>4.3.0</version>
<version>4.8.0</version>
</parent>

<groupId>org.igniterealtime.openfire.plugins</groupId>
Expand Down
31 changes: 0 additions & 31 deletions src/main/java/org/apache/jasper/runtime/JspSourceImports.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
/*
* 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;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;

public class CoreThreadPoolsEvaluator implements Evaluator
{
Expand Down Expand Up @@ -60,31 +73,38 @@ protected boolean checkPools()
final Set<ConnectionListener> 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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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
{
Expand Down Expand Up @@ -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());
Expand Down
7 changes: 5 additions & 2 deletions src/main/web/threaddump.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) );
Expand Down
2 changes: 1 addition & 1 deletion src/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<description>${project.description}</description>
<author>Ignite Realtime</author>
<version>${project.version}</version>
<date>2023-08-31</date>
<date>2024-11-02</date>
<minServerVersion>4.8.0</minServerVersion>

<adminconsole>
Expand Down
19 changes: 10 additions & 9 deletions src/readme.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,16 @@ <h2>Configuration</h2>
<p>The following evaluator classes are available:</p>
<ul>
<li>
<p><tt style="color: black">org.igniterealtime.openfire.plugin.threaddump.evaluator.CoreThreadPoolsEvaluator</tt></p>
<p>An evaluator that periodically checks the activity in the thread pools that power most network-related activity.
<table>
<tr><td><tt>threaddump.evaluator.threadpools.interval</tt></td><td>The frequency (in milliseconds) of core network thread pool evaluation.</td></tr>
<tr><td><tt>threaddump.evaluator.threadpools.busy-percentage-max</tt></td><td>The percentage of threads in a pool that can be running at the same time that is considered 'busy'.</td></tr>
<tr><td><tt>threaddump.evaluator.threadpools.successive-hits</tt></td><td>How many successive evaluations must have detected excessive thread pool usage, for a thread dump to be created.</td></tr>
</table>
</p>
</li><li>
<!-- FIXME: Re-enable when CoreThreadPoolsEvaluator is fixed. See https://github.com/igniterealtime/openfire-threaddump-plugin/issues/16 -->
<!--<p><tt style="color: black">org.igniterealtime.openfire.plugin.threaddump.evaluator.CoreThreadPoolsEvaluator</tt></p>-->
<!--<p>An evaluator that periodically checks the activity in the thread pools that power most network-related activity.-->
<!-- <table>-->
<!-- <tr><td><tt>threaddump.evaluator.threadpools.interval</tt></td><td>The frequency (in milliseconds) of core network thread pool evaluation.</td></tr>-->
<!-- <tr><td><tt>threaddump.evaluator.threadpools.busy-percentage-max</tt></td><td>The percentage of threads in a pool that can be running at the same time that is considered 'busy'.</td></tr>-->
<!-- <tr><td><tt>threaddump.evaluator.threadpools.successive-hits</tt></td><td>How many successive evaluations must have detected excessive thread pool usage, for a thread dump to be created.</td></tr>-->
<!-- </table>-->
<!--</p>-->
<!-- </li><li>-->
<p><tt style="color: black">org.igniterealtime.openfire.plugin.threaddump.evaluator.DatabaseConnectionPoolEvaluator</tt></p>
<p>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.
<table>
Expand Down

0 comments on commit 627cde7

Please sign in to comment.