Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 35 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
CDBMessageIndex | |
0.00% |
0 / 35 |
|
0.00% |
0 / 5 |
182 | |
0.00% |
0 / 1 |
retrieve | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
getKeys | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
get | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
store | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
getReader | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace MediaWiki\Extension\Translate\MessageLoading; |
5 | |
6 | use Cdb\Reader; |
7 | use Cdb\Writer; |
8 | use MediaWiki\Extension\Translate\Utilities\Utilities; |
9 | |
10 | /** |
11 | * Storage on CDB files. |
12 | * |
13 | * This is improved version of SerializedMessageIndex. It uses CDB files |
14 | * for storage, which means it provides random access. The CDB files are |
15 | * about double the size of serialized files (~7M for 50000 keys). |
16 | * |
17 | * Loading the whole index is slower than serialized, but about the same |
18 | * as for database. Suitable for single-server setups where |
19 | * SerializedMessageIndex is too slow for loading the whole index. |
20 | */ |
21 | class CDBMessageIndex extends MessageIndex { |
22 | private ?array $index = null; |
23 | private ?Reader $reader = null; |
24 | private const FILENAME = 'translate_messageindex.cdb'; |
25 | |
26 | public function retrieve( bool $readLatest = false ): array { |
27 | $reader = $this->getReader(); |
28 | // This must be below the line above, which may fill the index |
29 | if ( $this->index !== null ) { |
30 | return $this->index; |
31 | } |
32 | |
33 | $this->index = []; |
34 | foreach ( $this->getKeys() as $key ) { |
35 | $this->index[$key] = $this->unserialize( $reader->get( $key ) ); |
36 | } |
37 | |
38 | return $this->index; |
39 | } |
40 | |
41 | public function getKeys(): array { |
42 | $reader = $this->getReader(); |
43 | $keys = []; |
44 | $key = $reader->firstkey(); |
45 | while ( $key !== false ) { |
46 | $keys[] = $key; |
47 | $key = $reader->nextkey(); |
48 | } |
49 | |
50 | return $keys; |
51 | } |
52 | |
53 | /** @inheritDoc */ |
54 | protected function get( $key ) { |
55 | $reader = $this->getReader(); |
56 | // We might have the full cache loaded |
57 | if ( $this->index !== null ) { |
58 | return $this->index[$key] ?? null; |
59 | } |
60 | |
61 | $value = $reader->get( $key ); |
62 | return is_string( $value ) ? $this->unserialize( $value ) : null; |
63 | } |
64 | |
65 | /** @inheritDoc */ |
66 | protected function store( array $array, array $diff ): void { |
67 | $this->reader = null; |
68 | |
69 | $file = Utilities::cacheFile( self::FILENAME ); |
70 | $cache = Writer::open( $file ); |
71 | |
72 | foreach ( $array as $key => $value ) { |
73 | $value = $this->serialize( $value ); |
74 | $cache->set( $key, $value ); |
75 | } |
76 | |
77 | $cache->close(); |
78 | |
79 | $this->index = $array; |
80 | } |
81 | |
82 | private function getReader() { |
83 | if ( $this->reader ) { |
84 | return $this->reader; |
85 | } |
86 | |
87 | $file = Utilities::cacheFile( self::FILENAME ); |
88 | if ( !file_exists( $file ) ) { |
89 | // Create an empty index to allow rebuild |
90 | $this->store( [], [] ); |
91 | $this->index = $this->rebuild(); |
92 | } |
93 | |
94 | $this->reader = Reader::open( $file ); |
95 | return $this->reader; |
96 | } |
97 | } |