From 94d0d29d195df0c40845e4195e86d687606dd376 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Fri, 21 Jul 2023 22:57:52 +0200 Subject: [PATCH] OF-2606: Prevent surplus DB connection errors during setup (#2189) When an invalid database connection string is provided during setup, the PluginMonitor tries to use it to read properties until it is corrected. This leads to database connection errors being logged every time that the monitor runs (once every 30 seconds). It's mostly benign, but annoying. With this commit, the PluginMonitor does not try to read from the database until setup has been completed (apart from the admin plugin, no other plugins are loaded during setup anyway). --- .../openfire/container/PluginMonitor.java | 99 +++++++++---------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/container/PluginMonitor.java b/xmppserver/src/main/java/org/jivesoftware/openfire/container/PluginMonitor.java index a9339b9f57..db74c1d048 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/container/PluginMonitor.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/container/PluginMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 IgniteRealtime.org + * Copyright 2016-2023 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. @@ -350,68 +350,67 @@ public boolean accept( final Path path ) throws IOException // plugins always precede their children. final Deque> dirs = sortPluginDirs( ds, devPlugins ); - // Hierarchy processing could be parallel. - final Collection> parallelProcesses = new ArrayList<>(); - for ( final List hierarchy : dirs ) + // Before running any plugin, make sure that the admin plugin is loaded. It is a dependency + // of all plugins that attempt to modify the admin panel. + if ( pluginManager.getPlugin( "admin" ) == null ) { - parallelProcesses.add( new Callable() - { + pluginManager.loadPlugin( "admin", dirs.getFirst().get( 0 ) ); + } - @Override - public Integer call() throws Exception + // Prevent trying to read properties from the database while we're still in setup mode. + if (!XMPPServer.getInstance().isSetupMode()) + { + // Hierarchy processing could be parallel. + final Collection> parallelProcesses = new ArrayList<>(); + for ( final List hierarchy : dirs ) + { + parallelProcesses.add( new Callable() { - int loaded = 0; - for ( final Path path : hierarchy ) + + @Override + public Integer call() throws Exception { - // If the plugin hasn't already been started, start it. - final String canonicalName = PluginMetadataHelper.getCanonicalName( path ); - if ( pluginManager.getPlugin( canonicalName ) == null ) + int loaded = 0; + for ( final Path path : hierarchy ) { - if ( pluginManager.loadPlugin( canonicalName, path ) ) + // If the plugin hasn't already been started, start it. + final String canonicalName = PluginMetadataHelper.getCanonicalName( path ); + if ( pluginManager.getPlugin( canonicalName ) == null ) { - loaded++; + if ( pluginManager.loadPlugin( canonicalName, path ) ) + { + loaded++; + } } } + + return loaded; } + } ); + } - return loaded; + // Hierarchies could be processed in parallel. This is likely to be beneficial during the first + // execution of this monitor, as during later executions, most plugins will likely already be loaded. + final int parallelProcessMax = JiveGlobals.getIntProperty("plugins.loading.max-parallel", 4); + final int parallelProcessCount = (pluginManager.isExecuted() ? 1 : parallelProcessMax); + final ThreadFactory threadFactory = new NamedThreadFactory("PluginMonitorExec-", Executors.defaultThreadFactory(), false, Thread.NORM_PRIORITY); + final ExecutorService executorService = Executors.newFixedThreadPool(parallelProcessCount, threadFactory); + try { + // Blocks until ready + final List> futures = executorService.invokeAll(parallelProcesses); + + // Unless nothing happened, report that we're done loading plugins. + int pluginsLoaded = 0; + for (Future future : futures) { + pluginsLoaded += future.get(); } - } ); - } - - // Before running any plugin, make sure that the admin plugin is loaded. It is a dependency - // of all plugins that attempt to modify the admin panel. - if ( pluginManager.getPlugin( "admin" ) == null ) - { - pluginManager.loadPlugin( "admin", dirs.getFirst().get( 0 ) ); - } - - // Hierarchies could be processed in parallel. This is likely to be beneficial during the first - // execution of this monitor, as during later executions, most plugins will likely already be loaded. - final int parallelProcessMax = JiveGlobals.getIntProperty( "plugins.loading.max-parallel", 4 ); - final int parallelProcessCount = ( pluginManager.isExecuted() ? 1 : parallelProcessMax ); - final ThreadFactory threadFactory = new NamedThreadFactory("PluginMonitorExec-", Executors.defaultThreadFactory(), false, Thread.NORM_PRIORITY); - final ExecutorService executorService = Executors.newFixedThreadPool( parallelProcessCount, threadFactory ); - try - { - // Blocks until ready - final List> futures = executorService.invokeAll( parallelProcesses ); - - // Unless nothing happened, report that we're done loading plugins. - int pluginsLoaded = 0; - for ( Future future : futures ) - { - pluginsLoaded += future.get(); - } - if ( pluginsLoaded > 0 && !XMPPServer.getInstance().isSetupMode() ) - { - Log.info( "Finished processing all plugins." ); + if (pluginsLoaded > 0) { + Log.info("Finished processing all plugins."); + } + } finally { + executorService.shutdown(); } } - finally - { - executorService.shutdown(); - } // Trigger event that plugins have been monitored pluginManager.firePluginsMonitored();