Index: trunk/phase3/includes/Export.php |
— | — | @@ -354,6 +354,9 @@ |
355 | 355 | * @ingroup Dump |
356 | 356 | */ |
357 | 357 | class XmlDumpWriter { |
| 358 | + var $firstPageWritten = 0; |
| 359 | + var $lastPageWritten = 0; |
| 360 | + var $pageInProgress = 0; |
358 | 361 | |
359 | 362 | /** |
360 | 363 | * Returns the export schema version. |
— | — | @@ -458,6 +461,7 @@ |
459 | 462 | $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
460 | 463 | $out .= ' ' . Xml::elementClean( 'title', array(), $title->getPrefixedText() ) . "\n"; |
461 | 464 | $out .= ' ' . Xml::element( 'id', array(), strval( $row->page_id ) ) . "\n"; |
| 465 | + $this->pageInProgress = $row->page_id; |
462 | 466 | if ( $row->page_is_redirect ) { |
463 | 467 | $out .= ' ' . Xml::element( 'redirect', array() ) . "\n"; |
464 | 468 | } |
— | — | @@ -478,6 +482,10 @@ |
479 | 483 | */ |
480 | 484 | function closePage() { |
481 | 485 | return " </page>\n"; |
| 486 | + if (! $this->firstPageWritten) { |
| 487 | + $this->firstPageWritten = $this->pageInProgress; |
| 488 | + } |
| 489 | + $this->lastPageWritten = $this->pageInProgress; |
482 | 490 | } |
483 | 491 | |
484 | 492 | /** |
— | — | @@ -691,6 +699,18 @@ |
692 | 700 | function write( $string ) { |
693 | 701 | print $string; |
694 | 702 | } |
| 703 | + |
| 704 | + function closeRenameAndReopen( $newname ) { |
| 705 | + return; |
| 706 | + } |
| 707 | + |
| 708 | + function rename( $newname ) { |
| 709 | + return; |
| 710 | + } |
| 711 | + |
| 712 | + function getFilename() { |
| 713 | + return NULL; |
| 714 | + } |
695 | 715 | } |
696 | 716 | |
697 | 717 | /** |
— | — | @@ -699,14 +719,56 @@ |
700 | 720 | */ |
701 | 721 | class DumpFileOutput extends DumpOutput { |
702 | 722 | var $handle; |
| 723 | + var $filename; |
703 | 724 | |
704 | 725 | function __construct( $file ) { |
705 | 726 | $this->handle = fopen( $file, "wt" ); |
| 727 | + $this->filename = $file; |
706 | 728 | } |
707 | 729 | |
708 | 730 | function write( $string ) { |
709 | 731 | fputs( $this->handle, $string ); |
710 | 732 | } |
| 733 | + |
| 734 | + /** |
| 735 | + * Close the old file, move it to a specified name, |
| 736 | + * and reopen new file with the old name. Use this |
| 737 | + * for writing out a file in multiple pieces |
| 738 | + * at specified checkpoints (e.g. every n hours). |
| 739 | + */ |
| 740 | + function closeRenameAndReopen( $newname ) { |
| 741 | + if ( is_array($newname) ) { |
| 742 | + if (count($newname) > 1) { |
| 743 | + WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 744 | + } |
| 745 | + else { |
| 746 | + $newname = $newname[0]; |
| 747 | + } |
| 748 | + } |
| 749 | + if ( $newname ) { |
| 750 | + fclose( $this->handle ); |
| 751 | + rename( $this->filename, $newname ); |
| 752 | + $this->handle = fopen( $this->filename, "wt" ); |
| 753 | + } |
| 754 | + } |
| 755 | + |
| 756 | + function rename( $newname ) { |
| 757 | + if ( is_array($newname) ) { |
| 758 | + if (count($newname) > 1) { |
| 759 | + WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 760 | + } |
| 761 | + else { |
| 762 | + $newname = $newname[0]; |
| 763 | + } |
| 764 | + } |
| 765 | + if ( $newname ) { |
| 766 | + rename( $this->filename, $newname ); |
| 767 | + } |
| 768 | + } |
| 769 | + |
| 770 | + function getFilename() { |
| 771 | + return $this->filename; |
| 772 | + } |
711 | 773 | } |
712 | 774 | |
713 | 775 | /** |
— | — | @@ -716,12 +778,52 @@ |
717 | 779 | * @ingroup Dump |
718 | 780 | */ |
719 | 781 | class DumpPipeOutput extends DumpFileOutput { |
| 782 | + var $command; |
| 783 | + |
720 | 784 | function __construct( $command, $file = null ) { |
721 | 785 | if ( !is_null( $file ) ) { |
722 | 786 | $command .= " > " . wfEscapeShellArg( $file ); |
723 | 787 | } |
724 | 788 | $this->handle = popen( $command, "w" ); |
| 789 | + $this->command = $command; |
| 790 | + $this->filename = $file; |
725 | 791 | } |
| 792 | + |
| 793 | + /** |
| 794 | + * Close the old file, move it to a specified name, |
| 795 | + * and reopen new file with the old name. |
| 796 | + */ |
| 797 | + function closeRenameAndReopen( $newname ) { |
| 798 | + if ( is_array($newname) ) { |
| 799 | + if (count($newname) > 1) { |
| 800 | + WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 801 | + } |
| 802 | + else { |
| 803 | + $newname = $newname[0]; |
| 804 | + } |
| 805 | + } |
| 806 | + if ( $newname ) { |
| 807 | + pclose( $this->handle ); |
| 808 | + rename( $this->filename, $newname ); |
| 809 | + $command = $this->command; |
| 810 | + $command .= " > " . wfEscapeShellArg( $this->filename ); |
| 811 | + $this->handle = popen( $command, "w" ); |
| 812 | + } |
| 813 | + } |
| 814 | + |
| 815 | + function rename( $newname ) { |
| 816 | + if ( is_array($newname) ) { |
| 817 | + if (count($newname) > 1) { |
| 818 | + WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 819 | + } |
| 820 | + else { |
| 821 | + $newname = $newname[0]; |
| 822 | + } |
| 823 | + } |
| 824 | + if ( $newname ) { |
| 825 | + rename( $this->filename, $newname ); |
| 826 | + } |
| 827 | + } |
726 | 828 | } |
727 | 829 | |
728 | 830 | /** |
— | — | @@ -749,13 +851,48 @@ |
750 | 852 | * @ingroup Dump |
751 | 853 | */ |
752 | 854 | class Dump7ZipOutput extends DumpPipeOutput { |
| 855 | + var $filename; |
| 856 | + |
753 | 857 | function __construct( $file ) { |
754 | 858 | $command = "7za a -bd -si " . wfEscapeShellArg( $file ); |
755 | 859 | // Suppress annoying useless crap from p7zip |
756 | 860 | // Unfortunately this could suppress real error messages too |
757 | 861 | $command .= ' >' . wfGetNull() . ' 2>&1'; |
758 | 862 | parent::__construct( $command ); |
| 863 | + $this->filename = $file; |
759 | 864 | } |
| 865 | + |
| 866 | + function closeRenameAndReopen( $newname ) { |
| 867 | + if ( is_array($newname) ) { |
| 868 | + if (count($newname) > 1) { |
| 869 | + WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 870 | + } |
| 871 | + else { |
| 872 | + $newname = $newname[0]; |
| 873 | + } |
| 874 | + } |
| 875 | + if ( $newname ) { |
| 876 | + pclose( $this->handle ); |
| 877 | + rename( $this->filename, $newname ); |
| 878 | + $command = "7za a -bd -si " . wfEscapeShellArg( $file ); |
| 879 | + $command .= ' >' . wfGetNull() . ' 2>&1'; |
| 880 | + $this->handle = popen( $command, "w" ); |
| 881 | + } |
| 882 | + } |
| 883 | + |
| 884 | + function rename( $newname ) { |
| 885 | + if ( is_array($newname) ) { |
| 886 | + if (count($newname) > 1) { |
| 887 | + WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 888 | + } |
| 889 | + else { |
| 890 | + $newname = $newname[0]; |
| 891 | + } |
| 892 | + } |
| 893 | + if ( $newname ) { |
| 894 | + rename( $this->filename, $newname ); |
| 895 | + } |
| 896 | + } |
760 | 897 | } |
761 | 898 | |
762 | 899 | |
— | — | @@ -803,6 +940,18 @@ |
804 | 941 | $this->sink->writeRevision( $rev, $string ); |
805 | 942 | } |
806 | 943 | |
| 944 | + function closeRenameAndReopen( $newname ) { |
| 945 | + $this->sink->closeRenameAndReopen( $newname ); |
| 946 | + } |
| 947 | + |
| 948 | + function rename( $newname ) { |
| 949 | + $this->sink->rename( $newname ); |
| 950 | + } |
| 951 | + |
| 952 | + function getFilename() { |
| 953 | + return $this->sink->getFilename(); |
| 954 | + } |
| 955 | + |
807 | 956 | /** |
808 | 957 | * Override for page-based filter types. |
809 | 958 | * @return bool |
— | — | @@ -950,6 +1099,27 @@ |
951 | 1100 | $this->sinks[$i]->writeRevision( $rev, $string ); |
952 | 1101 | } |
953 | 1102 | } |
| 1103 | + |
| 1104 | + function closeRenameAndReopen( $newnames ) { |
| 1105 | + for( $i = 0; $i < $this->count; $i++ ) { |
| 1106 | + $this->sinks[$i]->closeRenameAndReopen( $newnames[$i] ); |
| 1107 | + } |
| 1108 | + } |
| 1109 | + |
| 1110 | + function rename( $newnames ) { |
| 1111 | + for( $i = 0; $i < $this->count; $i++ ) { |
| 1112 | + $this->sinks[$i]->rename( $newnames[$i] ); |
| 1113 | + } |
| 1114 | + } |
| 1115 | + |
| 1116 | + function getFilename() { |
| 1117 | + $filenames = array(); |
| 1118 | + for( $i = 0; $i < $this->count; $i++ ) { |
| 1119 | + $filenames[] = $this->sinks[$i]->getFilename(); |
| 1120 | + } |
| 1121 | + return $filenames; |
| 1122 | + } |
| 1123 | + |
954 | 1124 | } |
955 | 1125 | |
956 | 1126 | function xmlsafe( $string ) { |