Detect, Option to Forcibly Terminate AsterixDB Processes (Windows)

Port of https://asterix-gerrit.ics.uci.edu/#/c/1316/ to Windows

Change-Id: I1daf8e629f62d933a4bb672d7bc7532d60b67bf6
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1328
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-server/src/main/samples/local/bin/start-sample-cluster.bat b/asterixdb/asterix-server/src/main/samples/local/bin/start-sample-cluster.bat
index 589d55e..580e1e0 100644
--- a/asterixdb/asterix-server/src/main/samples/local/bin/start-sample-cluster.bat
+++ b/asterixdb/asterix-server/src/main/samples/local/bin/start-sample-cluster.bat
@@ -19,6 +19,39 @@
 
 @echo off
 setlocal
+goto opts
+
+:usage
+echo.
+echo Usage: %~nx0 [-f[orce]]
+echo.
+echo   -f[orce]  : Forces a start attempt when ${PRODUCT} processes are found to be running
+exit /B 0
+
+:opts
+if "%1" == "" goto postopts
+
+if "%1" == "-f" (
+  set force=1
+) else if "%1" == "-force" (
+  set force=1
+) else if "%1" == "-usage" (
+  goto :usage
+) else if "%1" == "-help" (
+  goto :usage
+) else if "%1" == "--help" (
+  goto :usage
+) else if "%1" == "--usage" (
+  goto :usage
+) else (
+  echo ERROR: unknown argument '%1'
+  call :usage
+  exit /B 1
+)
+shift
+goto opts
+:postopts
+
 if NOT DEFINED JAVA_HOME (
   echo ERROR: JAVA_HOME not defined
   goto :ERROR
@@ -55,11 +88,46 @@
   echo ERROR: sample cluster address [localhost:${LISTEN_PORT}] already in use
   goto :ERROR
 )
+set tempfile="%TEMP%\start-sample-cluster-%random%"
 
-REM TODO(mblow): append timestamp to logs when starting
+wmic process where ^
+  "name='java.exe' and CommandLine like '%%org.codehaus.mojo.appassembler.booter.AppassemblerBooter%%' and (CommandLine like '%%app.name=\"%%[cn]c\"%%' or CommandLine like '%%app.name=\"%%ncservice\"%%')" ^
+  GET processid > %tempfile% 2>/dev/null
 
+set severity=ERROR
+if "%force%" == "1" set severity=WARNING
+
+for /F "skip=1" %%P in ('type %tempfile%') DO set found=1
+
+if "%found%" == "1" (
+  if "%force%" == "1" (
+    echo %severity%: ${PRODUCT} processes are already running; -f[orce] specified, ignoring
+    del %tempfile%
+ ) else (
+    echo %severity%: ${PRODUCT} processes are already running; aborting"
+    echo.
+    echo Re-run with -f to ignore, or run stop-sample-cluster.bat -f to forcibly terminate all running ${PRODUCT} processes:
+    for /F "skip=1" %%P in ('type %tempfile%') DO @echo     - %%P
+    del %tempfile%
+    exit /B 1
+  )
+)
+
+goto :post_timestamp
+
+:timestamp
+if "%1" == "" exit /B 0
+echo "--------------------------" >> %1
+echo "%date% %time%" >> %1
+echo "--------------------------" >> %1
+shift
+goto :timestamp
+
+:post_timestamp
 echo Starting sample cluster...
 
+call :timestamp %LOGSDIR%\blue-service.log %LOGSDIR%\red-service.log %LOGSDIR%\cc.log
+
 start /MIN "blue-nc" cmd /c "echo See output in %LOGSDIR%\blue-service.log && %INSTALLDIR%\bin\${NC_SERVICE_COMMAND} -logdir - -config-file %CLUSTERDIR%\conf\blue.conf >> %LOGSDIR%\blue-service.log 2>&1"
 start /MIN "red-nc" cmd /c "echo See output in %LOGSDIR%\red-service.log && %INSTALLDIR%\bin\${NC_SERVICE_COMMAND} -logdir - >> %LOGSDIR%\red-service.log 2>&1"
 start /MIN "cc" cmd /c "echo See output in %LOGSDIR%\cc.log && %INSTALLDIR%\bin\${CC_COMMAND} -config-file %CLUSTERDIR%\conf\cc.conf >>%LOGSDIR%\cc.log 2>&1"
diff --git a/asterixdb/asterix-server/src/main/samples/local/bin/stop-sample-cluster.bat b/asterixdb/asterix-server/src/main/samples/local/bin/stop-sample-cluster.bat
index 8e35c5f..0971065 100644
--- a/asterixdb/asterix-server/src/main/samples/local/bin/stop-sample-cluster.bat
+++ b/asterixdb/asterix-server/src/main/samples/local/bin/stop-sample-cluster.bat
@@ -18,6 +18,46 @@
 @REM ------------------------------------------------------------
 @echo off
 setlocal
+
+goto opts
+
+:usage
+echo.
+echo Usage: %~nx0 [-f[orce]]
+echo.
+echo   -f[orce]  : Forcibly terminates any running ${PRODUCT} processes (after shutting down cluster, if running)
+exit /B 0
+
+:kill
+echo    Killing %1...
+TASKKILL /F /PID %1
+echo    %1...killed
+exit /B 0
+
+:opts
+if "%1" == "" goto postopts
+
+if "%1" == "-f" (
+  set force=1
+) else if "%1" == "-force" (
+  set force=1
+) else if "%1" == "-usage" (
+  goto :usage
+) else if "%1" == "-help" (
+  goto :usage
+) else if "%1" == "--help" (
+  goto :usage
+) else if "%1" == "--usage" (
+  goto :usage
+) else (
+  echo ERROR: unknown argument '%1'
+  call :usage
+  exit /B 1
+)
+shift
+goto opts
+:postopts
+
 if NOT DEFINED JAVA_HOME (
   echo ERROR: JAVA_HOME not defined
   goto :ERROR
@@ -36,22 +76,55 @@
 cd %CLUSTERDIR%\..\..
 set INSTALLDIR=%cd%
 
+set tempfile="%TEMP%\stop-sample-cluster-%random%"
+
 call %INSTALLDIR%\bin\${HELPER_COMMAND} get_cluster_state -quiet
-if %ERRORLEVEL% NEQ 1 (
-  call %INSTALLDIR%\bin\${HELPER_COMMAND} shutdown_cluster_all
-) else (
-  echo WARNING: sample cluster does not appear to be running, will attempt to wait for
-  echo          CCDriver to terminate if running.
+if %ERRORLEVEL% EQU 1 (
+  echo WARNING: sample cluster does not appear to be running
+  goto :post_shutdown
 )
+call %INSTALLDIR%\bin\${HELPER_COMMAND} shutdown_cluster_all
+echo INFO: Waiting up for cluster to shutdown...
+
+set tries=0
+:wait_loop
+set /A tries=%tries% + 1
+if "%tries%" == "60" goto :post_shutdown
+wmic process where ^
+  "name='java.exe' and CommandLine like '%%org.codehaus.mojo.appassembler.booter.AppassemblerBooter%%' and CommandLine like '%%app.name=\"%%cc\"%%'" ^
+  GET processid >%tempfile% 2>/dev/null
+
+set found=
+for /F "skip=1" %%P in ('type %tempfile%') DO set found=1
+if "%found%" == "1" (
+  timeout /T 1 /NOBREAK >/dev/null
+  goto :wait_loop
+)
+:post_shutdown
 echo.
-powershell "Write-Host "Waiting for CCDriver to terminate..." -nonewline; do { if ($running) { Start-Sleep 1 }; %JAVA_HOME%\bin\jps.exe -v | select-string -pattern ${CC_COMMAND} -quiet -outvariable running | Out-Null; Write-Host "." -nonewline } while ($running)"
-echo .done.
+
+wmic process where ^
+  "name='java.exe' and CommandLine like '%%org.codehaus.mojo.appassembler.booter.AppassemblerBooter%%' and (CommandLine like '%%app.name=\"%%[cn]c\"%%' or CommandLine like '%%app.name=\"%%ncservice\"%%')" ^
+  GET processid > %tempfile% 2>/dev/null
+
+set found=
+for /F "skip=1" %%P in ('type %tempfile%') DO set found=1
+
+if "%found%" == "1" (
+  if "%force%" == "1" (
+    echo WARNING: ${PRODUCT} processes remain after cluster shutdown; -f[orce] specified, forcibly terminating ${PRODUCT} processes:
+    for /F "skip=1" %%P in ('type %tempfile%') DO call :kill %%P
+  ) else (
+    echo WARNING: ${PRODUCT} processes remain after cluster shutdown; re-run with -f[orce] to forcibly terminate all ${PRODUCT} processes:
+    for /F "skip=1" %%P in ('type %tempfile%') DO @echo     - %%P
+  )
+)
+del %tempfile%
+
 goto :END
 :ERROR
-echo.
 popd
 exit /B 1
 
 :END
-echo.
 popd