Test Failed
Push — 6-0 ( cfb4d5 )
by Tomas Norre
03:23
created

startRequiredProcesses()   C

Complexity

Conditions 8
Paths 17

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 18
nc 17
nop 0
dl 0
loc 26
rs 5.3846
c 1
b 0
f 0
1
<?php
2
/***************************************************************
3
 *  Copyright notice
4
 *
5
 *  (c) 2009 AOE media ([email protected])
6
 *  All rights reserved
7
 *
8
 *  This script is part of the TYPO3 project. The TYPO3 project is
9
 *  free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  (at your option) any later version.
13
 *
14
 *  The GNU General Public License can be found at
15
 *  http://www.gnu.org/copyleft/gpl.html.
16
 *
17
 *  This script is distributed in the hope that it will be useful,
18
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 *  GNU General Public License for more details.
21
 *
22
 *  This copyright notice MUST APPEAR in all copies of the script!
23
 ***************************************************************/
24
25
/**
26
 * Manages cralwer processes and can be used to start a new process or multiple processes
27
 *
28
 */
29
class tx_crawler_domain_process_manager
30
{
31
    /**
32
     * @var $timeToLive integer
33
     */
34
    private $timeToLive;
35
36
    /**
37
     * @var integer
38
     */
39
    private $countInARun;
40
41
    /**
42
     * @var integer
43
     */
44
    private $processLimit;
45
46
    /**
47
     * @var $crawlerObj tx_crawler_lib
48
     */
49
    private $crawlerObj;
50
51
    /**
52
     * @var $queueRepository tx_crawler_domain_queue_repository
53
     */
54
    private $queueRepository;
55
56
    /**
57
     * @var tx_crawler_domain_process_repository
58
     */
59
    private $processRepository;
60
61
    /**
62
     * @var $verbose boolean
63
     */
64
    private $verbose;
65
66
    /**
67
     * the constructor
68
     */
69
    public function __construct()
70
    {
71
        $this->processRepository = new tx_crawler_domain_process_repository();
72
        $this->queueRepository = new tx_crawler_domain_queue_repository();
73
        $this->crawlerObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_crawler_lib');
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Utility\GeneralUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
74
        $this->timeToLive = intval($this->crawlerObj->extensionSettings['processMaxRunTime']);
75
        $this->countInARun = intval($this->crawlerObj->extensionSettings['countInARun']);
76
        $this->processLimit = intval($this->crawlerObj->extensionSettings['processLimit']);
77
        $this->verbose = intval($this->crawlerObj->extensionSettings['processVerbose']);
78
    }
79
80
    /**
81
     * starts multiple processes
82
     *
83
     * @param integer $timeout
84
     *
85
     * @throws RuntimeException
86
     */
87
    public function multiProcess($timeout)
88
    {
89
        if ($this->processLimit <= 1) {
90
            throw new RuntimeException('To run crawler in multi process mode you have to configure the processLimit > 1.' . PHP_EOL);
91
        }
92
93
        $pendingItemsStart = $this->queueRepository->countAllPendingItems();
94
        $itemReportLimit = 20;
95
        $reportItemCount = $pendingItemsStart - $itemReportLimit;
96
        if ($this->verbose) {
97
            $this->reportItemStatus();
98
        }
99
        $this->startRequiredProcesses();
100
        $nextTimeOut = time() + $this->timeToLive;
101
        for ($i = 0; $i < $timeout; $i++) {
102
            $currentPendingItems = $this->queueRepository->countAllPendingItems();
103
            if ($this->startRequiredProcesses($this->verbose)) {
0 ignored issues
show
Unused Code introduced by
The call to tx_crawler_domain_proces...tartRequiredProcesses() has too many arguments starting with $this->verbose. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
            if ($this->/** @scrutinizer ignore-call */ startRequiredProcesses($this->verbose)) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
104
                $nextTimeOut = time() + $this->timeToLive;
105
            }
106
            if ($currentPendingItems == 0) {
107
                if ($this->verbose) {
108
                    echo 'Finished...' . chr(10);
109
                }
110
                break;
111
            }
112
            if ($currentPendingItems < $reportItemCount) {
113
                if ($this->verbose) {
114
                    $this->reportItemStatus();
115
                }
116
                $reportItemCount = $currentPendingItems - $itemReportLimit;
117
            }
118
            sleep(1);
119
            if ($nextTimeOut < time()) {
120
                $timedOutProcesses = $this->processRepository->findAll('', 'DESC', null, 0, 'ttl >' . $nextTimeOut);
121
                $nextTimeOut = time() + $this->timeToLive;
122
                if ($this->verbose) {
123
                    echo 'Cleanup' . implode(',', $timedOutProcesses->getProcessIds()) . chr(10);
124
                }
125
                $this->crawlerObj->CLI_releaseProcesses($timedOutProcesses->getProcessIds(), true);
126
            }
127
        }
128
        if ($currentPendingItems > 0 && $this->verbose) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $currentPendingItems does not seem to be defined for all execution paths leading up to this point.
Loading history...
129
            echo 'Stop with timeout' . chr(10);
130
        }
131
    }
132
133
    /**
134
     * Reports curent Status of queue
135
     */
136
    protected function reportItemStatus()
137
    {
138
        echo 'Pending:' . $this->queueRepository->countAllPendingItems() . ' / Assigned:' . $this->queueRepository->countAllAssignedPendingItems() . chr(10);
139
    }
140
141
    /**
142
     * according to the given count of pending items and the countInARun Setting this method
143
     * starts more crawling processes
144
     * @return boolean if processes are started
145
     */
146
    private function startRequiredProcesses()
147
    {
148
        $ret = false;
149
        $currentProcesses = $this->processRepository->countActive();
150
        $availableProcessesCount = $this->processLimit - $currentProcesses;
151
        $requiredProcessesCount = ceil($this->queueRepository->countAllUnassignedPendingItems() / $this->countInARun);
152
        $startProcessCount = min([$availableProcessesCount,$requiredProcessesCount]);
153
        if ($startProcessCount <= 0) {
154
            return $ret;
155
        }
156
        if ($startProcessCount && $this->verbose) {
157
            echo 'Start ' . $startProcessCount . ' new processes (Running:' . $currentProcesses . ')';
158
        }
159
        for ($i = 0;$i < $startProcessCount;$i++) {
160
            usleep(100);
161
            if ($this->startProcess()) {
162
                if ($this->verbose) {
163
                    echo '.';
164
                    $ret = true;
165
                }
166
            }
167
        }
168
        if ($this->verbose) {
169
            echo chr(10);
170
        }
171
        return $ret;
172
    }
173
174
    /**
175
     * starts new process
176
     * @throws Exception if no crawlerprocess was started
177
     */
178
    public function startProcess()
179
    {
180
        $ttl = (time() + $this->timeToLive - 1);
181
        $current = $this->processRepository->countNotTimeouted($ttl);
182
        $completePath = '(' . escapeshellcmd($this->getCrawlerCliPath()) . ' &) > /dev/null';
183
        if (system($completePath) === false) {
184
            throw new Exception('could not start process!');
185
        } else {
186
            for ($i = 0;$i < 10;$i++) {
187
                if ($this->processRepository->countNotTimeouted($ttl) > $current) {
188
                    return true;
189
                }
190
                sleep(1);
191
            }
192
            throw new Exception('Something went wrong: process did not appear within 10 seconds.');
193
        }
194
    }
195
196
    /**
197
     * Returns the path to start the crawler from the command line
198
     *
199
     * @return string
200
     */
201
    public function getCrawlerCliPath()
202
    {
203
        $phpPath = $this->crawlerObj->extensionSettings['phpPath'] . ' ';
204
        $pathToTypo3 = rtrim(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_DOCUMENT_ROOT'), '/');
205
        $pathToTypo3 .= rtrim(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'), '/');
206
        $cliPart = '/typo3/cli_dispatch.phpsh crawler';
207
        return $phpPath . $pathToTypo3 . $cliPart;
208
    }
209
}
210