diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java index 1bdde25fc857..066d54c07dff 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java @@ -91,7 +91,7 @@ public class CompileServerManager implements ApplicationComponent{ private static final String COMPILE_SERVER_SYSTEM_ROOT = "compile-server"; private static final String LOGGER_CONFIG = "log.xml"; private static final String DEFAULT_LOGGER_CONFIG = "defaultLogConfig.xml"; - private volatile ServerWrapper myProcessHandler; + private volatile OSProcessHandler myProcessHandler; private final File mySystemDirectory; @Nullable private volatile CompileServerClient myClient; @@ -335,7 +335,7 @@ public class CompileServerManager implements ApplicationComponent{ public RequestFuture submitCompilationTask(final Project project, final boolean isRebuild, final boolean isMake, final Collection modules, final Collection artifacts, final Collection paths, - final Map _userData, final JpsServerResponseHandler handler) { + final Map userData, final JpsServerResponseHandler handler) { final String projectId = getProjectPath(project); final Ref futureRef = new Ref(null); final RunnableFuture future = myTaskExecutor.submit(new Runnable() { @@ -344,16 +344,9 @@ public class CompileServerManager implements ApplicationComponent{ try { final CompileServerClient client = ensureServerRunningAndClientConnected(true); if (client != null) { - final Map userData = new LinkedHashMap(); - if (!isRebuild) { //todo pass user data on rebuild as well? - userData.putAll(_userData); - } - if (Registry.is("compiler.server.use.external.javac.process")) { - userData.put(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION, "true"); - } final RequestFuture requestFuture = isRebuild ? - client.sendRebuildRequest(projectId, handler, userData) : - client.sendCompileRequest(isMake, projectId, modules, artifacts, paths, userData, handler); + client.sendRebuildRequest(projectId, handler, userData) : + client.sendCompileRequest(isMake, projectId, modules, artifacts, paths, userData, handler); futureRef.set(requestFuture); } else { @@ -397,9 +390,9 @@ public class CompileServerManager implements ApplicationComponent{ // executed in one thread at a time @Nullable private CompileServerClient ensureServerRunningAndClientConnected(boolean forceRestart) throws Throwable { - final ServerWrapper ph = myProcessHandler; + final OSProcessHandler ph = myProcessHandler; final CompileServerClient cl = myClient; - final boolean processNotRunning = ph == null || ph.isDead(); + final boolean processNotRunning = ph == null || ph.isProcessTerminated() || ph.isProcessTerminating(); final boolean clientNotConnected = cl == null || !cl.isConnected(); if (processNotRunning || clientNotConnected) { @@ -412,13 +405,68 @@ public class CompileServerManager implements ApplicationComponent{ return null; } - final File workDirectory = new File(mySystemDirectory, COMPILE_SERVER_SYSTEM_ROOT); - workDirectory.mkdirs(); - ensureLogConfigExists(workDirectory); - final int port = NetUtils.findAvailableSocketPort(); - final long serverPingInterval = Registry.intValue("compiler.server.ping.interval", -1) * 1000L; - ServerWrapper wrapper = Registry.is("compiler.server.in.process") ? launchServerThread(workDirectory, port) : launchServerProcess(port, serverPingInterval, workDirectory); + final long serverPingInterval = Registry.intValue("compiler.server.ping.interval", -1) * 1000L; + final Process process = launchServer(port, serverPingInterval); + + final OSProcessHandler processHandler = new OSProcessHandler(process, null) { + @Override + protected boolean shouldDestroyProcessRecursively() { + return true; + } + }; + final StringBuilder serverStartMessage = new StringBuilder(); + final Semaphore semaphore = new Semaphore(); + semaphore.down(); + processHandler.addProcessListener(new ProcessAdapter() { + @Override + public void onTextAvailable(ProcessEvent event, Key outputType) { + // re-translate server's output to idea.log + final String text = event.getText(); + if (!StringUtil.isEmpty(text)) { + LOG.info("COMPILE_SERVER [" +outputType.toString() +"]: "+ text.trim()); + } + } + }); + processHandler.addProcessListener(new ProcessAdapter() { + @Override + public void processTerminated(ProcessEvent event) { + try { + processHandler.removeProcessListener(this); + } + finally { + semaphore.up(); + } + } + + @Override + public void onTextAvailable(ProcessEvent event, Key outputType) { + if (outputType == ProcessOutputTypes.STDERR) { + try { + final String text = event.getText(); + if (text != null) { + if (text.contains(Server.SERVER_SUCCESS_START_MESSAGE) || text.contains(Server.SERVER_ERROR_START_MESSAGE)) { + processHandler.removeProcessListener(this); + } + if (serverStartMessage.length() > 0) { + serverStartMessage.append("\n"); + } + serverStartMessage.append(text); + } + } + finally { + semaphore.up(); + } + } + } + }); + processHandler.startNotify(); + semaphore.waitFor(); + + final String startupMsg = serverStartMessage.toString(); + if (!startupMsg.contains(Server.SERVER_SUCCESS_START_MESSAGE)) { + throw new Exception("Server startup failed: " + startupMsg); + } CompileServerClient client = new CompileServerClient(serverPingInterval, myAsyncExec); boolean connected = false; @@ -427,90 +475,19 @@ public class CompileServerManager implements ApplicationComponent{ if (connected) { final RequestFuture setupFuture = sendSetupRequest(client); setupFuture.waitFor(); - myProcessHandler = wrapper; + myProcessHandler = processHandler; myClient = client; } } finally { if (!connected) { - shutdownServer(cl, wrapper); + shutdownServer(cl, processHandler); } } } return myClient; } - private static ServerWrapper launchServerThread(final File workDirectory, final int port) { - final Server server = new Server(workDirectory, Registry.is("compiler.server.use.memory.temp.cache")); - //todo hostname - server.start(port); - return new ServerWrapper(null, server); - } - - private ServerWrapper launchServerProcess(int port, long serverPingInterval, File workDirectory) throws Exception { - final Process process = launchServer(port, serverPingInterval, workDirectory); - - final OSProcessHandler processHandler = new OSProcessHandler(process, null) { - @Override - protected boolean shouldDestroyProcessRecursively() { - return true; - } - }; - final StringBuilder serverStartMessage = new StringBuilder(); - final Semaphore semaphore = new Semaphore(); - semaphore.down(); - processHandler.addProcessListener(new ProcessAdapter() { - @Override - public void onTextAvailable(ProcessEvent event, Key outputType) { - // re-translate server's output to idea.log - final String text = event.getText(); - if (!StringUtil.isEmpty(text)) { - LOG.info("COMPILE_SERVER [" +outputType.toString() +"]: "+ text.trim()); - } - } - }); - processHandler.addProcessListener(new ProcessAdapter() { - @Override - public void processTerminated(ProcessEvent event) { - try { - processHandler.removeProcessListener(this); - } - finally { - semaphore.up(); - } - } - - @Override - public void onTextAvailable(ProcessEvent event, Key outputType) { - if (outputType == ProcessOutputTypes.STDERR) { - try { - final String text = event.getText(); - if (text != null) { - if (text.contains(Server.SERVER_SUCCESS_START_MESSAGE) || text.contains(Server.SERVER_ERROR_START_MESSAGE)) { - processHandler.removeProcessListener(this); - } - if (serverStartMessage.length() > 0) { - serverStartMessage.append("\n"); - } - serverStartMessage.append(text); - } - } - finally { - semaphore.up(); - } - } - } - }); - processHandler.startNotify(); - semaphore.waitFor(); - - final String startupMsg = serverStartMessage.toString(); - if (!startupMsg.contains(Server.SERVER_SUCCESS_START_MESSAGE)) { - throw new Exception("Server startup failed: " + startupMsg); - } - return new ServerWrapper(processHandler, null); - } - private static RequestFuture sendSetupRequest(final @NotNull CompileServerClient client) throws Exception { final Map data = new HashMap(); @@ -593,7 +570,7 @@ public class CompileServerManager implements ApplicationComponent{ // commandLine.add((launcherUsed? "-J" : "") + "-D" + CharsetToolkit.FILE_ENCODING_PROPERTY + "=" + CharsetToolkit.getDefaultSystemCharset().name()); //} - private Process launchServer(final int port, long pingInterval, File workDirectory) throws ExecutionException { + private Process launchServer(final int port, long pingInterval) throws ExecutionException { // validate tools.jar presence final JavaCompiler systemCompiler = ToolProvider.getSystemJavaCompiler(); if (systemCompiler == null) { @@ -642,6 +619,9 @@ public class CompileServerManager implements ApplicationComponent{ if (Registry.is("compiler.server.use.memory.temp.cache")) { cmdLine.addParameter("-D"+ GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION + "=true"); } + if (Registry.is("compiler.server.use.external.javac.process")) { + cmdLine.addParameter("-D"+ GlobalOptions.USE_EXTERNAL_JAVAC_OPTION + "=true"); + } cmdLine.addParameter("-D"+ GlobalOptions.HOSTNAME_OPTION + "=" + NetUtils.getLocalHostString()); // javac's VM should use the same default locale that IDEA uses in order for javac to print messages in 'correct' language @@ -672,6 +652,10 @@ public class CompileServerManager implements ApplicationComponent{ cmdLine.addParameter(org.jetbrains.jps.server.Server.class.getName()); cmdLine.addParameter(Integer.toString(port)); + final File workDirectory = new File(mySystemDirectory, COMPILE_SERVER_SYSTEM_ROOT); + workDirectory.mkdirs(); + ensureLogConfigExists(workDirectory); + cmdLine.addParameter(FileUtil.toSystemIndependentName(workDirectory.getPath())); cmdLine.setWorkDirectory(workDirectory); @@ -711,7 +695,7 @@ public class CompileServerManager implements ApplicationComponent{ shutdownServer(myClient, myProcessHandler); } - private static void shutdownServer(final CompileServerClient client, final ServerWrapper processHandler) { + private static void shutdownServer(final CompileServerClient client, final OSProcessHandler processHandler) { try { if (client != null && client.isConnected()) { final Future future = client.sendShutdownRequest(); @@ -884,28 +868,4 @@ public class CompileServerManager implements ApplicationComponent{ } } } - - private static class ServerWrapper { - final @Nullable OSProcessHandler myHandler; - final @Nullable Server myServer; - - ServerWrapper(OSProcessHandler handler, Server server) { - myHandler = handler; - myServer = server; - } - - public void destroyProcess() { - if (myHandler != null) { - myHandler.destroyProcess(); - } else if (myServer != null) { - myServer.stop(); - } - } - - public boolean isDead() { - return myHandler != null && (myHandler.isProcessTerminated() || myHandler.isProcessTerminating()) || - myServer != null && myServer.isStopped(); - } - } } - diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index a84911754c50..4eb3dfa3f5ac 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -7,13 +7,13 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.io.MappingFailedException; import com.intellij.util.io.PersistentEnumerator; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.*; import org.jetbrains.jps.api.CanceledStatus; import org.jetbrains.jps.api.GlobalOptions; import org.jetbrains.jps.api.RequestFuture; import org.jetbrains.jps.api.SharedThreadPool; import org.jetbrains.jps.incremental.java.ExternalJavacDescriptor; +import org.jetbrains.jps.incremental.java.JavaBuilder; import org.jetbrains.jps.incremental.java.JavaBuilderLogger; import org.jetbrains.jps.incremental.messages.BuildMessage; import org.jetbrains.jps.incremental.messages.CompilerMessage; @@ -164,7 +164,7 @@ public class IncProjectBuilder { return context; } - private static void flushContext(@Nullable CompileContext context) { + private static void flushContext(CompileContext context) { if (context != null) { context.getTimestampStorage().force(); context.getDataManager().flush(false); @@ -181,16 +181,14 @@ public class IncProjectBuilder { } ExternalJavacDescriptor.KEY.set(context, null); } - if (context == null || context.getBuilderParameter(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null) { - cleanupJavacNameTable(); - } + cleanupJavacNameTable(); } private static boolean ourClenupFailed = false; private static void cleanupJavacNameTable() { try { - if (!ourClenupFailed) { + if (JavaBuilder.USE_EMBEDDED_JAVAC && !ourClenupFailed) { final Field freelistField = Class.forName("com.sun.tools.javac.util.Name$Table").getDeclaredField("freelist"); freelistField.setAccessible(true); freelistField.set(null, com.sun.tools.javac.util.List.nil()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 14e158ff66a4..64d96061c30c 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -56,6 +56,7 @@ public class JavaBuilder extends ModuleLevelBuilder { private static final String FORMS_BUILDER_NAME = "forms"; private static final String JAVA_EXTENSION = ".java"; private static final String FORM_EXTENSION = ".form"; + public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null; public static final FileFilter JAVA_SOURCES_FILTER = new FileFilter() { public boolean accept(File file) { @@ -385,7 +386,7 @@ public class JavaBuilder extends ModuleLevelBuilder { final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink); try { final boolean rc; - if (context.getBuilderParameter(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null) { + if (USE_EMBEDDED_JAVAC) { rc = JavacMain.compile( options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, context.getCancelStatus() ); diff --git a/jps/jps-builders/src/org/jetbrains/jps/server/Server.java b/jps/jps-builders/src/org/jetbrains/jps/server/Server.java index baacea57e79d..1bb5387910b2 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/server/Server.java +++ b/jps/jps-builders/src/org/jetbrains/jps/server/Server.java @@ -70,7 +70,7 @@ public class Server { private final ScheduledExecutorService myScheduler; private final ServerMessageHandler myMessageHandler; - public Server(File systemDir, boolean cachesInMemory) { + public Server(File systemDir) { Utils.setSystemRoot(systemDir); final ExecutorService threadPool = Executors.newCachedThreadPool(); myScheduler = ConcurrencyUtil.newSingleScheduledThreadExecutor("Client activity checker", Thread.MIN_PRIORITY); @@ -105,17 +105,6 @@ public class Server { ); } }; - ServerState.getInstance().setKeepTempCachesInMemory(cachesInMemory); - Runtime.getRuntime().addShutdownHook(new Thread("Shutdown hook thread") { - public void run() { - try { - myMessageHandler.cancelAllBuildsAndClearState(); - } - finally { - Server.this.stop(); - } - } - }); } public void start(int listenPort) { @@ -192,10 +181,6 @@ public class Server { myLastPingTime = System.currentTimeMillis(); } - public boolean isStopped() { - return myScheduler.isShutdown(); - } - public static void main(String[] args) { try { int port = DEFAULT_SERVER_PORT; @@ -212,10 +197,21 @@ public class Server { systemDir = new File(args[1]); } - final Server server = new Server(systemDir, System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION) != null); + final Server server = new Server(systemDir); + Runtime.getRuntime().addShutdownHook(new Thread("Shutdown hook thread") { + public void run() { + try { + server.myMessageHandler.cancelAllBuildsAndClearState(); + } + finally { + server.stop(); + } + } + }); initLoggers(); server.start(port); + ServerState.getInstance().setKeepTempCachesInMemory(System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION) != null); System.out.println("Server classpath: " + System.getProperty("java.class.path")); System.err.println(SERVER_SUCCESS_START_MESSAGE + port); diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index ae842e42edca..00a592aaff6a 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -151,9 +151,6 @@ compiler.server.use.external.javac.process.description=Run javac compiler in ext compiler.server.ping.interval=5 compiler.server.ping.interval.description=Interval in seconds between ping requests the IDE periodically sends to server. If server does not receive pings for some time, it shuts down. Specify -1 to disable this feature. -compiler.server.in.process=false -compiler.server.in.process.description=Launch compiler server in IDEA process - compiler.server.debug.port=-1 #compiler.server.javac.debug.port=-1