MediaWiki
REL1_20
|
00001 <?php 00035 class DBABagOStuff extends BagOStuff { 00036 var $mHandler, $mFile, $mReader, $mWriter, $mDisabled; 00037 00041 public function __construct( $params ) { 00042 global $wgDBAhandler; 00043 00044 if ( !isset( $params['dir'] ) ) { 00045 $params['dir'] = wfTempDir(); 00046 } 00047 00048 $this->mFile = $params['dir'] . '/mw-cache-' . wfWikiID() . '.db'; 00049 wfDebug( __CLASS__ . ": using cache file {$this->mFile}\n" ); 00050 $this->mHandler = $wgDBAhandler; 00051 } 00052 00060 protected function encode( $value, $expiry ) { 00061 # Convert to absolute time 00062 $expiry = $this->convertExpiry( $expiry ); 00063 00064 return sprintf( '%010u', intval( $expiry ) ) . ' ' . serialize( $value ); 00065 } 00066 00071 protected function decode( $blob ) { 00072 if ( !is_string( $blob ) ) { 00073 return array( false, 0 ); 00074 } else { 00075 return array( 00076 unserialize( substr( $blob, 11 ) ), 00077 intval( substr( $blob, 0, 10 ) ) 00078 ); 00079 } 00080 } 00081 00085 protected function getReader() { 00086 if ( file_exists( $this->mFile ) ) { 00087 $handle = dba_open( $this->mFile, 'rl', $this->mHandler ); 00088 } else { 00089 $handle = $this->getWriter(); 00090 } 00091 00092 if ( !$handle ) { 00093 wfDebug( "Unable to open DBA cache file {$this->mFile}\n" ); 00094 } 00095 00096 return $handle; 00097 } 00098 00102 protected function getWriter() { 00103 $handle = dba_open( $this->mFile, 'cl', $this->mHandler ); 00104 00105 if ( !$handle ) { 00106 wfDebug( "Unable to open DBA cache file {$this->mFile}\n" ); 00107 } 00108 00109 return $handle; 00110 } 00111 00116 public function get( $key ) { 00117 wfProfileIn( __METHOD__ ); 00118 wfDebug( __METHOD__ . "($key)\n" ); 00119 00120 $handle = $this->getReader(); 00121 if ( !$handle ) { 00122 wfProfileOut( __METHOD__ ); 00123 return false; 00124 } 00125 00126 $val = dba_fetch( $key, $handle ); 00127 list( $val, $expiry ) = $this->decode( $val ); 00128 00129 # Must close ASAP because locks are held 00130 dba_close( $handle ); 00131 00132 if ( $val !== false && $expiry && $expiry < time() ) { 00133 # Key is expired, delete it 00134 $handle = $this->getWriter(); 00135 dba_delete( $key, $handle ); 00136 dba_close( $handle ); 00137 wfDebug( __METHOD__ . ": $key expired\n" ); 00138 $val = false; 00139 } 00140 00141 wfProfileOut( __METHOD__ ); 00142 return $val; 00143 } 00144 00151 public function set( $key, $value, $exptime = 0 ) { 00152 wfProfileIn( __METHOD__ ); 00153 wfDebug( __METHOD__ . "($key)\n" ); 00154 00155 $blob = $this->encode( $value, $exptime ); 00156 00157 $handle = $this->getWriter(); 00158 if ( !$handle ) { 00159 wfProfileOut( __METHOD__ ); 00160 return false; 00161 } 00162 00163 $ret = dba_replace( $key, $blob, $handle ); 00164 dba_close( $handle ); 00165 00166 wfProfileOut( __METHOD__ ); 00167 return $ret; 00168 } 00169 00175 public function delete( $key, $time = 0 ) { 00176 wfProfileIn( __METHOD__ ); 00177 wfDebug( __METHOD__ . "($key)\n" ); 00178 00179 $handle = $this->getWriter(); 00180 if ( !$handle ) { 00181 wfProfileOut( __METHOD__ ); 00182 return false; 00183 } 00184 00185 $ret = !dba_exists( $key, $handle ) || dba_delete( $key, $handle ); 00186 dba_close( $handle ); 00187 00188 wfProfileOut( __METHOD__ ); 00189 return $ret; 00190 } 00191 00198 public function add( $key, $value, $exptime = 0 ) { 00199 wfProfileIn( __METHOD__ ); 00200 00201 $blob = $this->encode( $value, $exptime ); 00202 00203 $handle = $this->getWriter(); 00204 00205 if ( !$handle ) { 00206 wfProfileOut( __METHOD__ ); 00207 return false; 00208 } 00209 00210 $ret = dba_insert( $key, $blob, $handle ); 00211 00212 # Insert failed, check to see if it failed due to an expired key 00213 if ( !$ret ) { 00214 list( $value, $expiry ) = $this->decode( dba_fetch( $key, $handle ) ); 00215 00216 if ( $expiry && $expiry < time() ) { 00217 # Yes expired, delete and try again 00218 dba_delete( $key, $handle ); 00219 $ret = dba_insert( $key, $blob, $handle ); 00220 # This time if it failed then it will be handled by the caller like any other race 00221 } 00222 } 00223 00224 dba_close( $handle ); 00225 00226 wfProfileOut( __METHOD__ ); 00227 return $ret; 00228 } 00229 00235 public function incr( $key, $step = 1 ) { 00236 wfProfileIn( __METHOD__ ); 00237 00238 $handle = $this->getWriter(); 00239 00240 if ( !$handle ) { 00241 wfProfileOut( __METHOD__ ); 00242 return false; 00243 } 00244 00245 list( $value, $expiry ) = $this->decode( dba_fetch( $key, $handle ) ); 00246 if ( $value !== false ) { 00247 if ( $expiry && $expiry < time() ) { 00248 # Key is expired, delete it 00249 dba_delete( $key, $handle ); 00250 wfDebug( __METHOD__ . ": $key expired\n" ); 00251 $value = false; 00252 } else { 00253 $value += $step; 00254 $blob = $this->encode( $value, $expiry ); 00255 00256 $ret = dba_replace( $key, $blob, $handle ); 00257 $value = $ret ? $value : false; 00258 } 00259 } 00260 00261 dba_close( $handle ); 00262 00263 wfProfileOut( __METHOD__ ); 00264 00265 return ( $value === false ) ? false : (int)$value; 00266 } 00267 00268 function keys() { 00269 $reader = $this->getReader(); 00270 $k1 = dba_firstkey( $reader ); 00271 00272 if ( !$k1 ) { 00273 return array(); 00274 } 00275 00276 $result[] = $k1; 00277 00278 $key = dba_nextkey( $reader ); 00279 while ( $key ) { 00280 $result[] = $key; 00281 $key = dba_nextkey( $reader ); 00282 } 00283 00284 return $result; 00285 } 00286 }