Completed
Push — non_purge_indexer ( 4e290b...6bd5a6 )
by André
15:17
created

ReindexCommand::executeParallel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 4
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the eZ Publish Kernel package.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Bundle\EzPublishCoreBundle\Command;
10
11
use eZ\Publish\Core\Search\Common\IterativelyIndexer;
12
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Process\Process;
17
use Symfony\Component\Process\PhpExecutableFinder;
18
use eZ\Publish\Core\Search\Common\Indexer;
19
use ezcSystemInfo;
20
use RuntimeException;
21
22
class ReindexCommand extends ContainerAwareCommand
23
{
24
    /**
25
     * @var \eZ\Publish\Core\Search\Common\Indexer
26
     */
27
    private $searchIndexer;
28
29
    /**
30
     * Initialize objects required by {@see execute()}.
31
     *
32
     * @param InputInterface $input
33
     * @param OutputInterface $output
34
     */
35
    public function initialize(InputInterface $input, OutputInterface $output)
36
    {
37
        parent::initialize($input, $output);
38
        $this->searchIndexer = $this->getContainer()->get('ezpublish.spi.search.indexer');
39
        if (!$this->searchIndexer instanceof Indexer) {
40
            throw new RuntimeException(
41
                sprintf('Expected to find Search Engine Indexer but found "%s" instead', get_parent_class($this->searchIndexer))
42
            );
43
        }
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    protected function configure()
50
    {
51
        $this
52
            ->setName('ezplatform:reindex')
53
            ->setDescription('Recreate or Refresh search engine index')
54
            ->addOption('iteration-count', 'c', InputOption::VALUE_OPTIONAL, 'Number of objects to be indexed in a single iteration, for avoiding using to much memory', 20)
55
            ->addOption('no-commit', null, InputOption::VALUE_NONE, 'Do not commit after each iteration')
56
            ->addOption('no-purge', null, InputOption::VALUE_NONE, 'Do not purge before indexing. BC NOTE: Should this be default as of 2.0?')
57
            ->addOption('since', null, InputOption::VALUE_NONE, 'Index changes since a given time, any format understood by DateTime. Implies "no-purge", can not be combined with "content-ids".')
58
            ->addOption('content-ids', null, InputOption::VALUE_NONE, 'Comma separated list of content id\'s to refresh (deleted or updated/added). Implies "no-purge", can not be combined with "since".')
59
            ->addOption('processes', null, InputOption::VALUE_NONE, 'Number of sub processes to spawn in parallel, by default: (number of cpu cores)-1, disable by setting to "0"', $this->getNumberOfCPUCores() -1)
60
            ->setHelp(
61
                <<<EOT
62
The command <info>%command.name%</info> indexes current configured database in configured search engine index.
63
64
65
TODO: ADD EXAMPLES OF ADVANCE USAGE!
66
67
EOT
68
            );
69
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74
    protected function execute(InputInterface $input, OutputInterface $output)
75
    {
76
        $noCommit = $input->getOption('no-commit');
77
        $iterationCount = $input->getOption('iteration-count');
78
        if (!is_numeric($iterationCount) || (int) $iterationCount < 1) {
79
            throw new RuntimeException("'--iteration-count' option should be > 0, got '{$iterationCount}'");
80
        }
81
82
83
        if ($this->searchIndexer instanceof IterativelyIndexer) {
84
            return $this->executeParallel($input, $output, (int) $iterationCount, (bool) $noCommit);
85
        }
86
87
        $output->writeln( <<<EOT
88
DEPRECATED:
89
Running indexing against an Indexer that has not been updated to use IterativelyIndexer abstract, options that won't be
90
taken into account:
91
- since
92
- content-ids
93
- processes
94
- no-purge
95
EOT
96
        );
97
        $this->searchIndexer->createSearchIndex($output, (int) $iterationCount, empty($noCommit));
98
    }
99
100
101
    private function executeParallel(InputInterface $input, OutputInterface $output, $iterationCount, $noCommit) {
0 ignored issues
show
Unused Code introduced by
The parameter $output is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $iterationCount is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $noCommit is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
102
        $since = $input->getOption('since');
0 ignored issues
show
Unused Code introduced by
$since is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
103
        $contentIds = $input->getOption('content-ids');
0 ignored issues
show
Unused Code introduced by
$contentIds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
104
        $processes = $input->getOption('processes');
0 ignored issues
show
Unused Code introduced by
$processes is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
105
        $noPurge = $input->getOption('no-purge');
0 ignored issues
show
Unused Code introduced by
$noPurge is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
106
107
108
    }
109
110
111
    private static function getPhpProcess($consoleDir = 'app')
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
112
    {
113
        $phpFinder = new PhpExecutableFinder();
114
        if (!$phpPath = $phpFinder->find()) {
115
            throw new \RuntimeException('The php executable could not be found, add it to your PATH environment variable and try again');
116
        }
117
118
        $cmd = 'ezplatform:reindex';
119
        $php = escapeshellarg($phpFinder);
120
        $console = escapeshellarg($consoleDir.'/console');
121
122
        return new Process($php.' '.$console.' '.$cmd, null, null, null, null);
123
    }
124
125
    private function getNumberOfCPUCores()
126
    {
127
        $cores = 1;
128
        if (is_file('/proc/cpuinfo')) {
129
            // Linux (and potentially Windows with linux sub systems)
130
            $cpuinfo = file_get_contents('/proc/cpuinfo');
131
            preg_match_all('/^processor/m', $cpuinfo, $matches);
132
            $cores = count($matches[0]);
133
        } else if (DIRECTORY_SEPARATOR === '\\') {
134
            // Windows
135
            if (($process = @popen('wmic cpu get NumberOfCores', 'rb')) !== false) {
136
                fgets($process);
137
                $cores = (int) fgets($process);
138
                pclose($process);
139
            }
140
        } else {
141
            // *nix (Linux, BSD and Mac)
142
            if (($process = @popen('sysctl -a', 'rb')) !== false) {
143
                $output = stream_get_contents($process);
144
                if (preg_match('/hw.ncpu: (\d+)/', $output, $matches)) {
145
                    $cores = (int) $matches[1][0];
146
                }
147
                pclose($process);
148
            }
149
        }
150
151
        return $cores;
152
    }
153
}
154