-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from sayyassine9/master
Implementation of the classes
- Loading branch information
Showing
7 changed files
with
418 additions
and
67 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,109 @@ | ||
<?php | ||
|
||
namespace Gt\Daemon; | ||
|
||
class Pool { | ||
protected $processList; | ||
|
||
public function __construct() { | ||
$this->processList = []; | ||
} | ||
|
||
public function add(string $name, Process $process):void { | ||
$this->processList[$name] = $process; | ||
} | ||
|
||
public function exec():void { | ||
} | ||
|
||
public function numRunning():int { | ||
|
||
} | ||
|
||
public function read():string { | ||
|
||
} | ||
|
||
public function readError():string { | ||
|
||
} | ||
} | ||
<?php | ||
namespace Gt\Daemon; | ||
|
||
use \Exception; | ||
|
||
class Pool { | ||
protected $processList; | ||
|
||
public function __construct() { | ||
$this->processList = []; | ||
} | ||
|
||
public function add(string $name, Process $process) { | ||
$this->processList[$name] = $process; | ||
} | ||
|
||
/** Starts the execution of all proccesses */ | ||
public function exec() { | ||
foreach($this->processList as $name=>$process ){ | ||
$process->run(); | ||
} | ||
} | ||
|
||
public function numRunning():int { | ||
$num = 0 ; | ||
foreach($this->processList as $name=>$process){ | ||
$num += ($process->isAlive() ? 1 : 0); | ||
} | ||
|
||
return $num; | ||
} | ||
|
||
/** Returns ouptput for all the proccesses in the $processList */ | ||
public function read():string { | ||
$output = "" ; | ||
|
||
foreach($this->processList as $name=>$process){ | ||
$out = $process->getOutput(); | ||
|
||
if(!empty($out)){ | ||
$output .= "OUTPUT for [$name] : " . PHP_EOL . $out . PHP_EOL .PHP_EOL; | ||
} | ||
} | ||
|
||
return $output ; | ||
} | ||
|
||
/** Returns errors for all the proccesses in the $processList */ | ||
public function readError():string { | ||
$output = "" ; | ||
|
||
foreach($this->processList as $name=>$process){ | ||
$out = $process->getErrorOutput(); | ||
|
||
if(!empty($out)){ | ||
$output .= "ERROR for [$name] : " . PHP_EOL . $out . PHP_EOL .PHP_EOL; | ||
} | ||
} | ||
|
||
return $output ; | ||
} | ||
|
||
public function readErrorOf(string $processName):string { | ||
if(!array_key_exists($processName, $this->processList) | ||
|| !is_resource($this->processList[$processName])) { | ||
throw new \Exception("No process named $processName found ."); | ||
} | ||
|
||
return $this->processList[$processName]->getErrorOuput(); | ||
} | ||
|
||
public function readOutputOf(string $processName):string { | ||
if(!array_key_exists($processName, $this->processList) | ||
|| !is_resource($this->processList[$processName])) { | ||
throw new \Exception("No process named $processName found ."); | ||
} | ||
|
||
return $this->processList[$processName]->getErrorOuput(); | ||
} | ||
|
||
/** Executes only the proccess having $processName as a name */ | ||
public function executeOne(string $processName) { | ||
if(!array_key_exists( $processName ,$this->processList) | ||
|| !is_resource($this->processList[$processName])) { | ||
throw new \Exception("No process named $processName found ."); | ||
} | ||
|
||
$this->processList[$processName]->run(); | ||
} | ||
|
||
/** | ||
* Stops all the processes and returns an array mapping each proccess name with it's return code | ||
* This method should only be called if you want to stop the execution of all the processes | ||
* | ||
* example : | ||
* $return_codes = $pool->closeAll() ; | ||
* echo $return_codes['process1'] ; //assuming that the pool contained a process having 'process1' for name | ||
* //this will return the return code of 'process1' | ||
*/ | ||
public function closeAll():array { | ||
$codes = [] ; | ||
|
||
foreach($this->processList as $name=>$process){ | ||
$codes[$name] = $process->close(); | ||
} | ||
|
||
return $codes; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,153 @@ | ||
<?php | ||
namespace Gt\Daemon; | ||
|
||
class Process { | ||
public function __construct(string $command, string $cwd = null) { | ||
} | ||
|
||
public function isRunning():bool { | ||
|
||
} | ||
|
||
public function read():string { | ||
|
||
} | ||
|
||
public function readError():string { | ||
|
||
} | ||
|
||
public function write(string $input):int { | ||
|
||
} | ||
|
||
/** @return resource */ | ||
public function getInStream() { | ||
|
||
} | ||
|
||
/** @return resource */ | ||
public function getOutStream() { | ||
|
||
} | ||
|
||
/** @return resource */ | ||
public function getErrorStream() { | ||
|
||
} | ||
<?php | ||
/** | ||
* | ||
* By: sayyassine | ||
* For the love of code | ||
*/ | ||
|
||
namespace Gt\Daemon; | ||
/** | ||
* Class Process | ||
*/ | ||
class Process | ||
{ | ||
/** | ||
* @var string | ||
* Contains the command string | ||
*/ | ||
private $command = "" ; | ||
|
||
/** | ||
* @var array | ||
* The streams for the array input, output and errors | ||
*/ | ||
private $pipes = []; | ||
/** | ||
* @var null|resource | ||
* The thread within which the command will be ran | ||
*/ | ||
private $process = null ; | ||
|
||
/** | ||
* Process constructor. | ||
* @param string|null $command | ||
*/ | ||
public function __construct(string $command = null) | ||
{ | ||
$this->command = "" ; | ||
$this->OS = explode(' ', strtolower(php_uname('s')))[0] ; | ||
if( $command ){ | ||
$this->setCommand($command); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* @throws \Exception | ||
* Runs the command in a concurrent thread. | ||
* Sets the input , output and errors streams. | ||
* Throws an exception if the command is empty or null. | ||
*/ | ||
public function run() | ||
{ | ||
if( !$this->command ){ | ||
throw new \Exception("Trying to run an empty command."); | ||
} | ||
|
||
$descriptorspec = array( | ||
0 => array("pipe", "r"), | ||
1 => array("pipe", "w"), | ||
2 => array("pipe", "w") | ||
); | ||
$this->process = proc_open(escapeshellcmd($this->command), $descriptorspec, $this->pipes ); | ||
|
||
if (!is_resource($this->process)) { | ||
throw new \Exception("An unexpected error occured while trying to run $this->command"); | ||
} | ||
|
||
|
||
stream_set_blocking($this->pipes[1], 0); | ||
stream_set_blocking($this->pipes[2], 0); | ||
stream_set_blocking($this->pipes[0], 0); | ||
|
||
} | ||
|
||
/** | ||
* @return bool | ||
* @throws \Exception | ||
* is true as long as the thread is running | ||
*/ | ||
public function isAlive():bool | ||
{ | ||
if( !is_resource($this->process)) | ||
throw new \Exception("This function should be called after the run method."); | ||
|
||
return proc_get_status($this->process)['running']; | ||
} | ||
|
||
/** | ||
* @return string | ||
* returns the command string | ||
*/ | ||
public function getCommand():string | ||
{ | ||
return $this->command ; | ||
} | ||
|
||
/** | ||
* @param string $command | ||
* sets the command string | ||
* This needs to be called before the run method. | ||
* | ||
*/ | ||
public function setCommand(string $command) | ||
{ | ||
$this->command = $command ; | ||
} | ||
|
||
/** | ||
* @return string | ||
* @throws \Exception | ||
* Returns all the outputs that are still not read | ||
*/ | ||
public function getOutput():string | ||
{ | ||
|
||
if( !is_resource($this->process)) | ||
throw new \Exception("This function should be called after the run method."); | ||
|
||
|
||
$output = fread($this->pipes[1], 1024); | ||
|
||
|
||
return $output ; | ||
} | ||
|
||
/** | ||
* @return string | ||
* @throws \Exception | ||
* Returns all the errors generated by the command that are still not read | ||
*/ | ||
public function getErrorOutput():string | ||
{ | ||
|
||
|
||
if( !is_resource($this->process)) | ||
throw new \Exception("This function should be called after the run method."); | ||
|
||
|
||
$output = fread($this->pipes[2], 1024); | ||
|
||
return $output ; | ||
} | ||
|
||
/** | ||
* closes the thread and the streams then returns the return code of the command | ||
* @return int | ||
*/ | ||
public function close():int | ||
{ | ||
array_filter( $this->pipes, function($pipe){ return fclose($pipe); }); | ||
return proc_close($this->process); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
/** | ||
* Created by PhpStorm. | ||
* User: sayya | ||
* Date: 18/03/2019 | ||
* Time: 11:59 | ||
*/ | ||
|
||
|
||
use \Gt\Daemon\Pool; | ||
use \Gt\Daemon\Process; | ||
|
||
|
||
require_once '../src/Pool.php'; | ||
require_once '../src/Process.php'; | ||
|
||
|
||
$pool = new Pool(); | ||
|
||
$pool->add("Numbers process",new Process("php numbers.php")); | ||
$pool->add("Letters process",new Process("php letters.php")); | ||
|
||
|
||
$pool->exec() ; | ||
|
||
while($pool->numRunning() > 0){ | ||
echo ($pool->read()); | ||
echo ($pool->readError()); | ||
|
||
sleep(3); | ||
|
||
} | ||
|
||
print_r($pool->closeAll()); | ||
|
||
echo ("Execution done." .PHP_EOL); |
Oops, something went wrong.