From 2335ac375b67ebd74c1dd0aaef317da1f7ea19aa Mon Sep 17 00:00:00 2001 From: Damien Urruty Date: Mon, 17 Feb 2025 14:12:47 +0100 Subject: [PATCH] SLCORE-1180 Avoid multiple known findings store to be created --- .../core/analysis/AnalysisEngineCache.java | 27 +++++++++++-------- .../core/plugin/PluginsRepository.java | 14 +++++----- .../tracking/KnownFindingsStorageService.java | 20 ++++++++------ 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/backend/core/src/main/java/org/sonarsource/sonarlint/core/analysis/AnalysisEngineCache.java b/backend/core/src/main/java/org/sonarsource/sonarlint/core/analysis/AnalysisEngineCache.java index 6a202e89cc..a854bdfbd7 100644 --- a/backend/core/src/main/java/org/sonarsource/sonarlint/core/analysis/AnalysisEngineCache.java +++ b/backend/core/src/main/java/org/sonarsource/sonarlint/core/analysis/AnalysisEngineCache.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import javax.annotation.PreDestroy; @@ -52,7 +53,7 @@ public class AnalysisEngineCache { private final NodeJsService nodeJsService; private final Map extraProperties = new HashMap<>(); private final Path csharpOssPluginPath; - private AnalysisEngine standaloneEngine; + private final AtomicReference standaloneEngine = new AtomicReference<>(); private final Map connectedEnginesByConnectionId = new ConcurrentHashMap<>(); public AnalysisEngineCache(ConfigurationRepository configurationRepository, NodeJsService nodeJsService, InitializeParams initializeParams, UserPaths userPaths, @@ -103,15 +104,17 @@ private synchronized AnalysisEngine getConnectedEngineIfStarted(String connectio } private synchronized AnalysisEngine getOrCreateStandaloneEngine() { - if (standaloneEngine == null) { - standaloneEngine = createEngine(pluginsService.getEmbeddedPlugins(), csharpOssPluginPath); + var engine = standaloneEngine.get(); + if (engine == null) { + engine = createEngine(pluginsService.getEmbeddedPlugins(), csharpOssPluginPath); + standaloneEngine.set(engine); } - return standaloneEngine; + return engine; } @CheckForNull private synchronized AnalysisEngine getStandaloneEngineIfStarted() { - return standaloneEngine; + return standaloneEngine.get(); } private AnalysisEngine createEngine(LoadedPlugins plugins, @Nullable Path actualCsharpAnalyzerPath) { @@ -167,18 +170,20 @@ private synchronized void stopEngineGracefully(String event) { } private synchronized void stopAllGracefully() { - if (this.standaloneEngine != null) { - this.standaloneEngine.finishGracefully(); - this.standaloneEngine = null; + var standaloneAnalysisEngine = this.standaloneEngine.get(); + if (standaloneAnalysisEngine != null) { + standaloneAnalysisEngine.finishGracefully(); + this.standaloneEngine.set(null); } connectedEnginesByConnectionId.forEach((connectionId, engine) -> engine.finishGracefully()); connectedEnginesByConnectionId.clear(); } private synchronized void stopAll() { - if (this.standaloneEngine != null) { - this.standaloneEngine.stop(); - this.standaloneEngine = null; + var standaloneAnalysisEngine = this.standaloneEngine.get(); + if (standaloneAnalysisEngine != null) { + standaloneAnalysisEngine.stop(); + this.standaloneEngine.set(null); } connectedEnginesByConnectionId.forEach((connectionId, engine) -> engine.stop()); connectedEnginesByConnectionId.clear(); diff --git a/backend/core/src/main/java/org/sonarsource/sonarlint/core/plugin/PluginsRepository.java b/backend/core/src/main/java/org/sonarsource/sonarlint/core/plugin/PluginsRepository.java index 32516e937d..c41599da5b 100644 --- a/backend/core/src/main/java/org/sonarsource/sonarlint/core/plugin/PluginsRepository.java +++ b/backend/core/src/main/java/org/sonarsource/sonarlint/core/plugin/PluginsRepository.java @@ -25,6 +25,7 @@ import java.util.LinkedList; import java.util.Map; import java.util.Queue; +import java.util.concurrent.atomic.AtomicReference; import javax.annotation.CheckForNull; import org.sonarsource.sonarlint.core.plugin.commons.LoadedPlugins; @@ -32,16 +33,16 @@ import static org.sonarsource.sonarlint.core.commons.IOExceptionUtils.tryAndCollectIOException; public class PluginsRepository { - private LoadedPlugins loadedEmbeddedPlugins; + private final AtomicReference loadedEmbeddedPlugins = new AtomicReference<>(); private final Map loadedPluginsByConnectionId = new HashMap<>(); public void setLoadedEmbeddedPlugins(LoadedPlugins loadedEmbeddedPlugins) { - this.loadedEmbeddedPlugins = loadedEmbeddedPlugins; + this.loadedEmbeddedPlugins.set(loadedEmbeddedPlugins); } @CheckForNull public LoadedPlugins getLoadedEmbeddedPlugins() { - return loadedEmbeddedPlugins; + return loadedEmbeddedPlugins.get(); } @CheckForNull @@ -56,9 +57,10 @@ public void setLoadedPlugins(String connectionId, LoadedPlugins loadedPlugins) { @PreDestroy public void unloadAllPlugins() throws IOException { Queue exceptions = new LinkedList<>(); - if (loadedEmbeddedPlugins != null) { - tryAndCollectIOException(loadedEmbeddedPlugins::close, exceptions); - loadedEmbeddedPlugins = null; + var embeddedPlugins = loadedEmbeddedPlugins.get(); + if (embeddedPlugins != null) { + tryAndCollectIOException(embeddedPlugins::close, exceptions); + loadedEmbeddedPlugins.set(null); } synchronized (loadedPluginsByConnectionId) { loadedPluginsByConnectionId.values().forEach(l -> tryAndCollectIOException(l::close, exceptions)); diff --git a/backend/core/src/main/java/org/sonarsource/sonarlint/core/tracking/KnownFindingsStorageService.java b/backend/core/src/main/java/org/sonarsource/sonarlint/core/tracking/KnownFindingsStorageService.java index 242f945741..89991fd84d 100644 --- a/backend/core/src/main/java/org/sonarsource/sonarlint/core/tracking/KnownFindingsStorageService.java +++ b/backend/core/src/main/java/org/sonarsource/sonarlint/core/tracking/KnownFindingsStorageService.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.concurrent.atomic.AtomicReference; import javax.annotation.PreDestroy; import org.sonarsource.sonarlint.core.UserPaths; @@ -28,29 +29,32 @@ public class KnownFindingsStorageService { private final Path projectsStorageBaseDir; private final Path workDir; - private XodusKnownFindingsStore trackedIssuesStore; + private final AtomicReference trackedIssuesStore = new AtomicReference<>(); public KnownFindingsStorageService(UserPaths userPaths) { this.projectsStorageBaseDir = userPaths.getStorageRoot(); this.workDir = userPaths.getWorkDir(); } - public XodusKnownFindingsStore get() { - if (trackedIssuesStore == null) { + public synchronized XodusKnownFindingsStore get() { + var store = trackedIssuesStore.get(); + if (store == null) { try { - trackedIssuesStore = new XodusKnownFindingsStore(projectsStorageBaseDir, workDir); - return trackedIssuesStore; + store = new XodusKnownFindingsStore(projectsStorageBaseDir, workDir); + trackedIssuesStore.set(store); + return store; } catch (IOException e) { throw new IllegalStateException("Unable to create tracked issues database", e); } } - return trackedIssuesStore; + return store; } @PreDestroy public void close() { - if (trackedIssuesStore != null) { - trackedIssuesStore.close(); + var store = trackedIssuesStore.get(); + if (store != null) { + store.close(); } }