19
19
*/
20
20
package org .sonarsource .sonarlint .core .analysis ;
21
21
22
- import java .util .ArrayList ;
23
- import java .util .List ;
24
- import java .util .concurrent .BlockingQueue ;
25
- import java .util .concurrent .CompletableFuture ;
26
- import java .util .concurrent .LinkedBlockingQueue ;
27
22
import java .util .concurrent .atomic .AtomicReference ;
28
23
import javax .annotation .Nullable ;
29
- import org .sonarsource .sonarlint .core .analysis .api .AnalysisEngineConfiguration ;
24
+ import org .sonarsource .sonarlint .core .analysis .api .AnalysisSchedulerConfiguration ;
30
25
import org .sonarsource .sonarlint .core .analysis .command .Command ;
31
26
import org .sonarsource .sonarlint .core .analysis .container .global .GlobalAnalysisContainer ;
32
- import org .sonarsource .sonarlint .core .analysis .container .global .ModuleRegistry ;
33
27
import org .sonarsource .sonarlint .core .commons .log .LogOutput ;
34
28
import org .sonarsource .sonarlint .core .commons .log .SonarLintLogger ;
35
- import org .sonarsource .sonarlint .core .commons .progress .ProgressMonitor ;
36
29
import org .sonarsource .sonarlint .core .plugin .commons .LoadedPlugins ;
37
30
38
- public class AnalysisEngine {
31
+ public class AnalysisScheduler {
39
32
private static final SonarLintLogger LOG = SonarLintLogger .get ();
40
33
private static final Runnable CANCELING_TERMINATION = () -> {
41
34
};
42
35
43
- private final GlobalAnalysisContainer globalAnalysisContainer ;
44
- private final BlockingQueue < AsyncCommand <?>> commandQueue = new LinkedBlockingQueue <> ();
45
- private final Thread analysisThread = new Thread (this ::executeQueuedCommands , "sonarlint-analysis-engine " );
36
+ private final AtomicReference < GlobalAnalysisContainer > globalAnalysisContainer = new AtomicReference <>() ;
37
+ private final AnalysisQueue analysisQueue = new AnalysisQueue ();
38
+ private final Thread analysisThread = new Thread (this ::executeQueuedCommands , "sonarlint-analysis-scheduler " );
46
39
private final LogOutput logOutput ;
47
40
private final AtomicReference <Runnable > termination = new AtomicReference <>();
48
- private final AtomicReference <AsyncCommand <?> > executingCommand = new AtomicReference <>();
41
+ private final AtomicReference <Command > executingCommand = new AtomicReference <>();
49
42
50
- public AnalysisEngine (AnalysisEngineConfiguration analysisGlobalConfig , LoadedPlugins loadedPlugins , @ Nullable LogOutput logOutput ) {
51
- globalAnalysisContainer = new GlobalAnalysisContainer (analysisGlobalConfig , loadedPlugins );
43
+ public AnalysisScheduler (AnalysisSchedulerConfiguration analysisGlobalConfig , LoadedPlugins loadedPlugins , @ Nullable LogOutput logOutput ) {
52
44
this .logOutput = logOutput ;
53
- start ();
54
- }
55
-
56
- private void start () {
57
45
// if the container cannot be started, the thread won't be started
58
- globalAnalysisContainer . startComponents ( );
46
+ startContainer ( analysisGlobalConfig , loadedPlugins );
59
47
analysisThread .start ();
60
48
}
61
49
50
+ public void reset (AnalysisSchedulerConfiguration analysisGlobalConfig , LoadedPlugins loadedPlugins ) {
51
+ // recreate the context
52
+ globalAnalysisContainer .get ().stopComponents ();
53
+ startContainer (analysisGlobalConfig , loadedPlugins );
54
+ analysisQueue .clearAllButAnalyses ();
55
+ }
56
+
57
+ private void startContainer (AnalysisSchedulerConfiguration analysisGlobalConfig , LoadedPlugins loadedPlugins ) {
58
+ globalAnalysisContainer .set (new GlobalAnalysisContainer (analysisGlobalConfig , loadedPlugins ));
59
+ globalAnalysisContainer .get ().startComponents ();
60
+ }
61
+
62
+ public void wakeUp () {
63
+ analysisQueue .wakeUp ();
64
+ }
65
+
62
66
private void executeQueuedCommands () {
63
67
while (termination .get () == null ) {
64
68
SonarLintLogger .get ().setTarget (logOutput );
65
69
try {
66
- executingCommand .set (commandQueue . take ());
70
+ executingCommand .set (analysisQueue . takeNextCommand ());
67
71
if (termination .get () == CANCELING_TERMINATION ) {
68
72
executingCommand .get ().cancel ();
69
73
break ;
70
74
}
71
- executingCommand .get ().execute (getModuleRegistry ());
75
+ executingCommand .get ().execute (globalAnalysisContainer . get (). getModuleRegistry ());
72
76
executingCommand .set (null );
73
77
} catch (InterruptedException e ) {
74
78
if (termination .get () != CANCELING_TERMINATION ) {
@@ -79,23 +83,18 @@ private void executeQueuedCommands() {
79
83
termination .get ().run ();
80
84
}
81
85
82
- public < T > CompletableFuture < T > post (Command < T > command , ProgressMonitor progressMonitor ) {
86
+ public void post (Command command ) {
83
87
if (termination .get () != null ) {
84
88
LOG .error ("Analysis engine stopping, ignoring command" );
85
- return CompletableFuture .completedFuture (null );
89
+ command .cancel ();
90
+ return ;
86
91
}
87
92
if (!analysisThread .isAlive ()) {
88
93
LOG .error ("Analysis engine not started, ignoring command" );
89
- return CompletableFuture .completedFuture (null );
90
- }
91
-
92
- var asyncCommand = new AsyncCommand <>(command , progressMonitor );
93
- try {
94
- commandQueue .put (asyncCommand );
95
- } catch (InterruptedException e ) {
96
- asyncCommand .future .completeExceptionally (e );
94
+ command .cancel ();
95
+ return ;
97
96
}
98
- return asyncCommand . future ;
97
+ analysisQueue . post ( command ) ;
99
98
}
100
99
101
100
public void stop () {
@@ -111,37 +110,7 @@ public void stop() {
111
110
command .cancel ();
112
111
}
113
112
analysisThread .interrupt ();
114
- List <AsyncCommand <?>> pendingCommands = new ArrayList <>();
115
- commandQueue .drainTo (pendingCommands );
116
- pendingCommands .forEach (c -> c .future .cancel (false ));
117
- globalAnalysisContainer .stopComponents ();
118
- }
119
-
120
- private ModuleRegistry getModuleRegistry () {
121
- return globalAnalysisContainer .getModuleRegistry ();
122
- }
123
-
124
- public static class AsyncCommand <T > {
125
- private final CompletableFuture <T > future = new CompletableFuture <>();
126
- private final Command <T > command ;
127
- private final ProgressMonitor progressMonitor ;
128
-
129
- public AsyncCommand (Command <T > command , ProgressMonitor progressMonitor ) {
130
- this .command = command ;
131
- this .progressMonitor = progressMonitor ;
132
- }
133
-
134
- public void execute (ModuleRegistry moduleRegistry ) {
135
- try {
136
- var result = command .execute (moduleRegistry , progressMonitor );
137
- future .complete (result );
138
- } catch (Throwable e ) {
139
- future .completeExceptionally (e );
140
- }
141
- }
142
-
143
- public void cancel () {
144
- progressMonitor .cancel ();
145
- }
113
+ analysisQueue .removeAll ().forEach (Command ::cancel );
114
+ globalAnalysisContainer .get ().stopComponents ();
146
115
}
147
116
}
0 commit comments