SquidPurgeClientPool.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. /**
  3. * Squid and Varnish cache purging.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. */
  22. class SquidPurgeClientPool {
  23. /** @var SquidPurgeClient[] */
  24. protected $clients = [];
  25. /** @var int */
  26. protected $timeout = 5;
  27. /**
  28. * @param array $options
  29. */
  30. function __construct( $options = [] ) {
  31. if ( isset( $options['timeout'] ) ) {
  32. $this->timeout = $options['timeout'];
  33. }
  34. }
  35. /**
  36. * @param SquidPurgeClient $client
  37. * @return void
  38. */
  39. public function addClient( $client ) {
  40. $this->clients[] = $client;
  41. }
  42. public function run() {
  43. $done = false;
  44. $startTime = microtime( true );
  45. while ( !$done ) {
  46. $readSockets = $writeSockets = [];
  47. foreach ( $this->clients as $clientIndex => $client ) {
  48. $sockets = $client->getReadSocketsForSelect();
  49. foreach ( $sockets as $i => $socket ) {
  50. $readSockets["$clientIndex/$i"] = $socket;
  51. }
  52. $sockets = $client->getWriteSocketsForSelect();
  53. foreach ( $sockets as $i => $socket ) {
  54. $writeSockets["$clientIndex/$i"] = $socket;
  55. }
  56. }
  57. if ( $readSockets === [] && $writeSockets === [] ) {
  58. break;
  59. }
  60. $exceptSockets = null;
  61. $timeout = min( $startTime + $this->timeout - microtime( true ), 1 );
  62. Wikimedia\suppressWarnings();
  63. $numReady = socket_select( $readSockets, $writeSockets, $exceptSockets, $timeout );
  64. Wikimedia\restoreWarnings();
  65. if ( $numReady === false ) {
  66. wfDebugLog( 'squid', __METHOD__ . ': Error in stream_select: ' .
  67. socket_strerror( socket_last_error() ) . "\n" );
  68. break;
  69. }
  70. // Check for timeout, use 1% tolerance since we aimed at having socket_select()
  71. // exit at precisely the overall timeout
  72. if ( microtime( true ) - $startTime > $this->timeout * 0.99 ) {
  73. wfDebugLog( 'squid', __CLASS__ . ": timeout ({$this->timeout}s)\n" );
  74. break;
  75. } elseif ( !$numReady ) {
  76. continue;
  77. }
  78. foreach ( $readSockets as $key => $socket ) {
  79. list( $clientIndex, ) = explode( '/', $key );
  80. $client = $this->clients[$clientIndex];
  81. $client->doReads();
  82. }
  83. foreach ( $writeSockets as $key => $socket ) {
  84. list( $clientIndex, ) = explode( '/', $key );
  85. $client = $this->clients[$clientIndex];
  86. $client->doWrites();
  87. }
  88. $done = true;
  89. foreach ( $this->clients as $client ) {
  90. if ( !$client->isIdle() ) {
  91. $done = false;
  92. }
  93. }
  94. }
  95. foreach ( $this->clients as $client ) {
  96. $client->close();
  97. }
  98. }
  99. }