1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
<?php
/**
* Native CDB file reader and writer
*
* @file
*/
/**
* Read from a CDB file.
* Native and pure PHP implementations are provided.
* http://cr.yp.to/cdb.html
*/
abstract class CdbReader {
/**
* Open a file and return a subclass instance
*
* @param $fileName string
*
* @return CdbReader
*/
public static function open( $fileName ) {
if ( self::haveExtension() ) {
return new CdbReader_DBA( $fileName );
} else {
wfDebug( "Warning: no dba extension found, using emulation.\n" );
return new CdbReader_PHP( $fileName );
}
}
/**
* Returns true if the native extension is available
*
* @return bool
*/
public static function haveExtension() {
if ( !function_exists( 'dba_handlers' ) ) {
return false;
}
$handlers = dba_handlers();
if ( !in_array( 'cdb', $handlers ) || !in_array( 'cdb_make', $handlers ) ) {
return false;
}
return true;
}
/**
* Construct the object and open the file
*/
abstract function __construct( $fileName );
/**
* Close the file. Optional, you can just let the variable go out of scope.
*/
abstract function close();
/**
* Get a value with a given key. Only string values are supported.
*
* @param $key string
*/
abstract public function get( $key );
}
/**
* Write to a CDB file.
* Native and pure PHP implementations are provided.
*/
abstract class CdbWriter {
/**
* Open a writer and return a subclass instance.
* The user must have write access to the directory, for temporary file creation.
*
* @param $fileName string
*
* @return CdbWriter_DBA|CdbWriter_PHP
*/
public static function open( $fileName ) {
if ( CdbReader::haveExtension() ) {
return new CdbWriter_DBA( $fileName );
} else {
wfDebug( "Warning: no dba extension found, using emulation.\n" );
return new CdbWriter_PHP( $fileName );
}
}
/**
* Create the object and open the file
*
* @param $fileName string
*/
abstract function __construct( $fileName );
/**
* Set a key to a given value. The value will be converted to string.
* @param $key string
* @param $value string
*/
abstract public function set( $key, $value );
/**
* Close the writer object. You should call this function before the object
* goes out of scope, to write out the final hashtables.
*/
abstract public function close();
}
/**
* Reader class which uses the DBA extension
*/
class CdbReader_DBA {
var $handle;
function __construct( $fileName ) {
$this->handle = dba_open( $fileName, 'r-', 'cdb' );
if ( !$this->handle ) {
throw new MWException( 'Unable to open CDB file "' . $fileName . '"' );
}
}
function close() {
if( isset($this->handle) )
dba_close( $this->handle );
unset( $this->handle );
}
function get( $key ) {
return dba_fetch( $key, $this->handle );
}
}
/**
* Writer class which uses the DBA extension
*/
class CdbWriter_DBA {
var $handle, $realFileName, $tmpFileName;
function __construct( $fileName ) {
$this->realFileName = $fileName;
$this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
$this->handle = dba_open( $this->tmpFileName, 'n', 'cdb_make' );
if ( !$this->handle ) {
throw new MWException( 'Unable to open CDB file for write "' . $fileName . '"' );
}
}
function set( $key, $value ) {
return dba_insert( $key, $value, $this->handle );
}
function close() {
if( isset($this->handle) )
dba_close( $this->handle );
if ( wfIsWindows() ) {
unlink( $this->realFileName );
}
if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
throw new MWException( 'Unable to move the new CDB file into place.' );
}
unset( $this->handle );
}
function __destruct() {
if ( isset( $this->handle ) ) {
$this->close();
}
}
}
|