MediaWiki  1.23.13
backupTextPass.inc
Go to the documentation of this file.
1 <?php
27 require_once __DIR__ . '/backup.inc';
28 
33  var $prefetch = null;
34  var $input = "php://stdin";
36  var $fetchCount = 0;
37  var $prefetchCount = 0;
39  var $fetchCountLast = 0;
40 
41  var $maxFailures = 5;
43  var $failureTimeout = 5; // Seconds to sleep after db failure
44 
45  var $php = "php";
46  var $spawn = false;
47 
51  var $spawnProc = false;
52 
56  var $spawnWrite = false;
57 
61  var $spawnRead = false;
62 
66  var $spawnErr = false;
67 
68  var $xmlwriterobj = false;
69 
70  // when we spend more than maxTimeAllowed seconds on this run, we continue
71  // processing until we write out the next complete page, then save output file(s),
72  // rename it/them and open new one(s)
73  var $maxTimeAllowed = 0; // 0 = no limit
74  var $timeExceeded = false;
75  var $firstPageWritten = false;
76  var $lastPageWritten = false;
77  var $checkpointJustWritten = false;
79 
83  protected $db;
84 
96  function rotateDb() {
97  // Cleaning up old connections
98  if ( isset( $this->lb ) ) {
99  $this->lb->closeAll();
100  unset( $this->lb );
101  }
102 
103  if ( $this->forcedDb !== null ) {
104  $this->db = $this->forcedDb;
105  return;
106  }
107 
108  if ( isset( $this->db ) && $this->db->isOpen() ) {
109  throw new MWException( 'DB is set and has not been closed by the Load Balancer' );
110  }
111 
112  unset( $this->db );
113 
114  // Trying to set up new connection.
115  // We do /not/ retry upon failure, but delegate to encapsulating logic, to avoid
116  // individually retrying at different layers of code.
117 
118  // 1. The LoadBalancer.
119  try {
120  $this->lb = wfGetLBFactory()->newMainLB();
121  } catch ( Exception $e ) {
122  throw new MWException( __METHOD__ . " rotating DB failed to obtain new load balancer (" . $e->getMessage() . ")" );
123  }
124 
125  // 2. The Connection, through the load balancer.
126  try {
127  $this->db = $this->lb->getConnection( DB_SLAVE, 'dump' );
128  } catch ( Exception $e ) {
129  throw new MWException( __METHOD__ . " rotating DB failed to obtain new database (" . $e->getMessage() . ")" );
130  }
131  }
132 
134  parent::initProgress();
135  $this->timeOfCheckpoint = $this->startTime;
136  }
137 
138  function dump( $history, $text = WikiExporter::TEXT ) {
139  // Notice messages will foul up your XML output even if they're
140  // relatively harmless.
141  if ( ini_get( 'display_errors' ) ) {
142  ini_set( 'display_errors', 'stderr' );
143  }
144 
145  $this->initProgress( $this->history );
146 
147  // We are trying to get an initial database connection to avoid that the
148  // first try of this request's first call to getText fails. However, if
149  // obtaining a good DB connection fails it's not a serious issue, as
150  // getText does retry upon failure and can start without having a working
151  // DB connection.
152  try {
153  $this->rotateDb();
154  } catch ( Exception $e ) {
155  // We do not even count this as failure. Just let eventual
156  // watchdogs know.
157  $this->progress( "Getting initial DB connection failed (" .
158  $e->getMessage() . ")" );
159  }
160 
161  $this->egress = new ExportProgressFilter( $this->sink, $this );
162 
163  // it would be nice to do it in the constructor, oh well. need egress set
164  $this->finalOptionCheck();
165 
166  // we only want this so we know how to close a stream :-P
167  $this->xmlwriterobj = new XmlDumpWriter();
168 
169  $input = fopen( $this->input, "rt" );
170  $this->readDump( $input );
171 
172  if ( $this->spawnProc ) {
173  $this->closeSpawn();
174  }
175 
176  $this->report( true );
177  }
178 
179  function processOption( $opt, $val, $param ) {
180  global $IP;
181  $url = $this->processFileOpt( $val, $param );
182 
183  switch ( $opt ) {
184  case 'prefetch':
185  require_once "$IP/maintenance/backupPrefetch.inc";
186  $this->prefetch = new BaseDump( $url );
187  break;
188  case 'stub':
189  $this->input = $url;
190  break;
191  case 'maxtime':
192  $this->maxTimeAllowed = intval( $val ) * 60;
193  break;
194  case 'checkpointfile':
195  $this->checkpointFiles[] = $val;
196  break;
197  case 'current':
198  $this->history = WikiExporter::CURRENT;
199  break;
200  case 'full':
201  $this->history = WikiExporter::FULL;
202  break;
203  case 'spawn':
204  $this->spawn = true;
205  if ( $val ) {
206  $this->php = $val;
207  }
208  break;
209  }
210  }
211 
212  function processFileOpt( $val, $param ) {
213  $fileURIs = explode( ';', $param );
214  foreach ( $fileURIs as $URI ) {
215  switch ( $val ) {
216  case "file":
217  $newURI = $URI;
218  break;
219  case "gzip":
220  $newURI = "compress.zlib://$URI";
221  break;
222  case "bzip2":
223  $newURI = "compress.bzip2://$URI";
224  break;
225  case "7zip":
226  $newURI = "mediawiki.compress.7z://$URI";
227  break;
228  default:
229  $newURI = $URI;
230  }
231  $newFileURIs[] = $newURI;
232  }
233  $val = implode( ';', $newFileURIs );
234  return $val;
235  }
236 
240  function showReport() {
241  if ( !$this->prefetch ) {
242  parent::showReport();
243  return;
244  }
245 
246  if ( $this->reporting ) {
247  $now = wfTimestamp( TS_DB );
248  $nowts = microtime( true );
249  $deltaAll = $nowts - $this->startTime;
250  $deltaPart = $nowts - $this->lastTime;
251  $this->pageCountPart = $this->pageCount - $this->pageCountLast;
252  $this->revCountPart = $this->revCount - $this->revCountLast;
253 
254  if ( $deltaAll ) {
255  $portion = $this->revCount / $this->maxCount;
256  $eta = $this->startTime + $deltaAll / $portion;
257  $etats = wfTimestamp( TS_DB, intval( $eta ) );
258  if ( $this->fetchCount ) {
259  $fetchRate = 100.0 * $this->prefetchCount / $this->fetchCount;
260  } else {
261  $fetchRate = '-';
262  }
263  $pageRate = $this->pageCount / $deltaAll;
264  $revRate = $this->revCount / $deltaAll;
265  } else {
266  $pageRate = '-';
267  $revRate = '-';
268  $etats = '-';
269  $fetchRate = '-';
270  }
271  if ( $deltaPart ) {
272  if ( $this->fetchCountLast ) {
273  $fetchRatePart = 100.0 * $this->prefetchCountLast / $this->fetchCountLast;
274  } else {
275  $fetchRatePart = '-';
276  }
277  $pageRatePart = $this->pageCountPart / $deltaPart;
278  $revRatePart = $this->revCountPart / $deltaPart;
279 
280  } else {
281  $fetchRatePart = '-';
282  $pageRatePart = '-';
283  $revRatePart = '-';
284  }
285  $this->progress( sprintf( "%s: %s (ID %d) %d pages (%0.1f|%0.1f/sec all|curr), %d revs (%0.1f|%0.1f/sec all|curr), %0.1f%%|%0.1f%% prefetched (all|curr), ETA %s [max %d]",
286  $now, wfWikiID(), $this->ID, $this->pageCount, $pageRate, $pageRatePart, $this->revCount, $revRate, $revRatePart, $fetchRate, $fetchRatePart, $etats, $this->maxCount ) );
287  $this->lastTime = $nowts;
288  $this->revCountLast = $this->revCount;
289  $this->prefetchCountLast = $this->prefetchCount;
290  $this->fetchCountLast = $this->fetchCount;
291  }
292  }
293 
294  function setTimeExceeded() {
295  $this->timeExceeded = true;
296  }
297 
298  function checkIfTimeExceeded() {
299  if ( $this->maxTimeAllowed && ( $this->lastTime - $this->timeOfCheckpoint > $this->maxTimeAllowed ) ) {
300  return true;
301  }
302  return false;
303  }
304 
305  function finalOptionCheck() {
306  if ( ( $this->checkpointFiles && ! $this->maxTimeAllowed ) ||
307  ( $this->maxTimeAllowed && !$this->checkpointFiles ) ) {
308  throw new MWException( "Options checkpointfile and maxtime must be specified together.\n" );
309  }
310  foreach ( $this->checkpointFiles as $checkpointFile ) {
311  $count = substr_count ( $checkpointFile, "%s" );
312  if ( $count != 2 ) {
313  throw new MWException( "Option checkpointfile must contain two '%s' for substitution of first and last pageids, count is $count instead, file is $checkpointFile.\n" );
314  }
315  }
316 
317  if ( $this->checkpointFiles ) {
318  $filenameList = (array)$this->egress->getFilenames();
319  if ( count( $filenameList ) != count( $this->checkpointFiles ) ) {
320  throw new MWException( "One checkpointfile must be specified for each output option, if maxtime is used.\n" );
321  }
322  }
323  }
324 
329  function readDump( $input ) {
330  $this->buffer = "";
331  $this->openElement = false;
332  $this->atStart = true;
333  $this->state = "";
334  $this->lastName = "";
335  $this->thisPage = 0;
336  $this->thisRev = 0;
337 
338  $parser = xml_parser_create( "UTF-8" );
339  xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
340 
341  xml_set_element_handler( $parser, array( &$this, 'startElement' ), array( &$this, 'endElement' ) );
342  xml_set_character_data_handler( $parser, array( &$this, 'characterData' ) );
343 
344  $offset = 0; // for context extraction on error reporting
345  $bufferSize = 512 * 1024;
346  do {
347  if ( $this->checkIfTimeExceeded() ) {
348  $this->setTimeExceeded();
349  }
350  $chunk = fread( $input, $bufferSize );
351  if ( !xml_parse( $parser, $chunk, feof( $input ) ) ) {
352  wfDebug( "TextDumpPass::readDump encountered XML parsing error\n" );
353 
354  $byte = xml_get_current_byte_index( $parser );
355  $msg = wfMessage( 'xml-error-string',
356  'XML import parse failure',
357  xml_get_current_line_number( $parser ),
358  xml_get_current_column_number( $parser ),
359  $byte . ( is_null( $chunk ) ? null : ( '; "' . substr( $chunk, $byte -$offset, 16 ) . '"' ) ),
360  xml_error_string( xml_get_error_code( $parser ) ) )->escaped();
361 
362  xml_parser_free( $parser );
363 
364  throw new MWException( $msg );
365  }
366  $offset += strlen( $chunk );
367  } while ( $chunk !== false && !feof( $input ) );
368  if ( $this->maxTimeAllowed ) {
369  $filenameList = (array)$this->egress->getFilenames();
370  // we wrote some stuff after last checkpoint that needs renamed
371  if ( file_exists( $filenameList[0] ) ) {
372  $newFilenames = array();
373  # we might have just written the header and footer and had no
374  # pages or revisions written... perhaps they were all deleted
375  # there's no pageID 0 so we use that. the caller is responsible
376  # for deciding what to do with a file containing only the
377  # siteinfo information and the mw tags.
378  if ( ! $this->firstPageWritten ) {
379  $firstPageID = str_pad( 0, 9, "0", STR_PAD_LEFT );
380  $lastPageID = str_pad( 0, 9, "0", STR_PAD_LEFT );
381  }
382  else {
383  $firstPageID = str_pad( $this->firstPageWritten, 9, "0", STR_PAD_LEFT );
384  $lastPageID = str_pad( $this->lastPageWritten, 9, "0", STR_PAD_LEFT );
385  }
386  for ( $i = 0; $i < count( $filenameList ); $i++ ) {
387  $checkpointNameFilledIn = sprintf( $this->checkpointFiles[$i], $firstPageID, $lastPageID );
388  $fileinfo = pathinfo( $filenameList[$i] );
389  $newFilenames[] = $fileinfo['dirname'] . '/' . $checkpointNameFilledIn;
390  }
391  $this->egress->closeAndRename( $newFilenames );
392  }
393  }
394  xml_parser_free( $parser );
395 
396  return true;
397  }
398 
413  function getText( $id ) {
414  global $wgContentHandlerUseDB;
415 
416  $prefetchNotTried = true; // Whether or not we already tried to get the text via prefetch.
417  $text = false; // The candidate for a good text. false if no proper value.
418  $failures = 0; // The number of times, this invocation of getText already failed.
419 
420  // The number of times getText failed without yielding a good text in between.
421  static $consecutiveFailedTextRetrievals = 0;
422 
423  $this->fetchCount++;
424 
425  // To allow to simply return on success and do not have to worry about book keeping,
426  // we assume, this fetch works (possible after some retries). Nevertheless, we koop
427  // the old value, so we can restore it, if problems occur (See after the while loop).
428  $oldConsecutiveFailedTextRetrievals = $consecutiveFailedTextRetrievals;
429  $consecutiveFailedTextRetrievals = 0;
430 
431  while ( $failures < $this->maxFailures ) {
432 
433  // As soon as we found a good text for the $id, we will return immediately.
434  // Hence, if we make it past the try catch block, we know that we did not
435  // find a good text.
436 
437  try {
438  // Step 1: Get some text (or reuse from previous iteratuon if checking
439  // for plausibility failed)
440 
441  // Trying to get prefetch, if it has not been tried before
442  if ( $text === false && isset( $this->prefetch ) && $prefetchNotTried ) {
443  $prefetchNotTried = false;
444  $tryIsPrefetch = true;
445  $text = $this->prefetch->prefetch( intval( $this->thisPage ),
446  intval( $this->thisRev ) );
447  if ( $text === null ) {
448  $text = false;
449  }
450  }
451 
452  if ( $text === false ) {
453  // Fallback to asking the database
454  $tryIsPrefetch = false;
455  if ( $this->spawn ) {
456  $text = $this->getTextSpawned( $id );
457  } else {
458  $text = $this->getTextDb( $id );
459  }
460 
461  // No more checks for texts from DB for now.
462  // If we received something that is not false,
463  // We treat it as good text, regardless of whether it actually is or is not
464  if ( $text !== false ) {
465  return $text;
466  }
467  }
468 
469  if ( $text === false ) {
470  throw new MWException( "Generic error while obtaining text for id " . $id );
471  }
472 
473  // We received a good candidate for the text of $id via some method
474 
475  // Step 2: Checking for plausibility and return the text if it is
476  // plausible
477  $revID = intval( $this->thisRev );
478  if ( ! isset( $this->db ) ) {
479  throw new MWException( "No database available" );
480  }
481 
482  $revLength = strlen( $text );
483  if ( $wgContentHandlerUseDB ) {
484  $row = $this->db->selectRow(
485  'revision',
486  array( 'rev_len', 'rev_content_model' ),
487  array( 'rev_id' => $revID ),
488  __METHOD__
489  );
490  if ( $row ) {
491  // only check the length for the wikitext content handler,
492  // it's a wasted (and failed) check otherwise
493  if ( $row->rev_content_model == CONTENT_MODEL_WIKITEXT ) {
494  $revLength = $row->rev_len;
495  }
496  }
497 
498  }
499  else {
500  $revLength = $this->db->selectField( 'revision', 'rev_len', array( 'rev_id' => $revID ) );
501  }
502 
503  if ( strlen( $text ) == $revLength ) {
504  if ( $tryIsPrefetch ) {
505  $this->prefetchCount++;
506  }
507  return $text;
508  }
509 
510  $text = false;
511  throw new MWException( "Received text is unplausible for id " . $id );
512 
513  } catch ( Exception $e ) {
514  $msg = "getting/checking text " . $id . " failed (" . $e->getMessage() . ")";
515  if ( $failures + 1 < $this->maxFailures ) {
516  $msg .= " (Will retry " . ( $this->maxFailures - $failures - 1 ) . " more times)";
517  }
518  $this->progress( $msg );
519  }
520 
521  // Something went wrong; we did not a text that was plausible :(
522  $failures++;
523 
524  // A failure in a prefetch hit does not warrant resetting db connection etc.
525  if ( ! $tryIsPrefetch ) {
526  // After backing off for some time, we try to reboot the whole process as
527  // much as possible to not carry over failures from one part to the other
528  // parts
529  sleep( $this->failureTimeout );
530  try {
531  $this->rotateDb();
532  if ( $this->spawn ) {
533  $this->closeSpawn();
534  $this->openSpawn();
535  }
536  } catch ( Exception $e ) {
537  $this->progress( "Rebooting getText infrastructure failed (" . $e->getMessage() . ")" .
538  " Trying to continue anyways" );
539  }
540  }
541  }
542 
543  // Retirieving a good text for $id failed (at least) maxFailures times.
544  // We abort for this $id.
545 
546  // Restoring the consecutive failures, and maybe aborting, if the dump
547  // is too broken.
548  $consecutiveFailedTextRetrievals = $oldConsecutiveFailedTextRetrievals + 1;
549  if ( $consecutiveFailedTextRetrievals > $this->maxConsecutiveFailedTextRetrievals ) {
550  throw new MWException( "Graceful storage failure" );
551  }
552 
553  return "";
554  }
555 
562  private function getTextDb( $id ) {
564  if ( ! isset( $this->db ) ) {
565  throw new MWException( __METHOD__ . "No database available" );
566  }
567  $row = $this->db->selectRow( 'text',
568  array( 'old_text', 'old_flags' ),
569  array( 'old_id' => $id ),
570  __METHOD__ );
571  $text = Revision::getRevisionText( $row );
572  if ( $text === false ) {
573  return false;
574  }
575  $stripped = str_replace( "\r", "", $text );
576  $normalized = $wgContLang->normalize( $stripped );
577  return $normalized;
578  }
579 
580  private function getTextSpawned( $id ) {
582  if ( !$this->spawnProc ) {
583  // First time?
584  $this->openSpawn();
585  }
586  $text = $this->getTextSpawnedOnce( $id );
588  return $text;
589  }
590 
591  function openSpawn() {
592  global $IP;
593 
594  if ( file_exists( "$IP/../multiversion/MWScript.php" ) ) {
595  $cmd = implode( " ",
596  array_map( 'wfEscapeShellArg',
597  array(
598  $this->php,
599  "$IP/../multiversion/MWScript.php",
600  "fetchText.php",
601  '--wiki', wfWikiID() ) ) );
602  }
603  else {
604  $cmd = implode( " ",
605  array_map( 'wfEscapeShellArg',
606  array(
607  $this->php,
608  "$IP/maintenance/fetchText.php",
609  '--wiki', wfWikiID() ) ) );
610  }
611  $spec = array(
612  0 => array( "pipe", "r" ),
613  1 => array( "pipe", "w" ),
614  2 => array( "file", "/dev/null", "a" ) );
615  $pipes = array();
616 
617  $this->progress( "Spawning database subprocess: $cmd" );
618  $this->spawnProc = proc_open( $cmd, $spec, $pipes );
619  if ( !$this->spawnProc ) {
620  // shit
621  $this->progress( "Subprocess spawn failed." );
622  return false;
623  }
624  list(
625  $this->spawnWrite, // -> stdin
626  $this->spawnRead, // <- stdout
627  ) = $pipes;
628 
629  return true;
630  }
631 
632  private function closeSpawn() {
634  if ( $this->spawnRead ) {
635  fclose( $this->spawnRead );
636  }
637  $this->spawnRead = false;
638  if ( $this->spawnWrite ) {
639  fclose( $this->spawnWrite );
640  }
641  $this->spawnWrite = false;
642  if ( $this->spawnErr ) {
643  fclose( $this->spawnErr );
644  }
645  $this->spawnErr = false;
646  if ( $this->spawnProc ) {
647  pclose( $this->spawnProc );
648  }
649  $this->spawnProc = false;
651  }
652 
653  private function getTextSpawnedOnce( $id ) {
655 
656  $ok = fwrite( $this->spawnWrite, "$id\n" );
657  // $this->progress( ">> $id" );
658  if ( !$ok ) {
659  return false;
660  }
661 
662  $ok = fflush( $this->spawnWrite );
663  // $this->progress( ">> [flush]" );
664  if ( !$ok ) {
665  return false;
666  }
667 
668  // check that the text id they are sending is the one we asked for
669  // this avoids out of sync revision text errors we have encountered in the past
670  $newId = fgets( $this->spawnRead );
671  if ( $newId === false ) {
672  return false;
673  }
674  if ( $id != intval( $newId ) ) {
675  return false;
676  }
677 
678  $len = fgets( $this->spawnRead );
679  // $this->progress( "<< " . trim( $len ) );
680  if ( $len === false ) {
681  return false;
682  }
683 
684  $nbytes = intval( $len );
685  // actual error, not zero-length text
686  if ( $nbytes < 0 ) {
687  return false;
688  }
689 
690  $text = "";
691 
692  // Subprocess may not send everything at once, we have to loop.
693  while ( $nbytes > strlen( $text ) ) {
694  $buffer = fread( $this->spawnRead, $nbytes - strlen( $text ) );
695  if ( $buffer === false ) {
696  break;
697  }
698  $text .= $buffer;
699  }
700 
701  $gotbytes = strlen( $text );
702  if ( $gotbytes != $nbytes ) {
703  $this->progress( "Expected $nbytes bytes from database subprocess, got $gotbytes " );
704  return false;
705  }
706 
707  // Do normalization in the dump thread...
708  $stripped = str_replace( "\r", "", $text );
709  $normalized = $wgContLang->normalize( $stripped );
710  return $normalized;
711  }
712 
713  function startElement( $parser, $name, $attribs ) {
714  $this->checkpointJustWritten = false;
715 
716  $this->clearOpenElement( null );
717  $this->lastName = $name;
718 
719  if ( $name == 'revision' ) {
720  $this->state = $name;
721  $this->egress->writeOpenPage( null, $this->buffer );
722  $this->buffer = "";
723  } elseif ( $name == 'page' ) {
724  $this->state = $name;
725  if ( $this->atStart ) {
726  $this->egress->writeOpenStream( $this->buffer );
727  $this->buffer = "";
728  $this->atStart = false;
729  }
730  }
731 
732  if ( $name == "text" && isset( $attribs['id'] ) ) {
733  $text = $this->getText( $attribs['id'] );
734  $this->openElement = array( $name, array( 'xml:space' => 'preserve' ) );
735  if ( strlen( $text ) > 0 ) {
736  $this->characterData( $parser, $text );
737  }
738  } else {
739  $this->openElement = array( $name, $attribs );
740  }
741  }
742 
743  function endElement( $parser, $name ) {
744  $this->checkpointJustWritten = false;
745 
746  if ( $this->openElement ) {
747  $this->clearOpenElement( "" );
748  } else {
749  $this->buffer .= "</$name>";
750  }
751 
752  if ( $name == 'revision' ) {
753  $this->egress->writeRevision( null, $this->buffer );
754  $this->buffer = "";
755  $this->thisRev = "";
756  } elseif ( $name == 'page' ) {
757  if ( ! $this->firstPageWritten ) {
758  $this->firstPageWritten = trim( $this->thisPage );
759  }
760  $this->lastPageWritten = trim( $this->thisPage );
761  if ( $this->timeExceeded ) {
762  $this->egress->writeClosePage( $this->buffer );
763  // nasty hack, we can't just write the chardata after the
764  // page tag, it will include leading blanks from the next line
765  $this->egress->sink->write( "\n" );
766 
767  $this->buffer = $this->xmlwriterobj->closeStream();
768  $this->egress->writeCloseStream( $this->buffer );
769 
770  $this->buffer = "";
771  $this->thisPage = "";
772  // this could be more than one file if we had more than one output arg
773 
774  $filenameList = (array)$this->egress->getFilenames();
775  $newFilenames = array();
776  $firstPageID = str_pad( $this->firstPageWritten, 9, "0", STR_PAD_LEFT );
777  $lastPageID = str_pad( $this->lastPageWritten, 9, "0", STR_PAD_LEFT );
778  for ( $i = 0; $i < count( $filenameList ); $i++ ) {
779  $checkpointNameFilledIn = sprintf( $this->checkpointFiles[$i], $firstPageID, $lastPageID );
780  $fileinfo = pathinfo( $filenameList[$i] );
781  $newFilenames[] = $fileinfo['dirname'] . '/' . $checkpointNameFilledIn;
782  }
783  $this->egress->closeRenameAndReopen( $newFilenames );
784  $this->buffer = $this->xmlwriterobj->openStream();
785  $this->timeExceeded = false;
786  $this->timeOfCheckpoint = $this->lastTime;
787  $this->firstPageWritten = false;
788  $this->checkpointJustWritten = true;
789  }
790  else {
791  $this->egress->writeClosePage( $this->buffer );
792  $this->buffer = "";
793  $this->thisPage = "";
794  }
795 
796  } elseif ( $name == 'mediawiki' ) {
797  $this->egress->writeCloseStream( $this->buffer );
798  $this->buffer = "";
799  }
800  }
801 
802  function characterData( $parser, $data ) {
803  $this->clearOpenElement( null );
804  if ( $this->lastName == "id" ) {
805  if ( $this->state == "revision" ) {
806  $this->thisRev .= $data;
807  } elseif ( $this->state == "page" ) {
808  $this->thisPage .= $data;
809  }
810  }
811  // have to skip the newline left over from closepagetag line of
812  // end of checkpoint files. nasty hack!!
813  if ( $this->checkpointJustWritten ) {
814  if ( $data[0] == "\n" ) {
815  $data = substr( $data, 1 );
816  }
817  $this->checkpointJustWritten = false;
818  }
819  $this->buffer .= htmlspecialchars( $data );
820  }
821 
822  function clearOpenElement( $style ) {
823  if ( $this->openElement ) {
824  $this->buffer .= Xml::element( $this->openElement[0], $this->openElement[1], $style );
825  $this->openElement = false;
826  }
827  }
828 }
TextPassDumper\clearOpenElement
clearOpenElement( $style)
Definition: backupTextPass.inc:817
BaseDump
Readahead helper for making large MediaWiki data dumps; reads in a previous XML dump to sequentially ...
Definition: backupPrefetch.inc:42
ID
occurs before session is loaded can be modified ID
Definition: hooks.txt:2823
BackupDumper\revCount
revCount()
Definition: backup.inc:315
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
TextPassDumper\readDump
readDump( $input)
Definition: backupTextPass.inc:324
TextPassDumper\startElement
startElement( $parser, $name, $attribs)
Definition: backupTextPass.inc:708
TextPassDumper\$history
$history
Definition: backupTextPass.inc:35
WikiExporter\CURRENT
const CURRENT
Definition: Export.php:41
TextPassDumper\showReport
showReport()
Overridden to include prefetch ratio if enabled.
Definition: backupTextPass.inc:235
TextPassDumper\getText
getText( $id)
Tries to get the revision text for a revision id.
Definition: backupTextPass.inc:408
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:2530
BackupDumper\$forcedDb
DatabaseBase null $forcedDb
The dependency-injected database to use.
Definition: backup.inc:69
wfSuppressWarnings
wfSuppressWarnings( $end=false)
Reference-counted warning suppression.
Definition: GlobalFunctions.php:2434
TextPassDumper\$spawnProc
bool resource $spawnProc
Definition: backupTextPass.inc:50
BackupDumper\$revCountLast
$revCountLast
Definition: backup.inc:58
TextPassDumper\$maxTimeAllowed
$maxTimeAllowed
Definition: backupTextPass.inc:69
Revision\getRevisionText
static getRevisionText( $row, $prefix='old_', $wiki=false)
Get revision text associated with an old or archive row $row is usually an object from wfFetchRow(),...
Definition: Revision.php:1212
TextPassDumper\$spawnErr
bool resource $spawnErr
Definition: backupTextPass.inc:62
BackupDumper\$pageCountLast
$pageCountLast
Definition: backup.inc:57
TextPassDumper\setTimeExceeded
setTimeExceeded()
Definition: backupTextPass.inc:289
TS_DB
const TS_DB
MySQL DATETIME (YYYY-MM-DD HH:MM:SS)
Definition: GlobalFunctions.php:2483
TextPassDumper\rotateDb
rotateDb()
Drop the database connection $this->db and try to get a new one.
Definition: backupTextPass.inc:91
BackupDumper\$revCount
$revCount
Definition: backup.inc:43
TextPassDumper\$xmlwriterobj
$xmlwriterobj
Definition: backupTextPass.inc:64
$wgContLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the content language as $wgContLang
Definition: design.txt:56
CONTENT_MODEL_WIKITEXT
const CONTENT_MODEL_WIKITEXT
Definition: Defines.php:283
TextPassDumper\$spawnWrite
bool resource $spawnWrite
Definition: backupTextPass.inc:54
TextPassDumper\finalOptionCheck
finalOptionCheck()
Definition: backupTextPass.inc:300
TextPassDumper\processFileOpt
processFileOpt( $val, $param)
Definition: backupTextPass.inc:207
TextPassDumper\$maxConsecutiveFailedTextRetrievals
$maxConsecutiveFailedTextRetrievals
Definition: backupTextPass.inc:42
MWException
MediaWiki exception.
Definition: MWException.php:26
TextPassDumper\$firstPageWritten
$firstPageWritten
Definition: backupTextPass.inc:71
wfRestoreWarnings
wfRestoreWarnings()
Restore error level to previous value.
Definition: GlobalFunctions.php:2464
WikiExporter\TEXT
const TEXT
Definition: Export.php:49
TextPassDumper\dump
dump( $history, $text=WikiExporter::TEXT)
Definition: backupTextPass.inc:133
TextPassDumper\processOption
processOption( $opt, $val, $param)
Definition: backupTextPass.inc:174
$parser
do that in ParserLimitReportFormat instead $parser
Definition: hooks.txt:1961
TextPassDumper\$prefetchCount
$prefetchCount
Definition: backupTextPass.inc:37
TextPassDumper\$timeExceeded
$timeExceeded
Definition: backupTextPass.inc:70
TextPassDumper\$maxFailures
$maxFailures
Definition: backupTextPass.inc:41
TextPassDumper\$fetchCountLast
$fetchCountLast
Definition: backupTextPass.inc:39
TextPassDumper\$fetchCount
$fetchCount
Definition: backupTextPass.inc:36
TextPassDumper\$failureTimeout
$failureTimeout
Definition: backupTextPass.inc:43
TextPassDumper\$spawnRead
bool resource $spawnRead
Definition: backupTextPass.inc:58
wfMessage
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing after in associative array form externallinks including delete and has completed for all link tables default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt
Xml\element
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition: Xml.php:39
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
TextPassDumper\checkIfTimeExceeded
checkIfTimeExceeded()
Definition: backupTextPass.inc:293
TextPassDumper\getTextSpawnedOnce
getTextSpawnedOnce( $id)
Definition: backupTextPass.inc:648
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
$ok
$ok
Definition: UtfNormalTest.php:71
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
TextPassDumper\$php
$php
Definition: backupTextPass.inc:45
wfWikiID
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
Definition: GlobalFunctions.php:3660
TextPassDumper\initProgress
initProgress( $history=WikiExporter::FULL)
Initialise starting time and maximum revision count.
Definition: backupTextPass.inc:128
BackupDumper\report
report( $final=false)
Definition: backup.inc:320
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:336
TextPassDumper\$checkpointFiles
$checkpointFiles
Definition: backupTextPass.inc:74
DatabaseBase
Database abstraction object.
Definition: Database.php:219
WikiExporter\FULL
const FULL
Definition: Export.php:40
TextPassDumper\$input
$input
Definition: backupTextPass.inc:34
BackupDumper\progress
progress( $string)
Definition: backup.inc:360
TextPassDumper\$prefetchCountLast
$prefetchCountLast
Definition: backupTextPass.inc:38
TextPassDumper\characterData
characterData( $parser, $data)
Definition: backupTextPass.inc:797
$count
$count
Definition: UtfNormalTest2.php:96
TextPassDumper\getTextDb
getTextDb( $id)
May throw a database error if, say, the server dies during query.
Definition: backupTextPass.inc:557
DB_SLAVE
const DB_SLAVE
Definition: Defines.php:55
BackupDumper
Definition: backup.inc:39
wfGetLBFactory
& wfGetLBFactory()
Get the load balancer factory object.
Definition: GlobalFunctions.php:3725
TextPassDumper\getTextSpawned
getTextSpawned( $id)
Definition: backupTextPass.inc:575
TextPassDumper\$lastPageWritten
$lastPageWritten
Definition: backupTextPass.inc:72
TextPassDumper\openSpawn
openSpawn()
Definition: backupTextPass.inc:586
TextPassDumper\$prefetch
$prefetch
Definition: backupTextPass.inc:33
XmlDumpWriter
Definition: Export.php:476
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
TextPassDumper\$db
DatabaseBase $db
Definition: backupTextPass.inc:78
BackupDumper\$lastTime
$lastTime
Definition: backup.inc:56
TextPassDumper\$spawn
$spawn
Definition: backupTextPass.inc:46
TextPassDumper\endElement
endElement( $parser, $name)
Definition: backupTextPass.inc:738
ExportProgressFilter
Definition: backup.inc:370
TextPassDumper
Definition: backupTextPass.inc:32
TextPassDumper\$checkpointJustWritten
$checkpointJustWritten
Definition: backupTextPass.inc:73
$attribs
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing & $attribs
Definition: hooks.txt:1530
$IP
$IP
Definition: WebStart.php:88
TextPassDumper\closeSpawn
closeSpawn()
Definition: backupTextPass.inc:627
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:1632