Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 86 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
Metastore | |
0.00% |
0 / 79 |
|
0.00% |
0 / 5 |
342 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 32 |
|
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 | $status = $this->metaStore->createOrUpgradeIfNecessary(); |
71 | $this->unwrap( $status ); |
72 | } |
73 | |
74 | if ( $this->hasOption( 'version' ) ) { |
75 | $storeVersion = $this->metaStore->metastoreVersion(); |
76 | $runtimeVersion = $this->metaStore->runtimeVersion(); |
77 | if ( $storeVersion != $runtimeVersion ) { |
78 | $this->output( "mw_cirrus_metastore is running an old version ($storeVersion) " . |
79 | "please upgrade to $runtimeVersion by running metastore.php --upgrade\n" ); |
80 | } else { |
81 | $this->output( "mw_cirrus_metastore is up to date and running with version " . |
82 | "$storeVersion\n" ); |
83 | } |
84 | } elseif ( $this->hasOption( 'upgrade' ) ) { |
85 | $status = $this->metaStore->createOrUpgradeIfNecessary(); |
86 | $this->unwrap( $status ); |
87 | $this->output( "mw_cirrus_metastore is up and running with version " . |
88 | $this->metaStore->metastoreVersion() . "\n" ); |
89 | } elseif ( $this->hasOption( 'show-all-index-versions' ) ) { |
90 | $this->showIndexVersions(); |
91 | } elseif ( $this->hasOption( 'update-index-version' ) ) { |
92 | $baseName = $this->getOption( 'index-version-basename', |
93 | $this->getSearchConfig()->get( SearchConfig::INDEX_BASE_NAME ) ); |
94 | $this->updateIndexVersion( $baseName ); |
95 | } elseif ( $this->hasOption( 'show-index-version' ) ) { |
96 | // While it might seem like wiki would be a better option than basename, the update |
97 | // needs basename to generate document id's and we want |
98 | $baseName = $this->getOption( 'index-version-basename', |
99 | $this->getSearchConfig()->get( SearchConfig::INDEX_BASE_NAME ) ); |
100 | $this->showIndexVersions( $baseName ); |
101 | } else { |
102 | $this->maybeHelp( true ); |
103 | } |
104 | |
105 | return true; |
106 | } |
107 | |
108 | /** |
109 | * @param string|null $baseName |
110 | */ |
111 | private function showIndexVersions( $baseName = null ) { |
112 | $store = $this->metaStore->versionStore(); |
113 | $res = $store->findAll( $baseName ); |
114 | foreach ( $res as $r ) { |
115 | $data = $r->getData(); |
116 | $this->outputIndented( "index name: " . $data['index_name'] . "\n" ); |
117 | $this->outputIndented( " analysis version: {$data['analysis_maj']}.{$data['analysis_min']}\n" ); |
118 | $this->outputIndented( " mapping version: {$data['mapping_maj']}.{$data['mapping_min']}\n" ); |
119 | if ( isset( $data['mediawiki_version'] ) ) { |
120 | $this->outputIndented( " code version: {$data['mediawiki_version']} " . |
121 | "({$data['mediawiki_commit']}, Cirrus: {$data['cirrus_commit']})\n" ); |
122 | } |
123 | $this->outputIndented( " shards: {$data['shard_count']}\n" ); |
124 | } |
125 | } |
126 | |
127 | /** |
128 | * @param string $baseName |
129 | */ |
130 | private function updateIndexVersion( $baseName ) { |
131 | $this->outputIndented( "Updating tracking indexes..." ); |
132 | $this->metaStore->versionStore()->updateAll( $baseName ); |
133 | $this->output( "done\n" ); |
134 | } |
135 | |
136 | private function dump() { |
137 | if ( !$this->metaStore->cirrusReady() ) { |
138 | $this->fatalError( "Cannot dump metastore: index does not exists. Please run --upgrade first" ); |
139 | } |
140 | |
141 | $query = new \Elastica\Query(); |
142 | $query->setQuery( new \Elastica\Query\MatchAll() ); |
143 | $query->setSize( 100 ); |
144 | $query->setSource( true ); |
145 | $query->setSort( [ '_doc' ] ); |
146 | $search = $this->metaStore->elasticaIndex()->createSearch( $query ); |
147 | $scroll = new \Elastica\Scroll( $search, '15m' ); |
148 | foreach ( $scroll as $results ) { |
149 | foreach ( $results as $result ) { |
150 | $indexOp = [ |
151 | 'index' => [ |
152 | '_type' => $result->getType(), |
153 | '_id' => $result->getId(), |
154 | ] |
155 | ]; |
156 | fwrite( STDOUT, JSON::stringify( $indexOp ) . "\n" ); |
157 | fwrite( STDOUT, JSON::stringify( $result->getSource() ) . "\n" ); |
158 | } |
159 | } |
160 | } |
161 | } |
162 | |
163 | $maintClass = Metastore::class; |
164 | require_once RUN_MAINTENANCE_IF_MAIN; |