mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
shutdown server if IDE crashed
This commit is contained in:
@@ -35,6 +35,7 @@ message Message {
|
||||
RELOAD_PROJECT_COMMAND = 4;
|
||||
FS_EVENT = 5;
|
||||
CANCEL_BUILD_COMMAND = 6;
|
||||
PING = 7;
|
||||
}
|
||||
|
||||
message CompilationRequest {
|
||||
|
||||
@@ -10,4 +10,6 @@ public interface GlobalOptions {
|
||||
String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process";
|
||||
String HOSTNAME_OPTION = "localhost.name";
|
||||
String VM_EXE_PATH_OPTION = "vm.executable.path";
|
||||
|
||||
long SERVER_PING_PERIOD = 2000L; // 2 sec
|
||||
}
|
||||
|
||||
@@ -1019,6 +1019,7 @@ public final class JpsRemoteProto {
|
||||
RELOAD_PROJECT_COMMAND(3, 4),
|
||||
FS_EVENT(4, 5),
|
||||
CANCEL_BUILD_COMMAND(5, 6),
|
||||
PING(6, 7),
|
||||
;
|
||||
|
||||
|
||||
@@ -1032,6 +1033,7 @@ public final class JpsRemoteProto {
|
||||
case 4: return RELOAD_PROJECT_COMMAND;
|
||||
case 5: return FS_EVENT;
|
||||
case 6: return CANCEL_BUILD_COMMAND;
|
||||
case 7: return PING;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +116,10 @@ public class ProtoUtil {
|
||||
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.FS_EVENT).setFsEvent(builder.build()).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createPingRequest() {
|
||||
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.PING).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createSetupRequest(final Map<String, String> pathVars, List<GlobalLibrary> sdkAndLibs, @Nullable String globalEncoding) {
|
||||
final JpsRemoteProto.Message.Request.SetupCommand.Builder cmdBuilder = JpsRemoteProto.Message.Request.SetupCommand.newBuilder();
|
||||
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
package org.jetbrains.jps.client;
|
||||
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.api.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/11/11
|
||||
*/
|
||||
public class CompileServerClient extends SimpleProtobufClient<JpsServerResponseHandler> {
|
||||
private static final ScheduledThreadPoolExecutor ourPingService = ConcurrencyUtil.newSingleScheduledThreadExecutor("Compile server ping thread", Thread.MIN_PRIORITY);
|
||||
private volatile ScheduledFuture<?> myPingFuture;
|
||||
|
||||
public CompileServerClient() {
|
||||
super(JpsRemoteProto.Message.getDefaultInstance(), new UUIDGetter() {
|
||||
@@ -81,4 +87,22 @@ public class CompileServerClient extends SimpleProtobufClient<JpsServerResponseH
|
||||
return sendMessage(sessionUUID, ProtoUtil.toMessage(sessionUUID, request), handler, cancelAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConnect() {
|
||||
myPingFuture = ourPingService.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendRequest(ProtoUtil.createPingRequest(), null);
|
||||
}
|
||||
}, GlobalOptions.SERVER_PING_PERIOD, GlobalOptions.SERVER_PING_PERIOD, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDisconnect() {
|
||||
final ScheduledFuture<?> future = myPingFuture;
|
||||
if (future != null) {
|
||||
future.cancel(true);
|
||||
myPingFuture = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jps.client;
|
||||
|
||||
import com.google.protobuf.MessageLite;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.*;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
@@ -21,6 +22,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
* Date: 1/22/12
|
||||
*/
|
||||
public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.client.SimpleProtobufClient");
|
||||
private static enum State {
|
||||
DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING
|
||||
}
|
||||
@@ -69,6 +71,12 @@ public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
|
||||
|
||||
if (success) {
|
||||
myConnectFuture = future;
|
||||
try {
|
||||
onConnect();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final Throwable reason = future.getCause();
|
||||
@@ -87,6 +95,11 @@ public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onConnect() {
|
||||
}
|
||||
protected void onDisconnect() {
|
||||
}
|
||||
|
||||
public final void disconnect() {
|
||||
if (myState.compareAndSet(State.CONNECTED, State.DISCONNECTING)) {
|
||||
try {
|
||||
@@ -104,6 +117,12 @@ public class SimpleProtobufClient<T extends ProtobufResponseHandler> {
|
||||
finally {
|
||||
myConnectFuture = null;
|
||||
myState.compareAndSet(State.DISCONNECTING, State.DISCONNECTED);
|
||||
try {
|
||||
onDisconnect();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.jetbrains.jps.server;
|
||||
|
||||
//import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.xml.DOMConfigurator;
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
@@ -24,6 +25,8 @@ import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -40,10 +43,13 @@ public class Server {
|
||||
private final ChannelFactory myChannelFactory;
|
||||
private final ChannelPipelineFactory myPipelineFactory;
|
||||
private final ExecutorService myBuildsExecutor;
|
||||
private volatile long myLastPingTime = -1L;
|
||||
private final ScheduledExecutorService myScheduler;
|
||||
|
||||
public Server(File systemDir) {
|
||||
Paths.getInstance().setSystemRoot(systemDir);
|
||||
final ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
myScheduler = ConcurrencyUtil.newSingleScheduledThreadExecutor("Client activity checker", Thread.MIN_PRIORITY);
|
||||
myBuildsExecutor = Executors.newFixedThreadPool(MAX_SIMULTANEOUS_BUILD_SESSIONS);
|
||||
myChannelFactory = new NioServerSocketChannelFactory(threadPool, threadPool, 1);
|
||||
final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
|
||||
@@ -69,10 +75,53 @@ public class Server {
|
||||
bootstrap.setOption("child.keepAlive", true);
|
||||
final Channel serverChannel = bootstrap.bind(new InetSocketAddress(listenPort));
|
||||
myAllOpenChannels.add(serverChannel);
|
||||
|
||||
startIdleMonitor();
|
||||
}
|
||||
|
||||
private void startIdleMonitor() {
|
||||
final long allowedIdlePeriod = 2 * GlobalOptions.SERVER_PING_PERIOD;
|
||||
myScheduler.scheduleAtFixedRate(new Runnable() {
|
||||
private long myStartTime;
|
||||
@Override
|
||||
public void run() {
|
||||
final long now = System.currentTimeMillis();
|
||||
final long lastPing = myLastPingTime;
|
||||
if (lastPing > 0L) {
|
||||
final long elapsed = now - lastPing;
|
||||
if (elapsed > allowedIdlePeriod) {
|
||||
doStop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
final long start = myStartTime;
|
||||
if (start > 0) {
|
||||
final long elapsed = now - start;
|
||||
if (elapsed > 5 * GlobalOptions.SERVER_PING_PERIOD) {
|
||||
// no pings received since start
|
||||
doStop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
myStartTime = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doStop() {
|
||||
try {
|
||||
stop();
|
||||
}
|
||||
finally {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}, allowedIdlePeriod, allowedIdlePeriod, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
myScheduler.shutdownNow();
|
||||
myBuildsExecutor.shutdownNow();
|
||||
final ChannelGroupFuture closeFuture = myAllOpenChannels.close();
|
||||
closeFuture.awaitUninterruptibly();
|
||||
@@ -82,6 +131,10 @@ public class Server {
|
||||
}
|
||||
}
|
||||
|
||||
public void pingReceived() {
|
||||
myLastPingTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
int port = DEFAULT_SERVER_PORT;
|
||||
|
||||
@@ -138,6 +138,9 @@ class ServerMessageHandler extends SimpleChannelHandler {
|
||||
}
|
||||
reply = ProtoUtil.toMessage(sessionId, ProtoUtil.createCommandCompletedEvent(null));
|
||||
break;
|
||||
case PING:
|
||||
myServer.pingReceived();
|
||||
reply = ProtoUtil.toMessage(sessionId, ProtoUtil.createCommandCompletedEvent(null));
|
||||
default:
|
||||
reply = ProtoUtil.toMessage(sessionId, ProtoUtil.createFailure("Unknown request: " + message));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user