MediaWiki  1.23.8
CdbPHP.php
Go to the documentation of this file.
1 <?php
30 class CdbFunctions {
40  public static function unsignedMod( \$a, \$b ) {
41  if ( \$a & 0x80000000 ) {
42  \$m = ( \$a & 0x7fffffff ) % \$b + 2 * ( 0x40000000 % \$b );
43
44  return \$m % \$b;
45  } else {
46  return \$a % \$b;
47  }
48  }
49
56  public static function unsignedShiftRight( \$a, \$b ) {
57  if ( \$b == 0 ) {
58  return \$a;
59  }
60  if ( \$a & 0x80000000 ) {
61  return ( ( \$a & 0x7fffffff ) >> \$b ) | ( 0x40000000 >> ( \$b - 1 ) );
62  } else {
63  return \$a >> \$b;
64  }
65  }
66
74  public static function hash( \$s ) {
75  \$h = 5381;
76  \$len = strlen( \$s );
77  for ( \$i = 0; \$i < \$len; \$i++ ) {
78  \$h5 = ( \$h << 5 ) & 0xffffffff;
79  // Do a 32-bit sum
80  // Inlined here for speed
81  \$sum = ( \$h & 0x3fffffff ) + ( \$h5 & 0x3fffffff );
82  \$h =
83  (
84  ( \$sum & 0x40000000 ? 1 : 0 )
85  + ( \$h & 0x80000000 ? 2 : 0 )
86  + ( \$h & 0x40000000 ? 1 : 0 )
87  + ( \$h5 & 0x80000000 ? 2 : 0 )
88  + ( \$h5 & 0x40000000 ? 1 : 0 )
89  ) << 30
90  | ( \$sum & 0x3fffffff );
91  \$h ^= ord( \$s[\$i] );
92  \$h &= 0xffffffff;
93  }
94
95  return \$h;
96  }
97 }
98
105
106  /* number of hash slots searched under this key */
107  var \$loop;
108
109  /* initialized if loop is nonzero */
110  var \$khash;
111
112  /* initialized if loop is nonzero */
113  var \$kpos;
114
115  /* initialized if loop is nonzero */
116  var \$hpos;
117
118  /* initialized if loop is nonzero */
119  var \$hslots;
120
121  /* initialized if findNext() returns true */
122  var \$dpos;
123
124  /* initialized if cdb_findnext() returns 1 */
125  var \$dlen;
126
131  public function __construct( \$fileName ) {
132  \$this->fileName = \$fileName;
133  \$this->handle = fopen( \$fileName, 'rb' );
134  if ( !\$this->handle ) {
135  throw new CdbException( 'Unable to open CDB file "' . \$this->fileName . '".' );
136  }
137  \$this->findStart();
138  }
139
140  public function close() {
141  if ( isset( \$this->handle ) ) {
142  fclose( \$this->handle );
143  }
144  unset( \$this->handle );
145  }
146
151  public function get( \$key ) {
152  // strval is required
153  if ( \$this->find( strval( \$key ) ) ) {
154  return \$this->read( \$this->dlen, \$this->dpos );
155  } else {
156  return false;
157  }
158  }
159
165  protected function match( \$key, \$pos ) {
166  \$buf = \$this->read( strlen( \$key ), \$pos );
167
168  return \$buf === \$key;
169  }
170
171  protected function findStart() {
172  \$this->loop = 0;
173  }
174
181  protected function read( \$length, \$pos ) {
182  if ( fseek( \$this->handle, \$pos ) == -1 ) {
183  // This can easily happen if the internal pointers are incorrect
184  throw new CdbException(
185  'Seek failed, file "' . \$this->fileName . '" may be corrupted.' );
186  }
187
188  if ( \$length == 0 ) {
189  return '';
190  }
191
192  \$buf = fread( \$this->handle, \$length );
193  if ( \$buf === false || strlen( \$buf ) !== \$length ) {
194  throw new CdbException(
195  'Read from CDB file failed, file "' . \$this->fileName . '" may be corrupted.' );
196  }
197
198  return \$buf;
199  }
200
207  protected function unpack31( \$s ) {
208  \$data = unpack( 'V', \$s );
209  if ( \$data[1] > 0x7fffffff ) {
210  throw new CdbException(
211  'Error in CDB file "' . \$this->fileName . '", integer too big.' );
212  }
213
214  return \$data[1];
215  }
216
222  protected function unpackSigned( \$s ) {
223  \$data = unpack( 'va/vb', \$s );
224
225  return \$data['a'] | ( \$data['b'] << 16 );
226  }
227
232  protected function findNext( \$key ) {
233  if ( !\$this->loop ) {
234  \$u = CdbFunctions::hash( \$key );
235  \$buf = \$this->read( 8, ( \$u << 3 ) & 2047 );
236  \$this->hslots = \$this->unpack31( substr( \$buf, 4 ) );
237  if ( !\$this->hslots ) {
238  return false;
239  }
240  \$this->hpos = \$this->unpack31( substr( \$buf, 0, 4 ) );
241  \$this->khash = \$u;
242  \$u = CdbFunctions::unsignedShiftRight( \$u, 8 );
243  \$u = CdbFunctions::unsignedMod( \$u, \$this->hslots );
244  \$u <<= 3;
245  \$this->kpos = \$this->hpos + \$u;
246  }
247
248  while ( \$this->loop < \$this->hslots ) {
249  \$buf = \$this->read( 8, \$this->kpos );
250  \$pos = \$this->unpack31( substr( \$buf, 4 ) );
251  if ( !\$pos ) {
252  return false;
253  }
254  \$this->loop += 1;
255  \$this->kpos += 8;
256  if ( \$this->kpos == \$this->hpos + ( \$this->hslots << 3 ) ) {
257  \$this->kpos = \$this->hpos;
258  }
259  \$u = \$this->unpackSigned( substr( \$buf, 0, 4 ) );
260  if ( \$u === \$this->khash ) {
261  \$buf = \$this->read( 8, \$pos );
262  \$keyLen = \$this->unpack31( substr( \$buf, 0, 4 ) );
263  if ( \$keyLen == strlen( \$key ) && \$this->match( \$key, \$pos + 8 ) ) {
264  // Found
265  \$this->dlen = \$this->unpack31( substr( \$buf, 4 ) );
266  \$this->dpos = \$pos + 8 + \$keyLen;
267
268  return true;
269  }
270  }
271  }
272
273  return false;
274  }
275
280  protected function find( \$key ) {
281  \$this->findStart();
282
283  return \$this->findNext( \$key );
284  }
285 }
286
290 class CdbWriterPHP extends CdbWriter {
291  var \$hplist;
293
297  public function __construct( \$fileName ) {
298  \$this->realFileName = \$fileName;
299  \$this->tmpFileName = \$fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
300  \$this->handle = fopen( \$this->tmpFileName, 'wb' );
301  if ( !\$this->handle ) {
302  \$this->throwException(
303  'Unable to open CDB file "' . \$this->tmpFileName . '" for write.' );
304  }
305  \$this->hplist = array();
306  \$this->numentries = 0;
307  \$this->pos = 2048; // leaving space for the pointer array, 256 * 8
308  if ( fseek( \$this->handle, \$this->pos ) == -1 ) {
309  \$this->throwException( 'fseek failed in file "' . \$this->tmpFileName . '".' );
310  }
311  }
312
317  public function set( \$key, \$value ) {
318  if ( strval( \$key ) === '' ) {
319  // DBA cross-check hack
320  return;
321  }
322  \$this->addbegin( strlen( \$key ), strlen( \$value ) );
323  \$this->write( \$key );
324  \$this->write( \$value );
325  \$this->addend( strlen( \$key ), strlen( \$value ), CdbFunctions::hash( \$key ) );
326  }
327
331  public function close() {
332  \$this->finish();
333  if ( isset( \$this->handle ) ) {
334  fclose( \$this->handle );
335  }
336  if ( \$this->isWindows() && file_exists( \$this->realFileName ) ) {
338  }
339  if ( !rename( \$this->tmpFileName, \$this->realFileName ) ) {
340  \$this->throwException( 'Unable to move the new CDB file into place.' );
341  }
342  unset( \$this->handle );
343  }
344
349  protected function write( \$buf ) {
350  \$len = fwrite( \$this->handle, \$buf );
351  if ( \$len !== strlen( \$buf ) ) {
352  \$this->throwException( 'Error writing to CDB file "' . \$this->tmpFileName . '".' );
353  }
354  }
355
360  protected function posplus( \$len ) {
361  \$newpos = \$this->pos + \$len;
362  if ( \$newpos > 0x7fffffff ) {
363  \$this->throwException(
364  'A value in the CDB file "' . \$this->tmpFileName . '" is too large.' );
365  }
366  \$this->pos = \$newpos;
367  }
368
374  protected function addend( \$keylen, \$datalen, \$h ) {
375  \$this->hplist[] = array(
376  'h' => \$h,
377  'p' => \$this->pos
378  );
379
380  \$this->numentries++;
381  \$this->posplus( 8 );
382  \$this->posplus( \$keylen );
383  \$this->posplus( \$datalen );
384  }
385
391  protected function addbegin( \$keylen, \$datalen ) {
392  if ( \$keylen > 0x7fffffff ) {
393  \$this->throwException( 'Key length too long in file "' . \$this->tmpFileName . '".' );
394  }
395  if ( \$datalen > 0x7fffffff ) {
396  \$this->throwException( 'Data length too long in file "' . \$this->tmpFileName . '".' );
397  }
398  \$buf = pack( 'VV', \$keylen, \$datalen );
399  \$this->write( \$buf );
400  }
401
405  protected function finish() {
406  // Hack for DBA cross-check
407  \$this->hplist = array_reverse( \$this->hplist );
408
409  // Calculate the number of items that will be in each hashtable
410  \$counts = array_fill( 0, 256, 0 );
411  foreach ( \$this->hplist as \$item ) {
412  ++\$counts[255 & \$item['h']];
413  }
414
415  // Fill in \$starts with the *end* indexes
416  \$starts = array();
417  \$pos = 0;
418  for ( \$i = 0; \$i < 256; ++\$i ) {
419  \$pos += \$counts[\$i];
420  \$starts[\$i] = \$pos;
421  }
422
423  // Excessively clever and indulgent code to simultaneously fill \$packedTables
424  // with the packed hashtables, and adjust the elements of \$starts
425  // to actually point to the starts instead of the ends.
426  \$packedTables = array_fill( 0, \$this->numentries, false );
427  foreach ( \$this->hplist as \$item ) {
428  \$packedTables[--\$starts[255 & \$item['h']]] = \$item;
429  }
430
431  \$final = '';
432  for ( \$i = 0; \$i < 256; ++\$i ) {
433  \$count = \$counts[\$i];
434
435  // The size of the hashtable will be double the item count.
436  // The rest of the slots will be empty.
437  \$len = \$count + \$count;
438  \$final .= pack( 'VV', \$this->pos, \$len );
439
440  \$hashtable = array();
441  for ( \$u = 0; \$u < \$len; ++\$u ) {
442  \$hashtable[\$u] = array( 'h' => 0, 'p' => 0 );
443  }
444
445  // Fill the hashtable, using the next empty slot if the hashed slot
446  // is taken.
447  for ( \$u = 0; \$u < \$count; ++\$u ) {
448  \$hp = \$packedTables[\$starts[\$i] + \$u];
449  \$where = CdbFunctions::unsignedMod(
450  CdbFunctions::unsignedShiftRight( \$hp['h'], 8 ), \$len );
451  while ( \$hashtable[\$where]['p'] ) {
452  if ( ++\$where == \$len ) {
453  \$where = 0;
454  }
455  }
456  \$hashtable[\$where] = \$hp;
457  }
458
459  // Write the hashtable
460  for ( \$u = 0; \$u < \$len; ++\$u ) {
461  \$buf = pack( 'vvV',
462  \$hashtable[\$u]['h'] & 0xffff,
463  CdbFunctions::unsignedShiftRight( \$hashtable[\$u]['h'], 16 ),
464  \$hashtable[\$u]['p'] );
465  \$this->write( \$buf );
466  \$this->posplus( 8 );
467  }
468  }
469
470  // Write the pointer array at the start of the file
471  rewind( \$this->handle );
472  if ( ftell( \$this->handle ) != 0 ) {
473  \$this->throwException( 'Error rewinding to start of file "' . \$this->tmpFileName . '".' );
474  }
475  \$this->write( \$final );
476  }
477
484  protected function throwException( \$msg ) {
485  if ( \$this->handle ) {
486  fclose( \$this->handle );
488  }
489  throw new CdbException( \$msg );
490  }
491 }
close()
Close the file.
Definition: CdbPHP.php:140
CdbFunctions\unsignedShiftRight
static unsignedShiftRight( \$a, \$b)
Shift a signed integer right as if it were unsigned.
Definition: CdbPHP.php:56
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
CdbFunctions\hash
static hash( \$s)
The CDB hash function.
Definition: CdbPHP.php:74
CdbWriterPHP\close
close()
Definition: CdbPHP.php:331
\$s
\$s
Definition: mergeMessageFileList.php:156
CdbFunctions\unsignedMod
static unsignedMod( \$a, \$b)
Take a modulo of a signed integer as if it were an unsigned integer.
Definition: CdbPHP.php:40
\$khash
Definition: CdbPHP.php:110
findStart()
Definition: CdbPHP.php:171
Definition: CdbPHP.php:391
CdbWriterPHP\__construct
__construct( \$fileName)
Definition: CdbPHP.php:297
__construct( \$fileName)
Definition: CdbPHP.php:131
CdbWriterPHP\throwException
throwException( \$msg)
Clean up the temp file and throw an exception.
Definition: CdbPHP.php:484
findNext( \$key)
Definition: CdbPHP.php:232
CdbWriterPHP\\$hplist
\$hplist
Definition: CdbPHP.php:291
\$dlen
Definition: CdbPHP.php:125
CdbWriterPHP\\$numentries
\$numentries
Definition: CdbPHP.php:292
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
CdbWriterPHP\write
write( \$buf)
Definition: CdbPHP.php:349
\$dpos
Definition: CdbPHP.php:122
CdbFunctions
Common functions for readers and writers.
Definition: CdbPHP.php:30
CdbWriterPHP
CDB writer class.
Definition: CdbPHP.php:290
\$value
\$value
Definition: styleTest.css.php:45
CdbWriterPHP\posplus
posplus( \$len)
Definition: CdbPHP.php:360
unpackSigned( \$s)
Unpack a 32-bit signed integer.
Definition: CdbPHP.php:222
unpack31( \$s)
Unpack an unsigned integer and throw an exception if it needs more than 31 bits.
Definition: CdbPHP.php:207
CdbWriter\isWindows
isWindows()
Are we running on Windows?
Definition: Cdb.php:150
Definition: CdbPHP.php:102
\$count
\$count
Definition: UtfNormalTest2.php:96
Definition: Cdb.php:28
CdbException
Exception for Cdb errors.
Definition: Cdb.php:159
Definition: CdbPHP.php:181
match( \$key, \$pos)
Definition: CdbPHP.php:165
CdbWriter
Write to a CDB file.
Definition: Cdb.php:88
\$hslots
Definition: CdbPHP.php:119
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
CdbWriterPHP\\$pos
\$pos
Definition: CdbPHP.php:292
find( \$key)
Definition: CdbPHP.php:280
\$kpos
Definition: CdbPHP.php:113
\$loop
Definition: CdbPHP.php:107