Skip to content

Commit

Permalink
Merge pull request #2 from sayyassine9/master
Browse files Browse the repository at this point in the history
Implementation of the classes
  • Loading branch information
g105b authored Mar 19, 2019
2 parents 6aa0d5c + fb1f2a8 commit ad65791
Show file tree
Hide file tree
Showing 7 changed files with 418 additions and 67 deletions.
Binary file added documentation.pdf
Binary file not shown.
139 changes: 109 additions & 30 deletions src/Pool.php
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;
}
}
189 changes: 152 additions & 37 deletions src/Process.php
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);
}
}
36 changes: 36 additions & 0 deletions test/PoolTest.php
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);
Loading

0 comments on commit ad65791

Please sign in to comment.