Bearsampp 2026.9.23
Loading...
Searching...
No Matches
ServiceHelper Class Reference

Static Public Member Functions

static getAllServiceNames ()
static getBinFromServiceName ($serviceName, $bearsamppBins)
static getServiceDisplayName ($bin, $service)
static getServicePort ($serviceName, $bearsamppBins)
static getSyntaxCheckCmd ($serviceName, $bearsamppBins=null)
static hasSyntaxCheck ($serviceName)
static installService ($bin, $port, $syntaxCheckCmd, $showWindow=false)
static isPortInUse ($port)
static processServices ($bearsamppBins, callable $callback)
static removeService ($service, $name)
static startAllServicesParallel ($serviceInfos, ?callable $progressCallback=null, $startupTimeout=30)
static startService ($bin, $syntaxCheckCmd=null, $showWindow=false)
static stopAllServicesParallel ($bearsamppBins, ?callable $progressCallback=null, $shutdownTimeout=15)
static stopService ($service)

Static Private Member Functions

static allServicesRunning ($serviceInfos)
static allServicesStopped ($services)
static forceKillService ($serviceName)
static initializeMappings ($bearsamppBins)
static shutdownServicesParallel ($services, ?callable $progressCallback=null, $shutdownTimeout=15)
static shutdownServicesSequential ($services, ?callable $progressCallback=null)
static startServicesParallel ($serviceInfos, ?callable $progressCallback=null, $startupTimeout=30)
static startServicesSequential ($serviceInfos, ?callable $progressCallback=null)

Static Private Attributes

static $serviceMap = null
static $syntaxCheckMap = null

Detailed Description

Class ServiceHelper

Utility class for service management operations. Provides centralized methods for service lookup, syntax check commands, and common service operations to eliminate code duplication.

Definition at line 17 of file class.servicehelper.php.

Member Function Documentation

◆ allServicesRunning()

allServicesRunning ( $serviceInfos)
staticprivate

Check if all services are running

Parameters
array$serviceInfosArray of service information
Returns
bool True if all services are running

Definition at line 778 of file class.servicehelper.php.

779 {
780 foreach ($serviceInfos as $serviceName => $serviceInfo) {
781 $service = $serviceInfo['service'];
782 if (!$service->isRunning()) {
783 return false;
784 }
785 }
786
787 return true;
788 }

Referenced by startServicesParallel(), and startServicesSequential().

Here is the caller graph for this function:

◆ allServicesStopped()

allServicesStopped ( $services)
staticprivate

Check if all services are stopped

Parameters
array$servicesArray of services
Returns
bool True if all services are stopped

Definition at line 588 of file class.servicehelper.php.

589 {
590 foreach ($services as $serviceName => $service) {
591 if (!$service->isStopped()) {
592 return false;
593 }
594 }
595
596 return true;
597 }

Referenced by shutdownServicesParallel(), and shutdownServicesSequential().

Here is the caller graph for this function:

◆ forceKillService()

forceKillService ( $serviceName)
staticprivate

Force kill a service by process name

Parameters
string$serviceNameThe service name
Returns
bool True if force kill was executed

Definition at line 558 of file class.servicehelper.php.

559 {
560 $processMap = [
561 BinApache::SERVICE_NAME => 'httpd.exe',
562 BinMysql::SERVICE_NAME => 'mysqld.exe',
563 BinMariadb::SERVICE_NAME => 'mysqld.exe',
564 BinMailpit::SERVICE_NAME => 'mailpit.exe',
565 BinMemcached::SERVICE_NAME => 'memcached.exe',
566 BinPostgresql::SERVICE_NAME => 'postgres.exe',
567 BinXlight::SERVICE_NAME => 'xlightftpd.exe',
568 'nodejs' => 'node.exe', // NodeJS - not a Windows service but needs to be killed on exit
569 ];
570
571 if (isset($processMap[$serviceName])) {
572 Log::trace('Killing process: ' . $processMap[$serviceName]);
573 Win32Ps::killBins([$processMap[$serviceName]]);
574
575 return true;
576 }
577
578 return false;
579 }
const SERVICE_NAME
static trace($data, $file=null)
static killBins($refreshProcs=false)

References Win32Ps\killBins(), BinApache\SERVICE_NAME, BinMailpit\SERVICE_NAME, BinMariadb\SERVICE_NAME, BinMemcached\SERVICE_NAME, BinMysql\SERVICE_NAME, BinPostgresql\SERVICE_NAME, BinXlight\SERVICE_NAME, and Log\trace().

Referenced by shutdownServicesParallel(), and shutdownServicesSequential().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getAllServiceNames()

◆ getBinFromServiceName()

getBinFromServiceName ( $serviceName,
$bearsamppBins )
static

Get binary instance from service name

Parameters
string$serviceNameThe service name
object$bearsamppBinsThe bins object
Returns
object|null The binary instance or null if not found

Definition at line 71 of file class.servicehelper.php.

72 {
74
75 return isset(self::$serviceMap[$serviceName]) ? self::$serviceMap[$serviceName] : null;
76 }
global $bearsamppBins
static initializeMappings($bearsamppBins)

References $bearsamppBins, and initializeMappings().

Referenced by getServicePort(), processServices(), and ActionRestartAllServices\processWindow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getServiceDisplayName()

getServiceDisplayName ( $bin,
$service )
static

Get service display name (Name + Version + Service Name)

Parameters
object$binThe binary instance
object$serviceThe service instance
Returns
string The formatted service name

Definition at line 103 of file class.servicehelper.php.

104 {
105 return $bin->getName() . ' ' . $bin->getVersion() . ' (' . $service->getName() . ')';
106 }

Referenced by ActionRestartAllServices\processWindow(), and ActionStartAllServices\processWindow().

Here is the caller graph for this function:

◆ getServicePort()

getServicePort ( $serviceName,
$bearsamppBins )
static

Get port for a service

Parameters
string$serviceNameThe service name
object$bearsamppBinsThe bins object
Returns
int The port number or 0 if not applicable

Definition at line 382 of file class.servicehelper.php.

383 {
384 $bin = self::getBinFromServiceName($serviceName, $bearsamppBins);
385 if ($bin === null) {
386 return 0;
387 }
388
389 // Different services have different methods to get port
390 if (method_exists($bin, 'getPort')) {
391 return $bin->getPort();
392 } elseif (method_exists($bin, 'getSmtpPort')) {
393 return $bin->getSmtpPort();
394 }
395
396 return 0;
397 }
static getBinFromServiceName($serviceName, $bearsamppBins)

References $bearsamppBins, and getBinFromServiceName().

Here is the call graph for this function:

◆ getSyntaxCheckCmd()

getSyntaxCheckCmd ( $serviceName,
$bearsamppBins = null )
static

Get syntax check command for a service

Parameters
string$serviceNameThe service name
object$bearsamppBinsThe bins object (for initialization)
Returns
string|null The syntax check command or null if not applicable

Definition at line 86 of file class.servicehelper.php.

87 {
88 if ($bearsamppBins !== null) {
90 }
91
92 return isset(self::$syntaxCheckMap[$serviceName]) ? self::$syntaxCheckMap[$serviceName] : null;
93 }

References $bearsamppBins, and initializeMappings().

Referenced by processServices(), and ActionRestartAllServices\processWindow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hasSyntaxCheck()

hasSyntaxCheck ( $serviceName)
static

Check if a service has syntax check capability

Parameters
string$serviceNameThe service name
Returns
bool True if service supports syntax check

Definition at line 360 of file class.servicehelper.php.

361 {
362 if (self::$syntaxCheckMap === null) {
363 // Initialize with dummy bins object if needed
364 self::$syntaxCheckMap = [
368 ];
369 }
370
371 return isset(self::$syntaxCheckMap[$serviceName]);
372 }
const CMD_SYNTAX_CHECK
const CMD_SYNTAX_CHECK

References BinApache\CMD_SYNTAX_CHECK, BinMariadb\CMD_SYNTAX_CHECK, BinMysql\CMD_SYNTAX_CHECK, BinApache\SERVICE_NAME, BinMariadb\SERVICE_NAME, and BinMysql\SERVICE_NAME.

◆ initializeMappings()

initializeMappings ( $bearsamppBins)
staticprivate

Initialize service mappings

Parameters
object$bearsamppBinsThe bins object
Returns
void

Definition at line 40 of file class.servicehelper.php.

41 {
42 if (self::$serviceMap === null) {
43 self::$serviceMap = [
51 ];
52 }
53
54 if (self::$syntaxCheckMap === null) {
55 self::$syntaxCheckMap = [
59 ];
60 }
61 }

References $bearsamppBins, BinApache\CMD_SYNTAX_CHECK, BinMariadb\CMD_SYNTAX_CHECK, BinMysql\CMD_SYNTAX_CHECK, BinApache\SERVICE_NAME, BinMailpit\SERVICE_NAME, BinMariadb\SERVICE_NAME, BinMemcached\SERVICE_NAME, BinMysql\SERVICE_NAME, BinPostgresql\SERVICE_NAME, and BinXlight\SERVICE_NAME.

Referenced by getBinFromServiceName(), getSyntaxCheckCmd(), and processServices().

Here is the caller graph for this function:

◆ installService()

installService ( $bin,
$port,
$syntaxCheckCmd,
$showWindow = false )
static

Attempts to install and start a service on a specific port, with optional syntax checking and user notifications.

Parameters
object$binAn object containing the binary information and methods related to the service.
int$portThe port number on which the service should run.
string$syntaxCheckCmdThe command to execute for syntax checking of the service configuration.
bool$showWindowOptional. Whether to show message boxes for information, warnings, and errors. Defaults to false.
Returns
bool Returns true if the service is successfully installed and started, false otherwise.

Definition at line 227 of file class.servicehelper.php.

228 {
229 global $bearsamppLang, $bearsamppWinbinder;
230
231 if (method_exists($bin, 'initData')) {
232 $bin->initData();
233 }
234
235 $name = $bin->getName();
236 $service = $bin->getService();
237 $boxTitle = sprintf($bearsamppLang->getValue(Lang::INSTALL_SERVICE_TITLE), $name);
238
239 $isPortInUse = self::isPortInUse($port);
240 if ($isPortInUse === false) {
241 if (!$service->isInstalled()) {
242 $service->create();
243 if ($service->start()) {
244 Log::info(sprintf('%s service successfully installed. (name: %s ; port: %s)', $name, $service->getName(), $port));
245 if ($showWindow) {
246 $bearsamppWinbinder->messageBoxInfo(
247 sprintf($bearsamppLang->getValue(Lang::SERVICE_INSTALLED), $name, $service->getName(), $port),
248 $boxTitle
249 );
250 }
251
252 return true;
253 } else {
254 $serviceError = sprintf($bearsamppLang->getValue(Lang::SERVICE_INSTALL_ERROR), $name);
255 $serviceErrorLog = sprintf('Error during the installation of %s service', $name);
256 if (!empty($syntaxCheckCmd)) {
257 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
258 if (!$cmdSyntaxCheck['syntaxOk']) {
259 $serviceError .= PHP_EOL . sprintf($bearsamppLang->getValue(Lang::STARTUP_SERVICE_SYNTAX_ERROR), $cmdSyntaxCheck['content']);
260 $serviceErrorLog .= sprintf(' (conf errors detected : %s)', $cmdSyntaxCheck['content']);
261 }
262 }
263 Log::error($serviceErrorLog);
264 if ($showWindow) {
265 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
266 }
267 }
268 } else {
269 Log::warning(sprintf('%s service already installed', $name));
270 if ($showWindow) {
271 $bearsamppWinbinder->messageBoxWarning(
272 sprintf($bearsamppLang->getValue(Lang::SERVICE_ALREADY_INSTALLED), $name),
273 $boxTitle
274 );
275 }
276
277 return true;
278 }
279 } elseif ($service->isRunning()) {
280 Log::warning(sprintf('%s service already installed and running', $name));
281 if ($showWindow) {
282 $bearsamppWinbinder->messageBoxWarning(
283 sprintf($bearsamppLang->getValue(Lang::SERVICE_ALREADY_INSTALLED), $name),
284 $boxTitle
285 );
286 }
287
288 return true;
289 } else {
290 Log::error(sprintf('Port %s is used by an other application : %s', $port, $isPortInUse));
291 if ($showWindow) {
292 $bearsamppWinbinder->messageBoxError(
293 sprintf($bearsamppLang->getValue(Lang::PORT_NOT_USED_BY), $port, $isPortInUse),
294 $boxTitle
295 );
296 }
297 }
298
299 return false;
300 }
global $bearsamppLang
$port
const SERVICE_INSTALLED
const INSTALL_SERVICE_TITLE
const STARTUP_SERVICE_SYNTAX_ERROR
const SERVICE_INSTALL_ERROR
const SERVICE_ALREADY_INSTALLED
const PORT_NOT_USED_BY
static info($data, $file=null)
static warning($data, $file=null)
static error($data, $file=null)
static isPortInUse($port)

References $bearsamppLang, $port, Log\error(), Log\info(), Lang\INSTALL_SERVICE_TITLE, isPortInUse(), Lang\PORT_NOT_USED_BY, Lang\SERVICE_ALREADY_INSTALLED, Lang\SERVICE_INSTALL_ERROR, Lang\SERVICE_INSTALLED, Lang\STARTUP_SERVICE_SYNTAX_ERROR, and Log\warning().

Referenced by ActionService\install(), BinApache\setEnable(), BinMailpit\setEnable(), BinMariadb\setEnable(), BinMemcached\setEnable(), BinMysql\setEnable(), BinPostgresql\setEnable(), and BinXlight\setEnable().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isPortInUse()

isPortInUse ( $port)
static

Checks if a specific port is in use.

Parameters
int$portThe port number to check
Returns
mixed False if the port is not in use, otherwise returns the process using the port

Definition at line 191 of file class.servicehelper.php.

192 {
193 // Set localIP statically
194 $localIP = APP_LOCALHOST;
195
196 // Save current error reporting level
197 $errorReporting = error_reporting();
198
199 // Disable error reporting temporarily
200 error_reporting(0);
201
202 $connection = @fsockopen($localIP, $port);
203
204 // Restore original error reporting level
205 error_reporting($errorReporting);
206
207 if (is_resource($connection)) {
208 fclose($connection);
210
211 return $process != null ? $process : 'N/A';
212 }
213
214 return false;
215 }
static getProcessUsingPort($port)
const APP_LOCALHOST
Definition root.php:21

References $port, APP_LOCALHOST, and Batch\getProcessUsingPort().

Referenced by BinApache\changePort(), BinMailpit\changePort(), BinMariadb\changePort(), BinMemcached\changePort(), BinMysql\changePort(), BinPostgresql\changePort(), BinXlight\changePort(), BinPostgresql\handleNonPostgresUsage(), installService(), and ActionStartup\prepareService().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ processServices()

processServices ( $bearsamppBins,
callable $callback )
static

Process all services with a callback function

Parameters
object$bearsamppBinsThe bins object
callable$callbackFunction to call for each service: function($serviceName, $service, $bin, $syntaxCheckCmd)
Returns
void

Definition at line 116 of file class.servicehelper.php.

117 {
119
120 foreach ($bearsamppBins->getServices() as $serviceName => $service) {
121 $bin = self::getBinFromServiceName($serviceName, $bearsamppBins);
122 $syntaxCheckCmd = self::getSyntaxCheckCmd($serviceName);
123
124 if ($bin !== null) {
125 $callback($serviceName, $service, $bin, $syntaxCheckCmd);
126 }
127 }
128 }
static getSyntaxCheckCmd($serviceName, $bearsamppBins=null)

References $bearsamppBins, getBinFromServiceName(), getSyntaxCheckCmd(), and initializeMappings().

Referenced by ActionStartAllServices\processWindow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ removeService()

removeService ( $service,
$name )
static

Removes a service if it is installed.

Parameters
Win32Service$serviceThe service object to be removed.
string$nameThe name of the service.
Returns
bool Returns true if the service is successfully removed, false otherwise.

Definition at line 310 of file class.servicehelper.php.

311 {
312 if (!($service instanceof Win32Service)) {
313 Log::error('$service not an instance of Win32Service');
314
315 return false;
316 }
317
318 if ($service->isInstalled()) {
319 if ($service->delete()) {
320 Log::info(sprintf('%s service successfully removed', $name));
321
322 return true;
323 } else {
324 Log::error(sprintf('Error during the uninstallation of %s service', $name));
325
326 return false;
327 }
328 } else {
329 Log::warning(sprintf('%s service does not exist', $name));
330 }
331
332 return true;
333 }

References Log\error(), Log\info(), and Log\warning().

Referenced by ActionService\remove(), BinApache\setEnable(), BinMailpit\setEnable(), BinMariadb\setEnable(), BinMemcached\setEnable(), BinMysql\setEnable(), BinPostgresql\setEnable(), and BinXlight\setEnable().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdownServicesParallel()

shutdownServicesParallel ( $services,
?callable $progressCallback = null,
$shutdownTimeout = 15 )
staticprivate

Shutdown services in parallel (non-blocking)

Phase 1: Send stop commands to all services (non-blocking) Phase 2: Monitor their status until all stopped or timeout Phase 3: Force kill any services still running

Parameters
array$servicesArray of services
callable | null$progressCallbackOptional progress callback
int$shutdownTimeoutTimeout in seconds
Returns
bool True if all services stopped

Definition at line 460 of file class.servicehelper.php.

461 {
462 Log::trace('Phase 1: Sending stop commands to all services');
463 $totalServices = count($services);
464 $currentIndex = 0;
465
466 // Phase 1: Send stop commands (non-blocking)
467 foreach ($services as $serviceName => $service) {
468 $currentIndex++;
469 if ($progressCallback) {
470 $progressCallback($currentIndex, $totalServices, $serviceName);
471 }
472
473 Log::trace('Sending stop to: ' . $serviceName);
474 $service->stop();
475 }
476
477 // Phase 2: Monitor status
478 Log::trace('Phase 2: Monitoring service status');
479 $monitorStartTime = microtime(true);
480 $monitorTimeout = $shutdownTimeout;
481 $checkInterval = 0.5;
482 $allStopped = false;
483
484 while ((microtime(true) - $monitorStartTime) < $monitorTimeout) {
485 $allStopped = true;
486
487 foreach ($services as $serviceName => $service) {
488 if (!$service->isStopped()) {
489 $allStopped = false;
490 break;
491 }
492 }
493
494 if ($allStopped) {
495 Log::trace('All services stopped in parallel phase');
496
497 return true;
498 }
499
500 usleep($checkInterval * 1000000);
501 }
502
503 // Phase 3: Force kill remaining services
504 Log::trace('Phase 3: Force killing remaining services');
505 foreach ($services as $serviceName => $service) {
506 if (!$service->isStopped()) {
507 Log::trace('Force killing: ' . $serviceName);
508 self::forceKillService($serviceName);
509 }
510 }
511
512 // Final check
513 return self::allServicesStopped($services);
514 }
static forceKillService($serviceName)
static allServicesStopped($services)

References allServicesStopped(), forceKillService(), and Log\trace().

Referenced by stopAllServicesParallel().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdownServicesSequential()

shutdownServicesSequential ( $services,
?callable $progressCallback = null )
staticprivate

Shutdown services sequentially (fallback method)

Stops services one by one, waiting for each to complete. Used as fallback when parallel shutdown fails.

Parameters
array$servicesArray of services
callable | null$progressCallbackOptional progress callback
Returns
bool True if all services stopped

Definition at line 527 of file class.servicehelper.php.

528 {
529 Log::trace('Starting sequential shutdown phase');
530 $totalServices = count($services);
531 $currentIndex = 0;
532
533 foreach ($services as $serviceName => $service) {
534 $currentIndex++;
535 if ($progressCallback) {
536 $progressCallback($currentIndex, $totalServices, $serviceName);
537 }
538
539 Log::trace('Sequential stop: ' . $serviceName);
540 $service->stop();
541
542 if (!$service->isStopped()) {
543 Log::trace('Force killing: ' . $serviceName);
544 self::forceKillService($serviceName);
545 }
546 }
547
548 return self::allServicesStopped($services);
549 }

References allServicesStopped(), forceKillService(), and Log\trace().

Referenced by stopAllServicesParallel().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ startAllServicesParallel()

startAllServicesParallel ( $serviceInfos,
?callable $progressCallback = null,
$startupTimeout = 30 )
static

Start all services in parallel for optimized startup

Sends start commands to all services simultaneously, then monitors their status. Falls back to sequential startup if parallel fails. Significantly reduces startup time.

Performance: 40-60% faster startup (parallel vs sequential)

Parameters
array$serviceInfosArray of service information arrays with 'service', 'bin', 'name' keys
callable | null$progressCallbackOptional callback: function($current, $total, $serviceName)
int$startupTimeoutTimeout in seconds (default: 30)
Returns
bool True if all services started successfully

Definition at line 613 of file class.servicehelper.php.

614 {
615 Log::trace('ServiceHelper::startAllServicesParallel() starting with ' . count($serviceInfos) . ' services');
616 $startTime = microtime(true);
617
618 if (empty($serviceInfos)) {
619 Log::trace('No services to start');
620
621 return true;
622 }
623
624 Log::trace('Starting parallel startup of ' . count($serviceInfos) . ' services');
625
626 // Try parallel startup
627 $parallelSuccess = self::startServicesParallel($serviceInfos, $progressCallback, $startupTimeout);
628
629 if ($parallelSuccess) {
630 $duration = round(microtime(true) - $startTime, 3);
631 Log::info('Parallel startup completed successfully in ' . $duration . 's');
632
633 return true;
634 }
635
636 // Fallback to sequential
637 Log::info('Parallel startup timed out, falling back to sequential startup');
638 $sequentialSuccess = self::startServicesSequential($serviceInfos, $progressCallback);
639
640 $totalDuration = round(microtime(true) - $startTime, 3);
641 Log::info('Sequential startup completed in ' . $totalDuration . 's');
642
643 return $sequentialSuccess;
644 }
static startServicesParallel($serviceInfos, ?callable $progressCallback=null, $startupTimeout=30)
static startServicesSequential($serviceInfos, ?callable $progressCallback=null)

References Log\info(), startServicesParallel(), startServicesSequential(), and Log\trace().

Referenced by ActionStartup\installServicesSequential().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ startService()

startService ( $bin,
$syntaxCheckCmd = null,
$showWindow = false )
static

Start a service with optional syntax check

Parameters
object$binThe binary instance
string | null$syntaxCheckCmdThe syntax check command (optional)
bool$showWindowWhether to show error messages in a window (default: false)
Returns
bool True if service started successfully, false otherwise

Definition at line 139 of file class.servicehelper.php.

140 {
141 global $bearsamppLang, $bearsamppWinbinder;
142
143 if (method_exists($bin, 'initData')) {
144 $bin->initData();
145 }
146
147 $name = $bin->getName();
148 $service = $bin->getService();
149 $boxTitle = sprintf($bearsamppLang->getValue(Lang::START_SERVICE_TITLE), $name);
150
151 if (!$service->start()) {
152 $serviceError = sprintf($bearsamppLang->getValue(Lang::START_SERVICE_ERROR), $name);
153 $serviceErrorLog = sprintf('Error while starting the %s service', $name);
154 if (!empty($syntaxCheckCmd)) {
155 $cmdSyntaxCheck = $bin->getCmdLineOutput($syntaxCheckCmd);
156 if (!$cmdSyntaxCheck['syntaxOk']) {
157 $serviceError .= PHP_EOL . sprintf($bearsamppLang->getValue(Lang::STARTUP_SERVICE_SYNTAX_ERROR), $cmdSyntaxCheck['content']);
158 $serviceErrorLog .= sprintf(' (conf errors detected : %s)', $cmdSyntaxCheck['content']);
159 }
160 }
161 Log::error($serviceErrorLog);
162 if ($showWindow) {
163 $bearsamppWinbinder->messageBoxError($serviceError, $boxTitle);
164 }
165
166 return false;
167 }
168
169 return true;
170 }
const START_SERVICE_ERROR
const START_SERVICE_TITLE

References $bearsamppLang, Log\error(), Lang\START_SERVICE_ERROR, Lang\START_SERVICE_TITLE, and Lang\STARTUP_SERVICE_SYNTAX_ERROR.

Referenced by ActionRestartAllServices\processWindow(), ActionStartAllServices\processWindow(), BinPhp\setEnable(), and ActionService\start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ startServicesParallel()

startServicesParallel ( $serviceInfos,
?callable $progressCallback = null,
$startupTimeout = 30 )
staticprivate

Start services in parallel (non-blocking)

Phase 1: Send start commands to all services (non-blocking) Phase 2: Monitor their status until all running or timeout Phase 3: Retry any services that failed to start

Parameters
array$serviceInfosArray of service information
callable | null$progressCallbackOptional progress callback
int$startupTimeoutTimeout in seconds
Returns
bool True if all services started

Definition at line 659 of file class.servicehelper.php.

660 {
661 Log::trace('Phase 1: Sending start commands to all services');
662 $totalServices = count($serviceInfos);
663 $currentIndex = 0;
664
665 // Phase 1: Send start commands (non-blocking)
666 foreach ($serviceInfos as $serviceName => $serviceInfo) {
667 $currentIndex++;
668 if ($progressCallback) {
669 $progressCallback($currentIndex, $totalServices, $serviceInfo['name']);
670 }
671
672 Log::trace('Sending start to: ' . $serviceName);
673 $service = $serviceInfo['service'];
674
675 // Start the service
676 $service->start();
677 }
678
679 // Phase 2: Monitor status
680 Log::trace('Phase 2: Monitoring service status');
681 $monitorStartTime = microtime(true);
682 $monitorTimeout = $startupTimeout;
683 $checkInterval = 0.5;
684 $allRunning = false;
685 $failedServices = [];
686
687 while ((microtime(true) - $monitorStartTime) < $monitorTimeout) {
688 $allRunning = true;
689
690 foreach ($serviceInfos as $serviceName => $serviceInfo) {
691 $service = $serviceInfo['service'];
692
693 if (!$service->isRunning()) {
694 $allRunning = false;
695 $failedServices[$serviceName] = $serviceInfo;
696 }
697 }
698
699 if ($allRunning) {
700 Log::trace('All services running in parallel phase');
701
702 return true;
703 }
704
705 usleep($checkInterval * 1000000);
706 }
707
708 // Phase 3: Retry failed services
709 if (!empty($failedServices)) {
710 Log::trace('Phase 3: Retrying ' . count($failedServices) . ' failed services');
711
712 foreach ($failedServices as $serviceName => $serviceInfo) {
713 $service = $serviceInfo['service'];
714
715 if (!$service->isRunning()) {
716 Log::trace('Retrying start for: ' . $serviceName);
717 $service->start();
718 usleep(500000); // 500ms delay between retries
719 }
720 }
721
722 // Final check
723 return self::allServicesRunning($serviceInfos);
724 }
725
726 return true;
727 }
static allServicesRunning($serviceInfos)

References allServicesRunning(), and Log\trace().

Referenced by startAllServicesParallel().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ startServicesSequential()

startServicesSequential ( $serviceInfos,
?callable $progressCallback = null )
staticprivate

Start services sequentially (fallback method)

Starts services one by one, waiting for each to complete. Used as fallback when parallel startup fails.

Parameters
array$serviceInfosArray of service information
callable | null$progressCallbackOptional progress callback
Returns
bool True if all services started

Definition at line 740 of file class.servicehelper.php.

741 {
742 Log::trace('Starting sequential startup phase');
743 $totalServices = count($serviceInfos);
744 $currentIndex = 0;
745
746 foreach ($serviceInfos as $serviceName => $serviceInfo) {
747 $currentIndex++;
748 if ($progressCallback) {
749 $progressCallback($currentIndex, $totalServices, $serviceInfo['name']);
750 }
751
752 Log::trace('Sequential start: ' . $serviceName);
753 $service = $serviceInfo['service'];
754
755 $service->start();
756
757 // Small delay between service starts
758 usleep(200000);
759
760 if (!$service->isRunning()) {
761 Log::trace('Service failed to start: ' . $serviceName);
762 // Retry once
763 $service->start();
764 usleep(500000);
765 }
766 }
767
768 return self::allServicesRunning($serviceInfos);
769 }

References allServicesRunning(), and Log\trace().

Referenced by startAllServicesParallel().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stopAllServicesParallel()

stopAllServicesParallel ( $bearsamppBins,
?callable $progressCallback = null,
$shutdownTimeout = 15 )
static

Stop all services in parallel for optimized shutdown

Sends stop commands to all services simultaneously, then monitors their status. Falls back to sequential shutdown if parallel fails. Significantly reduces shutdown time.

Performance: 40-60% faster shutdown (parallel vs sequential)

Parameters
object$bearsamppBinsThe bins object
callable | null$progressCallbackOptional callback: function($current, $total, $serviceName)
int$shutdownTimeoutTimeout in seconds (default: 15)
Returns
bool True if all services stopped successfully

Definition at line 413 of file class.servicehelper.php.

414 {
415 Log::trace('ServiceHelper::stopAllServicesParallel() starting');
416 $startTime = microtime(true);
417
418 $services = $bearsamppBins->getServices();
419 if (empty($services)) {
420 Log::trace('No services to shut down');
421
422 return true;
423 }
424
425 Log::trace('Starting parallel shutdown of ' . count($services) . ' services');
426
427 // Try parallel shutdown
428 $parallelSuccess = self::shutdownServicesParallel($services, $progressCallback, $shutdownTimeout);
429
430 if ($parallelSuccess) {
431 $duration = round(microtime(true) - $startTime, 3);
432 Log::info('Parallel shutdown completed successfully in ' . $duration . 's');
433
434 return true;
435 }
436
437 // Fallback to sequential
438 Log::info('Parallel shutdown timed out, falling back to sequential shutdown');
439 $sequentialSuccess = self::shutdownServicesSequential($services, $progressCallback);
440
441 $totalDuration = round(microtime(true) - $startTime, 3);
442 Log::info('Sequential shutdown completed in ' . $totalDuration . 's');
443
444 return $sequentialSuccess;
445 }
static shutdownServicesSequential($services, ?callable $progressCallback=null)
static shutdownServicesParallel($services, ?callable $progressCallback=null, $shutdownTimeout=15)

References $bearsamppBins, Log\info(), shutdownServicesParallel(), shutdownServicesSequential(), and Log\trace().

Referenced by ActionStopAllServices\processWindow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stopService()

stopService ( $service)
static

Stop a service

Parameters
object$serviceThe service instance
Returns
bool True if service stopped successfully, false otherwise

Definition at line 179 of file class.servicehelper.php.

180 {
181 return $service->stop();
182 }

Referenced by ActionRestartAllServices\processWindow().

Here is the caller graph for this function:

Field Documentation

◆ $serviceMap

$serviceMap = null
staticprivate

Definition at line 24 of file class.servicehelper.php.

◆ $syntaxCheckMap

$syntaxCheckMap = null
staticprivate

Definition at line 31 of file class.servicehelper.php.


The documentation for this class was generated from the following file: