Passed
Push — master ( 0ab66c...87df70 )
by Dmitry
36s
created

Process::setIsAllowedFork()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace SymfonyBundles\Fork;
4
5
class Process implements ProcessInterface
6
{
7
    /**
8
     * @var bool
9
     */
10
    protected $isAllowedFork;
11
12
    /**
13
     * @var int
14
     */
15
    protected $processesCount;
16
17
    /**
18
     * Constructor.
19
     */
20 9
    public function __construct()
21
    {
22 9
        $this->setIsAllowedFork(function_exists('pcntl_fork'));
23 9
    }
24
25
    /**
26
     * {@inheritdoc}
27
     */
28 9
    public function setIsAllowedFork(bool $isAllowedFork): void
29
    {
30 9
        $this->isAllowedFork = $isAllowedFork;
31 9
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 3
    public function create(\Closure $closure): ProcessInterface
37
    {
38 3
        for ($i = 0; $i < $this->processesCount; ++$i) {
39 3
            if ($this->fork()) {
40 2
                $closure();
41
42 2
                $this->terminate();
43
            }
44
        }
45
46 3
        return $this;
47
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52 1
    public function wait(): ProcessInterface
53
    {
54 1
        if ($this->isAllowedFork) {
55 1
            pcntl_wait($status);
56
        }
57
58 1
        return $this;
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 2
    public function getPid(): int
65
    {
66 2
        return getmypid();
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     *
72
     * @codeCoverageIgnore
73
     */
74
    public function isAlive(int $pid): bool
75
    {
76
        $os = strtolower(trim(PHP_OS));
77
78
        switch ($os) {
79
            case 'linux':
80
                return empty($this->execute(sprintf('kill -0 %d', $pid)));
81
            case 'winnt':
82
            case 'windows':
83
                $output = $this->execute(sprintf('wmic process where processId=%d get processId', $pid));
84
85
                return $pid === (int) preg_replace('#[^\d]*#', '', $output);
86
        }
87
88
        return false;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94 1
    public function getMemoryUsage(): float
95
    {
96 1
        return round(memory_get_usage(true) / 1024 / 1024, 2);
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 5
    public function setCountOfChildProcesses(int $processesCount): ProcessInterface
103
    {
104 5
        if ($processesCount < 1) {
105 2
            $processesCount = $this->getOptimalNumberOfChildProcesses();
106
        }
107
108 5
        if ($processesCount > static::MAX_PROCESSES_QUANTITY) {
109 1
            $processesCount = static::MAX_PROCESSES_QUANTITY;
110
        }
111
112 5
        if ($this->isAllowedFork) {
113 4
            $this->processesCount = $processesCount;
114
        } else {
115 1
            $this->processesCount = 1;
116
        }
117
118 5
        return $this;
119
    }
120
121
    /**
122
     * @return bool Returns TRUE if this is a child process, else - FALSE
123
     */
124 2
    protected function fork(): bool
125
    {
126 2
        if ($this->isAllowedFork) {
127 1
            return 0 === pcntl_fork();
128
        }
129
130 1
        return true;
131
    }
132
133
    /**
134
     * @codeCoverageIgnore
135
     *
136
     * @return bool
137
     */
138
    protected function terminate(): bool
139
    {
140
        if ($this->isAllowedFork) {
141
            return posix_kill(getmypid(), SIGKILL);
142
        }
143
144
        return true;
145
    }
146
147
    /**
148
     * Returns the optimal number of child processes.
149
     *
150
     * @return int
151
     */
152 2
    protected function getOptimalNumberOfChildProcesses(): int
153
    {
154 2
        $coreNumber = 1;
155
        $detectCommand = [
156 2
            'linux' => 'cat /proc/cpuinfo | grep processor | wc -l',
157
        ];
158
159 2
        $os = strtolower(trim(PHP_OS));
160
161 2
        if (isset($detectCommand[$os])) {
162 2
            $coreNumber = intval($this->execute($detectCommand[$os]));
163
        }
164
165 2
        return $coreNumber;
166
    }
167
168
    /**
169
     * @param string $command
170
     *
171
     * @return string
172
     */
173 3
    protected function execute(string $command): string
174
    {
175 3
        return trim(shell_exec($command));
176
    }
177
}
178