]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/cache/localisation/LCStoreCDB.php
MediaWiki 1.30.2
[autoinstalls/mediawiki.git] / includes / cache / localisation / LCStoreCDB.php
1 <?php
2 /**
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16  * http://www.gnu.org/copyleft/gpl.html
17  *
18  * @file
19  */
20 use Cdb\Exception;
21 use Cdb\Reader;
22 use Cdb\Writer;
23
24 /**
25  * LCStore implementation which stores data as a collection of CDB files in the
26  * directory given by $wgCacheDirectory. If $wgCacheDirectory is not set, this
27  * will throw an exception.
28  *
29  * Profiling indicates that on Linux, this implementation outperforms MySQL if
30  * the directory is on a local filesystem and there is ample kernel cache
31  * space. The performance advantage is greater when the DBA extension is
32  * available than it is with the PHP port.
33  *
34  * See Cdb.php and https://cr.yp.to/cdb.html
35  */
36 class LCStoreCDB implements LCStore {
37
38         /** @var Reader[] */
39         private $readers;
40
41         /** @var Writer */
42         private $writer;
43
44         /** @var string Current language code */
45         private $currentLang;
46
47         /** @var bool|string Cache directory. False if not set */
48         private $directory;
49
50         function __construct( $conf = [] ) {
51                 global $wgCacheDirectory;
52
53                 if ( isset( $conf['directory'] ) ) {
54                         $this->directory = $conf['directory'];
55                 } else {
56                         $this->directory = $wgCacheDirectory;
57                 }
58         }
59
60         public function get( $code, $key ) {
61                 if ( !isset( $this->readers[$code] ) ) {
62                         $fileName = $this->getFileName( $code );
63
64                         $this->readers[$code] = false;
65                         if ( file_exists( $fileName ) ) {
66                                 try {
67                                         $this->readers[$code] = Reader::open( $fileName );
68                                 } catch ( Exception $e ) {
69                                         wfDebug( __METHOD__ . ": unable to open cdb file for reading\n" );
70                                 }
71                         }
72                 }
73
74                 if ( !$this->readers[$code] ) {
75                         return null;
76                 } else {
77                         $value = false;
78                         try {
79                                 $value = $this->readers[$code]->get( $key );
80                         } catch ( Exception $e ) {
81                                 wfDebug( __METHOD__ . ": \Cdb\Exception caught, error message was "
82                                         . $e->getMessage() . "\n" );
83                         }
84                         if ( $value === false ) {
85                                 return null;
86                         }
87
88                         return unserialize( $value );
89                 }
90         }
91
92         public function startWrite( $code ) {
93                 if ( !file_exists( $this->directory ) ) {
94                         if ( !wfMkdirParents( $this->directory, null, __METHOD__ ) ) {
95                                 throw new MWException( "Unable to create the localisation store " .
96                                         "directory \"{$this->directory}\"" );
97                         }
98                 }
99
100                 // Close reader to stop permission errors on write
101                 if ( !empty( $this->readers[$code] ) ) {
102                         $this->readers[$code]->close();
103                 }
104
105                 try {
106                         $this->writer = Writer::open( $this->getFileName( $code ) );
107                 } catch ( Exception $e ) {
108                         throw new MWException( $e->getMessage() );
109                 }
110                 $this->currentLang = $code;
111         }
112
113         public function finishWrite() {
114                 // Close the writer
115                 try {
116                         $this->writer->close();
117                 } catch ( Exception $e ) {
118                         throw new MWException( $e->getMessage() );
119                 }
120                 $this->writer = null;
121                 unset( $this->readers[$this->currentLang] );
122                 $this->currentLang = null;
123         }
124
125         public function set( $key, $value ) {
126                 if ( is_null( $this->writer ) ) {
127                         throw new MWException( __CLASS__ . ': must call startWrite() before calling set()' );
128                 }
129                 try {
130                         $this->writer->set( $key, serialize( $value ) );
131                 } catch ( Exception $e ) {
132                         throw new MWException( $e->getMessage() );
133                 }
134         }
135
136         protected function getFileName( $code ) {
137                 if ( strval( $code ) === '' || strpos( $code, '/' ) !== false ) {
138                         throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
139                 }
140
141                 return "{$this->directory}/l10n_cache-$code.cdb";
142         }
143
144 }