42 if (self::$serviceMap ===
null) {
54 if (self::$syntaxCheckMap ===
null) {
55 self::$syntaxCheckMap = [
75 return isset(self::$serviceMap[$serviceName]) ? self::$serviceMap[$serviceName] :
null;
92 return isset(self::$syntaxCheckMap[$serviceName]) ? self::$syntaxCheckMap[$serviceName] :
null;
105 return $bin->getName() .
' ' . $bin->getVersion() .
' (' . $service->getName() .
')';
120 foreach (
$bearsamppBins->getServices() as $serviceName => $service) {
125 $callback($serviceName, $service, $bin, $syntaxCheckCmd);
139 public static function startService($bin, $syntaxCheckCmd =
null, $showWindow =
false)
143 if (method_exists($bin,
'initData')) {
147 $name = $bin->getName();
148 $service = $bin->getService();
151 if (!$service->start()) {
153 $serviceErrorLog = sprintf(
'Error while starting the %s service', $name);
154 if (!empty($syntaxCheckCmd)) {
155 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
156 if (!$cmdSyntaxCheck[
'syntaxOk']) {
158 $serviceErrorLog .= sprintf(
' (conf errors detected : %s)', $cmdSyntaxCheck[
'content']);
163 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
181 return $service->stop();
197 $errorReporting = error_reporting();
202 $connection = @fsockopen($localIP,
$port);
205 error_reporting($errorReporting);
207 if (is_resource($connection)) {
211 return $process !=
null ? $process :
'N/A';
231 if (method_exists($bin,
'initData')) {
235 $name = $bin->getName();
236 $service = $bin->getService();
240 if ($isPortInUse ===
false) {
241 if (!$service->isInstalled()) {
243 if ($service->start()) {
244 Log::info(sprintf(
'%s service successfully installed. (name: %s ; port: %s)', $name, $service->getName(),
$port));
246 $bearsamppWinbinder->messageBoxInfo(
255 $serviceErrorLog = sprintf(
'Error during the installation of %s service', $name);
256 if (!empty($syntaxCheckCmd)) {
257 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
258 if (!$cmdSyntaxCheck[
'syntaxOk']) {
260 $serviceErrorLog .= sprintf(
' (conf errors detected : %s)', $cmdSyntaxCheck[
'content']);
265 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
269 Log::warning(sprintf(
'%s service already installed', $name));
271 $bearsamppWinbinder->messageBoxWarning(
279 } elseif ($service->isRunning()) {
280 Log::warning(sprintf(
'%s service already installed and running', $name));
282 $bearsamppWinbinder->messageBoxWarning(
290 Log::error(sprintf(
'Port %s is used by an other application : %s',
$port, $isPortInUse));
292 $bearsamppWinbinder->messageBoxError(
313 Log::error(
'$service not an instance of Win32Service');
318 if ($service->isInstalled()) {
319 if ($service->delete()) {
320 Log::info(sprintf(
'%s service successfully removed', $name));
324 Log::error(sprintf(
'Error during the uninstallation of %s service', $name));
329 Log::warning(sprintf(
'%s service does not exist', $name));
362 if (self::$syntaxCheckMap ===
null) {
364 self::$syntaxCheckMap = [
371 return isset(self::$syntaxCheckMap[$serviceName]);
390 if (method_exists($bin,
'getPort')) {
391 return $bin->getPort();
392 } elseif (method_exists($bin,
'getSmtpPort')) {
393 return $bin->getSmtpPort();
415 Log::trace(
'ServiceHelper::stopAllServicesParallel() starting');
416 $startTime = microtime(
true);
419 if (empty($services)) {
425 Log::trace(
'Starting parallel shutdown of ' . count($services) .
' services');
430 if ($parallelSuccess) {
431 $duration = round(microtime(
true) - $startTime, 3);
432 Log::info(
'Parallel shutdown completed successfully in ' . $duration .
's');
438 Log::info(
'Parallel shutdown timed out, falling back to sequential shutdown');
441 $totalDuration = round(microtime(
true) - $startTime, 3);
442 Log::info(
'Sequential shutdown completed in ' . $totalDuration .
's');
444 return $sequentialSuccess;
462 Log::trace(
'Phase 1: Sending stop commands to all services');
463 $totalServices = count($services);
467 foreach ($services as $serviceName => $service) {
469 if ($progressCallback) {
470 $progressCallback($currentIndex, $totalServices, $serviceName);
473 Log::trace(
'Sending stop to: ' . $serviceName);
478 Log::trace(
'Phase 2: Monitoring service status');
479 $monitorStartTime = microtime(
true);
480 $monitorTimeout = $shutdownTimeout;
481 $checkInterval = 0.5;
484 while ((microtime(
true) - $monitorStartTime) < $monitorTimeout) {
487 foreach ($services as $serviceName => $service) {
488 if (!$service->isStopped()) {
495 Log::trace(
'All services stopped in parallel phase');
500 usleep($checkInterval * 1000000);
504 Log::trace(
'Phase 3: Force killing remaining services');
505 foreach ($services as $serviceName => $service) {
506 if (!$service->isStopped()) {
529 Log::trace(
'Starting sequential shutdown phase');
530 $totalServices = count($services);
533 foreach ($services as $serviceName => $service) {
535 if ($progressCallback) {
536 $progressCallback($currentIndex, $totalServices, $serviceName);
539 Log::trace(
'Sequential stop: ' . $serviceName);
542 if (!$service->isStopped()) {
568 'nodejs' =>
'node.exe',
571 if (isset($processMap[$serviceName])) {
572 Log::trace(
'Killing process: ' . $processMap[$serviceName]);
590 foreach ($services as $serviceName => $service) {
591 if (!$service->isStopped()) {
615 Log::trace(
'ServiceHelper::startAllServicesParallel() starting with ' . count($serviceInfos) .
' services');
616 $startTime = microtime(
true);
618 if (empty($serviceInfos)) {
624 Log::trace(
'Starting parallel startup of ' . count($serviceInfos) .
' services');
629 if ($parallelSuccess) {
630 $duration = round(microtime(
true) - $startTime, 3);
631 Log::info(
'Parallel startup completed successfully in ' . $duration .
's');
637 Log::info(
'Parallel startup timed out, falling back to sequential startup');
640 $totalDuration = round(microtime(
true) - $startTime, 3);
641 Log::info(
'Sequential startup completed in ' . $totalDuration .
's');
643 return $sequentialSuccess;
659 private static function startServicesParallel($serviceInfos, ?callable $progressCallback =
null, $startupTimeout = 30)
661 Log::trace(
'Phase 1: Sending start commands to all services');
662 $totalServices = count($serviceInfos);
666 foreach ($serviceInfos as $serviceName => $serviceInfo) {
668 if ($progressCallback) {
669 $progressCallback($currentIndex, $totalServices, $serviceInfo[
'name']);
672 Log::trace(
'Sending start to: ' . $serviceName);
673 $service = $serviceInfo[
'service'];
680 Log::trace(
'Phase 2: Monitoring service status');
681 $monitorStartTime = microtime(
true);
682 $monitorTimeout = $startupTimeout;
683 $checkInterval = 0.5;
685 $failedServices = [];
687 while ((microtime(
true) - $monitorStartTime) < $monitorTimeout) {
690 foreach ($serviceInfos as $serviceName => $serviceInfo) {
691 $service = $serviceInfo[
'service'];
693 if (!$service->isRunning()) {
695 $failedServices[$serviceName] = $serviceInfo;
700 Log::trace(
'All services running in parallel phase');
705 usleep($checkInterval * 1000000);
709 if (!empty($failedServices)) {
710 Log::trace(
'Phase 3: Retrying ' . count($failedServices) .
' failed services');
712 foreach ($failedServices as $serviceName => $serviceInfo) {
713 $service = $serviceInfo[
'service'];
715 if (!$service->isRunning()) {
716 Log::trace(
'Retrying start for: ' . $serviceName);
742 Log::trace(
'Starting sequential startup phase');
743 $totalServices = count($serviceInfos);
746 foreach ($serviceInfos as $serviceName => $serviceInfo) {
748 if ($progressCallback) {
749 $progressCallback($currentIndex, $totalServices, $serviceInfo[
'name']);
752 Log::trace(
'Sequential start: ' . $serviceName);
753 $service = $serviceInfo[
'service'];
760 if (!$service->isRunning()) {
761 Log::trace(
'Service failed to start: ' . $serviceName);
780 foreach ($serviceInfos as $serviceName => $serviceInfo) {
781 $service = $serviceInfo[
'service'];
782 if (!$service->isRunning()) {
static getProcessUsingPort($port)
const START_SERVICE_ERROR
const START_SERVICE_TITLE
const INSTALL_SERVICE_TITLE
const STARTUP_SERVICE_SYNTAX_ERROR
const SERVICE_INSTALL_ERROR
const SERVICE_ALREADY_INSTALLED
static info($data, $file=null)
static warning($data, $file=null)
static trace($data, $file=null)
static error($data, $file=null)
static startAllServicesParallel($serviceInfos, ?callable $progressCallback=null, $startupTimeout=30)
static getServicePort($serviceName, $bearsamppBins)
static shutdownServicesSequential($services, ?callable $progressCallback=null)
static installService($bin, $port, $syntaxCheckCmd, $showWindow=false)
static forceKillService($serviceName)
static allServicesStopped($services)
static allServicesRunning($serviceInfos)
static startServicesParallel($serviceInfos, ?callable $progressCallback=null, $startupTimeout=30)
static removeService($service, $name)
static getServiceDisplayName($bin, $service)
static hasSyntaxCheck($serviceName)
static stopAllServicesParallel($bearsamppBins, ?callable $progressCallback=null, $shutdownTimeout=15)
static shutdownServicesParallel($services, ?callable $progressCallback=null, $shutdownTimeout=15)
static stopService($service)
static startService($bin, $syntaxCheckCmd=null, $showWindow=false)
static getSyntaxCheckCmd($serviceName, $bearsamppBins=null)
static isPortInUse($port)
static startServicesSequential($serviceInfos, ?callable $progressCallback=null)
static getAllServiceNames()
static processServices($bearsamppBins, callable $callback)
static getBinFromServiceName($serviceName, $bearsamppBins)
static initializeMappings($bearsamppBins)
static killBins($refreshProcs=false)