Permalink
Browse files

Support for resuming idle JVM when using run-app

  • Loading branch information...
1 parent 2a64d42 commit 24326f16221b0a94ea9a483dec149cab3519b879 @graemerocher graemerocher committed Jan 24, 2013
@@ -46,6 +46,13 @@ abstract class ForkedGrailsProcess {
File reloadingAgent
List<String> jvmArgs
ClassLoader forkedClassLoader
+ ExecutionContext executionContext
+
+ private String resumeIndicatorName
+
+ ForkedGrailsProcess() {
+ resumeIndicatorName = "${getClass().simpleName}-process-resume"
+ }
@CompileStatic
void configure(Map forkConfig) {
@@ -85,14 +92,55 @@ abstract class ForkedGrailsProcess {
}
}
+ @CompileStatic
+ protected void waitForResume() {
+ // wait for resume indicator
+ def resumeDir = new File(executionContext.projectWorkDir, resumeIndicatorName)
+ resumeDir.mkdirs()
+ resumeDir.deleteOnExit()
+ startIdleKiller()
+ while (resumeDir.exists()) {
+ sleep(100)
+ }
+ }
+
+ @CompileStatic
+ void killAfterTimeout() {
+ int idleTime = 1 * 60 // one hour
+
+ try {
+ Thread.sleep(idleTime * 60 * 1000) // convert minutes to ms
+ } catch (e) {
+ return;
+ }
+
+ def lockDir = new File(executionContext.projectWorkDir, "process-lock")
+ if (lockDir.mkdir()) {
+ System.exit 0
+ } else {
+ // someone is already connected; let the process finish
+ }
+ }
+
+ @CompileStatic
+ private void startIdleKiller() {
+ def idleKiller = new Thread({
+ killAfterTimeout()
+ } as Runnable)
+
+ idleKiller.daemon = true
+ idleKiller.start()
+ }
+
+
@CompileStatic
Process fork() {
ExecutionContext executionContext = createExecutionContext()
if (reloading) {
discoverAndSetAgent(executionContext)
}
- def resumeDir = new File(executionContext.projectWorkDir, "${getClass().simpleName}-process-resume")
+ def resumeDir = new File(executionContext.projectWorkDir, resumeIndicatorName)
if (forkReserve && resumeDir.exists() && InteractiveMode.isActive()) {
resumeDir.delete()
sleep(100)
@@ -125,6 +173,7 @@ abstract class ForkedGrailsProcess {
}
+ @CompileStatic
protected Process forkReserveProcess(List<String> cmd, ExecutionContext executionContext) {
final p2 = new ProcessBuilder()
.directory(executionContext.getBaseDir())
@@ -135,6 +184,7 @@ abstract class ForkedGrailsProcess {
attachOutputListener(p2, true)
}
+ @CompileStatic
protected Process attachOutputListener(Process process, boolean async = false) {
def is = process.inputStream
def es = process.errorStream
@@ -165,6 +215,7 @@ abstract class ForkedGrailsProcess {
return process
}
+ @CompileStatic
protected String getBoostrapClasspath(ExecutionContext executionContext) {
def cp = new StringBuilder()
for (File file : executionContext.getBuildDependencies()) {
@@ -26,7 +26,6 @@ import groovy.transform.CompileStatic
*/
@CompileStatic
abstract class ForkedGrailsProjectClassExecutor extends ForkedGrailsProcess{
- ExecutionContext executionContext
ForkedGrailsProjectClassExecutor(BuildSettings buildSettings) {
executionContext = new ExecutionContext()
@@ -57,42 +56,11 @@ abstract class ForkedGrailsProjectClassExecutor extends ForkedGrailsProcess{
runInstance(projectClassInstance)
}
else {
- // wait for resume indicator
- def resumeDir = new File(executionContext.projectWorkDir, "${getClass().simpleName}-process-resume")
- resumeDir.mkdirs()
- startIdleKiller()
- while(resumeDir.exists()) {
- sleep(100)
- }
+ waitForResume()
runInstance(projectClassInstance)
}
}
- void killAfterTimeout() {
- int idleTime = 4 * 60 // four hours
-
- try {
- Thread.sleep(idleTime * 60 * 1000) // convert minutes to ms
- } catch (e) {
- return;
- }
-
- def lockDir = new File(executionContext.projectWorkDir, "process-lock")
- if (lockDir.mkdir()) {
- System.exit 0
- } else {
- // someone is already connected; let the process finish
- }
- }
-
- private void startIdleKiller() {
- def idleKiller = new Thread({
- killAfterTimeout()
- } as Runnable)
-
- idleKiller.daemon = true
- idleKiller.start()
- }
protected Object createInstance(Class projectComponentClass, BuildSettings buildSettings) {
projectComponentClass.newInstance(buildSettings)
@@ -15,6 +15,7 @@
*/
package org.grails.plugins.tomcat.fork
+import grails.build.logging.GrailsConsole
import grails.util.BuildSettings
import grails.util.BuildSettingsHolder
import grails.util.Environment
@@ -33,12 +34,13 @@ import org.grails.plugins.tomcat.TomcatKillSwitch
*/
class ForkedTomcatServer extends ForkedGrailsProcess implements EmbeddableServer {
+ public static final GrailsConsole CONSOLE = GrailsConsole.getInstance()
@Delegate EmbeddableServer tomcatRunner
- TomcatExecutionContext executionContext
ForkedTomcatServer(TomcatExecutionContext executionContext) {
this.executionContext = executionContext
+ this.forkReserve = true
}
private ForkedTomcatServer() {
@@ -60,16 +62,28 @@ class ForkedTomcatServer extends ForkedGrailsProcess implements EmbeddableServer
@CompileStatic
def run() {
- TomcatExecutionContext ec = executionContext
+ if (!isReserveProcess()) {
+ runInternal()
+ }
+ else {
+ CONSOLE.verbose("Waiting for resume signal for idle JVM")
+ waitForResume()
+ CONSOLE.verbose("Resuming idle JVM")
+ runInternal()
+ }
+
+ }
+
+ protected void runInternal() {
+ TomcatExecutionContext ec = (TomcatExecutionContext)executionContext
BuildSettings buildSettings = initializeBuildSettings(ec)
URLClassLoader classLoader = initializeClassLoader(buildSettings)
- initializeLogging(ec.grailsHome,classLoader)
+ initializeLogging(ec.grailsHome, classLoader)
tomcatRunner = createTomcatRunner(buildSettings, ec, classLoader)
if (ec.securePort > 0) {
tomcatRunner.startSecure(ec.host, ec.port, ec.securePort)
- }
- else {
+ } else {
tomcatRunner.start(ec.host, ec.port)
}
@@ -108,7 +122,7 @@ class ForkedTomcatServer extends ForkedGrailsProcess implements EmbeddableServer
@CompileStatic
void startSecure(String host, int httpPort, int httpsPort) {
- final ec = executionContext
+ final ec = (TomcatExecutionContext)executionContext
ec.host = host
ec.port = httpPort
ec.securePort = httpsPort
@@ -144,8 +158,9 @@ class ForkedTomcatServer extends ForkedGrailsProcess implements EmbeddableServer
}
void stop() {
+ final ec = (TomcatExecutionContext)executionContext
try {
- new URL("http://${executionContext?.host}:${executionContext?.port + 1}").text
+ new URL("http://${ec?.host}:${executionContext?.ec + 1}").text
} catch(e) {
// ignore
}

0 comments on commit 24326f1

Please sign in to comment.