Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 84 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
Metastore | |
0.00% |
0 / 77 |
|
0.00% |
0 / 5 |
342 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
90 | |||
showIndexVersions | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
12 | |||
updateIndexVersion | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
dump | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | |
3 | namespace CirrusSearch\Maintenance; |
4 | |
5 | use CirrusSearch\MetaStore\MetaStoreIndex; |
6 | use CirrusSearch\SearchConfig; |
7 | use Elastica\JSON; |
8 | |
9 | /** |
10 | * Update and check the CirrusSearch metastore index. |
11 | * |
12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by |
14 | * the Free Software Foundation; either version 2 of the License, or |
15 | * (at your option) any later version. |
16 | * |
17 | * This program 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 | * You should have received a copy of the GNU General Public License along |
23 | * with this program; if not, write to the Free Software Foundation, Inc., |
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
25 | * http://www.gnu.org/copyleft/gpl.html |
26 | */ |
27 | |
28 | $IP = getenv( 'MW_INSTALL_PATH' ); |
29 | if ( $IP === false ) { |
30 | $IP = __DIR__ . '/../../..'; |
31 | } |
32 | require_once "$IP/maintenance/Maintenance.php"; |
33 | require_once __DIR__ . '/../includes/Maintenance/Maintenance.php'; |
34 | |
35 | class Metastore extends Maintenance { |
36 | /** |
37 | * @var MetaStoreIndex |
38 | */ |
39 | private $metaStore; |
40 | |
41 | public function __construct() { |
42 | parent::__construct(); |
43 | $this->addDescription( 'Update and check the CirrusSearch metastore index. ' . |
44 | 'Always operates on a single cluster.' ); |
45 | $this->addOption( 'upgrade', 'Create or upgrade the metastore index.' ); |
46 | $this->addOption( 'show-all-index-versions', |
47 | 'Show all versions for all indices managed by this cluster.' ); |
48 | $this->addOption( 'show-index-version', 'Show index versions for this wiki.' ); |
49 | $this->addOption( 'update-index-version', 'Update the version ' . |
50 | 'index for this wiki. Dangerous: index versions should be managed ' . |
51 | 'by updateSearchIndexConfig.php.' ); |
52 | $this->addOption( 'index-version-basename', 'What basename to use when running --show-index-version ' . |
53 | 'or --update-index-version, ' . |
54 | 'defaults to wiki id', false, true ); |
55 | $this->addOption( 'dump', 'Dump the metastore index to stdout (elasticsearch bulk index format).' ); |
56 | } |
57 | |
58 | public function execute() { |
59 | $this->metaStore = $this->getMetaStore(); |
60 | |
61 | if ( $this->hasOption( 'dump' ) ) { |
62 | $this->dump(); |
63 | return true; |
64 | } |
65 | |
66 | // Check if the metastore is usable |
67 | if ( !$this->metaStore->cirrusReady() ) { |
68 | // This is certainly a fresh install we need to create |
69 | // the metastore otherwize updateSearchIndexConfig will fail |
70 | $this->metaStore->createOrUpgradeIfNecessary(); |
71 | } |
72 | |
73 | if ( $this->hasOption( 'version' ) ) { |
74 | $storeVersion = $this->metaStore->metastoreVersion(); |
75 | $runtimeVersion = $this->metaStore->runtimeVersion(); |
76 | if ( $storeVersion != $runtimeVersion ) { |
77 | $this->output( "mw_cirrus_metastore is running an old version ($storeVersion) " . |
78 | "please upgrade to $runtimeVersion by running metastore.php --upgrade\n" ); |
79 | } else { |
80 | $this->output( "mw_cirrus_metastore is up to date and running with version " . |
81 | "$storeVersion\n" ); |
82 | } |
83 | } elseif ( $this->hasOption( 'upgrade' ) ) { |
84 | $this->metaStore->createOrUpgradeIfNecessary(); |
85 | $this->output( "mw_cirrus_metastore is up and running with version " . |
86 | $this->metaStore->metastoreVersion() . "\n" ); |
87 | } elseif ( $this->hasOption( 'show-all-index-versions' ) ) { |
88 | $this->showIndexVersions(); |
89 | } elseif ( $this->hasOption( 'update-index-version' ) ) { |
90 | $baseName = $this->getOption( 'index-version-basename', |
91 | $this->getSearchConfig()->get( SearchConfig::INDEX_BASE_NAME ) ); |
92 | $this->updateIndexVersion( $baseName ); |
93 | } elseif ( $this->hasOption( 'show-index-version' ) ) { |
94 | // While it might seem like wiki would be a better option than basename, the update |
95 | // needs basename to generate document id's and we want |
96 | $baseName = $this->getOption( 'index-version-basename', |
97 | $this->getSearchConfig()->get( SearchConfig::INDEX_BASE_NAME ) ); |
98 | $this->showIndexVersions( $baseName ); |
99 | } else { |
100 | $this->maybeHelp( true ); |
101 | } |
102 | |
103 | return true; |
104 | } |
105 | |
106 | /** |
107 | * @param string|null $baseName |
108 | */ |
109 | private function showIndexVersions( $baseName = null ) { |
110 | $store = $this->metaStore->versionStore(); |
111 | $res = $store->findAll( $baseName ); |
112 | foreach ( $res as $r ) { |
113 | $data = $r->getData(); |
114 | $this->outputIndented( "index name: " . $data['index_name'] . "\n" ); |
115 | $this->outputIndented( " analysis version: {$data['analysis_maj']}.{$data['analysis_min']}\n" ); |
116 | $this->outputIndented( " mapping version: {$data['mapping_maj']}.{$data['mapping_min']}\n" ); |
117 | if ( isset( $data['mediawiki_version'] ) ) { |
118 | $this->outputIndented( " code version: {$data['mediawiki_version']} " . |
119 | "({$data['mediawiki_commit']}, Cirrus: {$data['cirrus_commit']})\n" ); |
120 | } |
121 | $this->outputIndented( " shards: {$data['shard_count']}\n" ); |
122 | } |
123 | } |
124 | |
125 | /** |
126 | * @param string $baseName |
127 | */ |
128 | private function updateIndexVersion( $baseName ) { |
129 | $this->outputIndented( "Updating tracking indexes..." ); |
130 | $this->metaStore->versionStore()->updateAll( $baseName ); |
131 | $this->output( "done\n" ); |
132 | } |
133 | |
134 | private function dump() { |
135 | if ( !$this->metaStore->cirrusReady() ) { |
136 | $this->fatalError( "Cannot dump metastore: index does not exists. Please run --upgrade first" ); |
137 | } |
138 | |
139 | $query = new \Elastica\Query(); |
140 | $query->setQuery( new \Elastica\Query\MatchAll() ); |
141 | $query->setSize( 100 ); |
142 | $query->setSource( true ); |
143 | $query->setSort( [ '_doc' ] ); |
144 | $search = $this->metaStore->elasticaIndex()->createSearch( $query ); |
145 | $scroll = new \Elastica\Scroll( $search, '15m' ); |
146 | foreach ( $scroll as $results ) { |
147 | foreach ( $results as $result ) { |
148 | $indexOp = [ |
149 | 'index' => [ |
150 | '_type' => $result->getType(), |
151 | '_id' => $result->getId(), |
152 | ] |
153 | ]; |
154 | fwrite( STDOUT, JSON::stringify( $indexOp ) . "\n" ); |
155 | fwrite( STDOUT, JSON::stringify( $result->getSource() ) . "\n" ); |
156 | } |
157 | } |
158 | } |
159 | } |
160 | |
161 | $maintClass = Metastore::class; |
162 | require_once RUN_MAINTENANCE_IF_MAIN; |