00001 <?php
00012 class SquidUpdate {
00013 var $urlArr, $mMaxTitles;
00014
00015 function __construct( $urlArr = Array(), $maxTitles = false ) {
00016 global $wgMaxSquidPurgeTitles;
00017 if ( $maxTitles === false ) {
00018 $this->mMaxTitles = $wgMaxSquidPurgeTitles;
00019 } else {
00020 $this->mMaxTitles = $maxTitles;
00021 }
00022 if ( count( $urlArr ) > $this->mMaxTitles ) {
00023 $urlArr = array_slice( $urlArr, 0, $this->mMaxTitles );
00024 }
00025 $this->urlArr = $urlArr;
00026 }
00027
00028 static function newFromLinksTo( &$title ) {
00029 wfProfileIn( __METHOD__ );
00030
00031 # Get a list of URLs linking to this page
00032 $dbr = wfGetDB( DB_SLAVE );
00033 $res = $dbr->select( array( 'links', 'page' ),
00034 array( 'page_namespace', 'page_title' ),
00035 array(
00036 'pl_namespace' => $title->getNamespace(),
00037 'pl_title' => $title->getDBkey(),
00038 'pl_from=page_id' ),
00039 __METHOD__ );
00040 $blurlArr = $title->getSquidURLs();
00041 if ( $dbr->numRows( $res ) <= $this->mMaxTitles ) {
00042 while ( $BL = $dbr->fetchObject ( $res ) )
00043 {
00044 $tobj = Title::makeTitle( $BL->page_namespace, $BL->page_title ) ;
00045 $blurlArr[] = $tobj->getInternalURL();
00046 }
00047 }
00048 $dbr->freeResult ( $res ) ;
00049
00050 wfProfileOut( __METHOD__ );
00051 return new SquidUpdate( $blurlArr );
00052 }
00053
00057 static function newFromTitles( $titles, $urlArr = array() ) {
00058 global $wgMaxSquidPurgeTitles;
00059 $i = 0;
00060 foreach ( $titles as $title ) {
00061 $urlArr[] = $title->getInternalURL();
00062 if ( $i++ > $wgMaxSquidPurgeTitles ) {
00063 break;
00064 }
00065 }
00066 return new SquidUpdate( $urlArr );
00067 }
00068
00069 static function newSimplePurge( &$title ) {
00070 $urlArr = $title->getSquidURLs();
00071 return new SquidUpdate( $urlArr );
00072 }
00073
00074 function doUpdate() {
00075 SquidUpdate::purge( $this->urlArr );
00076 }
00077
00078
00079
00080
00081
00082
00083 static function purge( $urlArr ) {
00084 global $wgSquidServers, $wgHTCPMulticastAddress, $wgHTCPPort;
00085
00086
00087
00088
00089
00090
00091 if( !$urlArr ) {
00092 return;
00093 }
00094
00095 if ( $wgHTCPMulticastAddress && $wgHTCPPort ) {
00096 return SquidUpdate::HTCPPurge( $urlArr );
00097 }
00098
00099 wfProfileIn( __METHOD__ );
00100
00101 $maxSocketsPerSquid = 8;
00102 $urlsPerSocket = 400;
00103 $socketsPerSquid = ceil( count( $urlArr ) / $urlsPerSocket );
00104 if ( $socketsPerSquid > $maxSocketsPerSquid ) {
00105 $socketsPerSquid = $maxSocketsPerSquid;
00106 }
00107
00108 $pool = new SquidPurgeClientPool;
00109 $chunks = array_chunk( $urlArr, ceil( count( $urlArr ) / $socketsPerSquid ) );
00110 foreach ( $wgSquidServers as $server ) {
00111 foreach ( $chunks as $chunk ) {
00112 $client = new SquidPurgeClient( $server );
00113 foreach ( $chunk as $url ) {
00114 $client->queuePurge( $url );
00115 }
00116 $pool->addClient( $client );
00117 }
00118 }
00119 $pool->run();
00120
00121 wfProfileOut( __METHOD__ );
00122 }
00123
00124 static function HTCPPurge( $urlArr ) {
00125 global $wgHTCPMulticastAddress, $wgHTCPMulticastTTL, $wgHTCPPort;
00126 wfProfileIn( __METHOD__ );
00127
00128 $htcpOpCLR = 4;
00129
00130
00131 if( !defined( "IPPROTO_IP" ) ) {
00132 define( "IPPROTO_IP", 0 );
00133 define( "IP_MULTICAST_LOOP", 34 );
00134 define( "IP_MULTICAST_TTL", 33 );
00135 }
00136
00137
00138 $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
00139 if ( $conn ) {
00140
00141 socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_LOOP, 0 );
00142 if ( $wgHTCPMulticastTTL != 1 )
00143 socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_TTL,
00144 $wgHTCPMulticastTTL );
00145
00146 foreach ( $urlArr as $url ) {
00147 if( !is_string( $url ) ) {
00148 throw new MWException( 'Bad purge URL' );
00149 }
00150 $url = SquidUpdate::expand( $url );
00151
00152
00153
00154
00155 $htcpTransID = rand();
00156
00157 $htcpSpecifier = pack( 'na4na*na8n',
00158 4, 'HEAD', strlen( $url ), $url,
00159 8, 'HTTP/1.0', 0 );
00160
00161 $htcpDataLen = 8 + 2 + strlen( $htcpSpecifier );
00162 $htcpLen = 4 + $htcpDataLen + 2;
00163
00164
00165
00166
00167 $htcpPacket = pack( 'nxxnCxNxxa*n',
00168 $htcpLen, $htcpDataLen, $htcpOpCLR,
00169 $htcpTransID, $htcpSpecifier, 2);
00170
00171
00172 wfDebug( "Purging URL $url via HTCP\n" );
00173 socket_sendto( $conn, $htcpPacket, $htcpLen, 0,
00174 $wgHTCPMulticastAddress, $wgHTCPPort );
00175 }
00176 } else {
00177 $errstr = socket_strerror( socket_last_error() );
00178 wfDebug( __METHOD__ . "(): Error opening UDP socket: $errstr\n" );
00179 }
00180 wfProfileOut( __METHOD__ );
00181 }
00182
00196 static function expand( $url ) {
00197 global $wgInternalServer;
00198 if( $url != '' && $url{0} == '/' ) {
00199 return $wgInternalServer . $url;
00200 }
00201 return $url;
00202 }
00203 }