Implement routing for HTCP purges
authorCatrope <roan.kattouw@gmail.com>
Fri, 6 Apr 2012 20:27:10 +0000 (13:27 -0700)
committerCatrope <roan.kattouw@gmail.com>
Fri, 6 Apr 2012 22:04:27 +0000 (15:04 -0700)
This allows HTCP purges for different domains to be sent to different
multicast groups, based on regexes. Mark requested this so we could
separate the multicast groups for upload caches and text caches.

This code is UNTESTED, I'm mostly submitting this as a proof of concept
and to invite review by other core devs (specifically Tim).

Change-Id: Ie333a04131d6ca8394884ed1054f2baff55ab2d1

includes/DefaultSettings.php
includes/Setup.php
includes/cache/SquidUpdate.php

index 8402d69..48995a4 100644 (file)
@@ -1861,23 +1861,58 @@ $wgSquidServersNoPurge = array();
 /** Maximum number of titles to purge in any one client operation */
 $wgMaxSquidPurgeTitles = 400;
 
+/**
+ * Routing configuration for HTCP multicast purging. Add elements here to
+ * enable HTCP and determine which purges are sent where. If set to an empty
+ * array, HTCP is disabled.
+ * 
+ * Each key in this array is a regular expression to match against the purged
+ * URL, or an empty string to match all URLs. The purged URL is matched against
+ * the regexes in the order specified, and the first rule whose regex matches
+ * is used.
+ * 
+ * Example configuration to send purges for upload.wikimedia.org to one
+ * multicast group and all other purges to another:
+ * $wgHTCPMulticastRouting = array(
+ *         '|^https?://upload\.wikimedia\.org|' => array(
+ *                 'host' => '239.128.0.113',
+ *                 'port' => 4827,
+ *         ),
+ *         '' => array(
+ *                 'host' => '239.128.0.112',
+ *                 'port' => 4827,
+ *         ),
+ * );
+ * 
+ * @see $wgHTCPMulticastTTL
+ */
+$wgHTCPMulticastRouting = array();
+
 /**
  * HTCP multicast address. Set this to a multicast IP address to enable HTCP.
  *
  * Note that MediaWiki uses the old non-RFC compliant HTCP format, which was
  * present in the earliest Squid implementations of the protocol.
+ * 
+ * This setting is DEPRECATED in favor of $wgHTCPMulticastRouting , and kept
+ * for backwards compatibility only. If $wgHTCPMulticastRouting is set, this
+ * setting is ignored. If $wgHTCPMulticastRouting is not set and this setting
+ * is, it is used to populate $wgHTCPMulticastRouting.
+ * 
+ * @deprecated in favor of $wgHTCPMulticastRouting
  */
 $wgHTCPMulticastAddress = false;
 
 /**
  * HTCP multicast port.
+ * @deprecated in favor of $wgHTCPMulticastRouting
  * @see $wgHTCPMulticastAddress
  */
 $wgHTCPPort = 4827;
 
 /**
  * HTCP multicast TTL.
- * @see $wgHTCPMulticastAddress
+ * @see $wgHTCPMulticastRouting
  */
 $wgHTCPMulticastTTL = 1;
 
index 2777f73..9333e40 100644 (file)
@@ -391,6 +391,16 @@ if ( $wgCanonicalServer === false ) {
        $wgCanonicalServer = wfExpandUrl( $wgServer, PROTO_HTTP );
 }
 
+// Initialize $wgHTCPMulticastRouting from backwards-compatible settings
+if ( !$wgHTCPMulticastRouting && $wgHTCPMulticastAddress ) {
+       $wgHTCPMulticastRouting = array(
+               '' => array(
+                       'host' => $wgHTCPMulticastAddress,
+                       'port' => $wgHTCPPort,
+               )
+       );
+}
+
 wfProfileIn( $fname . '-misc1' );
 
 # Raise the memory limit if it's too low
index bd70095..e560e0e 100644 (file)
@@ -103,7 +103,7 @@ class SquidUpdate {
         * @return void
         */
        static function purge( $urlArr ) {
-               global $wgSquidServers, $wgHTCPMulticastAddress, $wgHTCPPort;
+               global $wgSquidServers, $wgHTCPMulticastRouting;
 
                /*if ( (@$wgSquidServers[0]) == 'echo' ) {
                        echo implode("<br />\n", $urlArr) . "<br />\n";
@@ -114,7 +114,7 @@ class SquidUpdate {
                        return;
                }
 
-               if ( $wgHTCPMulticastAddress && $wgHTCPPort ) {
+               if ( $wgHTCPMulticastRouting ) {
                        SquidUpdate::HTCPPurge( $urlArr );
                }
 
@@ -149,7 +149,7 @@ class SquidUpdate {
         * @param $urlArr array
         */
        static function HTCPPurge( $urlArr ) {
-               global $wgHTCPMulticastAddress, $wgHTCPMulticastTTL, $wgHTCPPort;
+               global $wgHTCPMulticastRouting, $wgHTCPMulticastTTL;
                wfProfileIn( __METHOD__ );
 
                $htcpOpCLR = 4; // HTCP CLR
@@ -176,6 +176,14 @@ class SquidUpdate {
                                        throw new MWException( 'Bad purge URL' );
                                }
                                $url = SquidUpdate::expand( $url );
+                               $conf = self::getRuleForURL( $url, $wgHTCPMulticastRouting );
+                               if ( !$conf ) {
+                                       wfDebug( "No HTCP rule configured for URL $url , skipping\n" );
+                                       continue;
+                               }
+                               if ( !isset( $conf['host'] ) || !isset( $conf['port'] ) ) {
+                                       throw new MWException( "Invalid HTCP rule for URL $url\n" );
+                               }
 
                                // Construct a minimal HTCP request diagram
                                // as per RFC 2756
@@ -199,7 +207,7 @@ class SquidUpdate {
                                // Send out
                                wfDebug( "Purging URL $url via HTCP\n" );
                                socket_sendto( $conn, $htcpPacket, $htcpLen, 0,
-                                       $wgHTCPMulticastAddress, $wgHTCPPort );
+                                       $conf['host'], $conf['port'] );
                        }
                } else {
                        $errstr = socket_strerror( socket_last_error() );
@@ -226,4 +234,20 @@ class SquidUpdate {
        static function expand( $url ) {
                return wfExpandUrl( $url, PROTO_INTERNAL );
        }
+       
+       /**
+        * Find the HTCP routing rule to use for a given URL.
+        * @param $url string URL to match
+        * @param $rules array Array of rules, see $wgHTCPMulticastRouting for format and behavior
+        * @return mixed Element of $rules that matched, or false if nothing matched
+        */
+       static function getRuleForURL( $url, $rules ) {
+               foreach ( $rules as $regex => $routing ) {
+                       if ( $regex === '' || preg_match( $regex, $url ) ) {
+                               return $routing;
+                       }
+               }
+               return false;
+       }
+       
 }