Skip to content

Commit

Permalink
OF-2606: Prevent surplus DB connection errors during setup (#2189)
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
guusdk authored Jul 21, 2023
1 parent 162a33d commit 94d0d29
Showing 1 changed file with 49 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -350,68 +350,67 @@ public boolean accept( final Path path ) throws IOException
// plugins always precede their children.
final Deque<List<Path>> dirs = sortPluginDirs( ds, devPlugins );

// Hierarchy processing could be parallel.
final Collection<Callable<Integer>> parallelProcesses = new ArrayList<>();
for ( final List<Path> 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<Integer>()
{
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<Callable<Integer>> parallelProcesses = new ArrayList<>();
for ( final List<Path> hierarchy : dirs )
{
parallelProcesses.add( new Callable<Integer>()
{
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<Future<Integer>> futures = executorService.invokeAll(parallelProcesses);

// Unless nothing happened, report that we're done loading plugins.
int pluginsLoaded = 0;
for (Future<Integer> 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<Future<Integer>> futures = executorService.invokeAll( parallelProcesses );

// Unless nothing happened, report that we're done loading plugins.
int pluginsLoaded = 0;
for ( Future<Integer> 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();
Expand Down

0 comments on commit 94d0d29

Please sign in to comment.