[FileBackend] Moved scoped timeout stuff to its own file. Also removed some commented...
authorAaron Schulz <aaron@users.mediawiki.org>
Tue, 27 Mar 2012 18:45:48 +0000 (11:45 -0700)
committerAaron Schulz <aaron@users.mediawiki.org>
Tue, 27 Mar 2012 18:45:48 +0000 (11:45 -0700)
Change-Id: I0f0b7fe1a0f1da3fffe57c58b9f4d5a77d97cd29

includes/AutoLoader.php
includes/ScopedPHPTimeout.php [new file with mode: 0644]
includes/filerepo/backend/FileOp.php

index 44ed532..301c024 100644 (file)
@@ -195,6 +195,7 @@ $wgAutoloadLocalClasses = array(
        'RevisionList' => 'includes/RevisionList.php',
        'RSSFeed' => 'includes/Feed.php',
        'Sanitizer' => 'includes/Sanitizer.php',
+       'ScopedPHPTimeout' => 'includes/ScopedPHPTimeout.php',
        'SiteConfiguration' => 'includes/SiteConfiguration.php',
        'SiteStats' => 'includes/SiteStats.php',
        'SiteStatsInit' => 'includes/SiteStats.php',
@@ -521,7 +522,6 @@ $wgAutoloadLocalClasses = array(
        'MySqlLockManager'=> 'includes/filerepo/backend/lockmanager/DBLockManager.php',
        'NullLockManager' => 'includes/filerepo/backend/lockmanager/LockManager.php',
        'FileOp' => 'includes/filerepo/backend/FileOp.php',
-       'FileOpScopedPHPTimeout' => 'includes/filerepo/backend/FileOp.php',
        'StoreFileOp' => 'includes/filerepo/backend/FileOp.php',
        'CopyFileOp' => 'includes/filerepo/backend/FileOp.php',
        'MoveFileOp' => 'includes/filerepo/backend/FileOp.php',
diff --git a/includes/ScopedPHPTimeout.php b/includes/ScopedPHPTimeout.php
new file mode 100644 (file)
index 0000000..97c6bbf
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * Class to expand PHP execution time for a function call.
+ * On construction, set_time_limit() is called and set to $seconds.
+ * When the object goes out of scope, the timer is restarted, with
+ * the original time limit minus the time the object existed.
+ */
+class ScopedPHPTimeout {
+       protected $startTime; // float; seconds
+       protected $oldTimeout; // integer; seconds
+
+       protected static $stackDepth = 0; // integer
+       protected static $totalCalls = 0; // integer
+       protected static $totalElapsed = 0; // float; seconds
+
+       /* Prevent callers in infinite loops from running forever */
+       const MAX_TOTAL_CALLS = 1000000;
+       const MAX_TOTAL_TIME = 300; // seconds
+
+       /**
+        * @param $seconds integer
+        */
+       public function __construct( $seconds ) {
+               if ( ini_get( 'max_execution_time' ) > 0 ) { // CLI uses 0
+                       if ( self::$totalCalls >= self::MAX_TOTAL_CALLS ) {
+                               trigger_error( "Maximum invocations of " . __CLASS__ . " exceeded." );
+                       } elseif ( self::$totalElapsed >= self::MAX_TOTAL_TIME ) {
+                               trigger_error( "Time limit within invocations of " . __CLASS__ . " exceeded." );
+                       } elseif ( self::$stackDepth > 0 ) { // recursion guard
+                               trigger_error( "Resursive invocation of " . __CLASS__ . " attempted." );
+                       } else {
+                               $this->oldTimeout = ini_set( 'max_execution_time', $seconds );
+                               $this->startTime = microtime( true );
+                               ++self::$stackDepth;
+                               ++self::$totalCalls; // proof against < 1us scopes
+                       }
+               }
+       }
+
+       /**
+        * Restore the original timeout.
+        * This does not account for the timer value on __construct().
+        */
+       public function __destruct() {
+               if ( $this->oldTimeout ) {
+                       $elapsed = microtime( true ) - $this->startTime;
+                       // Note: a limit of 0 is treated as "forever"
+                       set_time_limit( max( 1, $this->oldTimeout - (int)$elapsed ) );
+                       // If each scoped timeout is for less than one second, we end up
+                       // restoring the original timeout without any decrease in value.
+                       // Thus web scripts in an infinite loop can run forever unless we
+                       // take some measures to prevent this. Track total time and calls.
+                       self::$totalElapsed += $elapsed;
+                       --self::$stackDepth;
+               }
+       }
+}
index 6cee9f9..ebc6b4c 100644 (file)
@@ -155,12 +155,6 @@ abstract class FileOp {
                        $status->setResult( true, $status->value );
                }
 
-               // Restart PHP's execution timer and set the timeout to safe amount.
-               // This handles cases where the operations take a long time or where we are
-               // already running low on time left. The old timeout is restored afterwards.
-               # @TODO: re-enable this for when the number of batches is high.
-               #$scopedTimeLimit = new FileOpScopedPHPTimeout( self::TIME_LIMIT_SEC );
-
                // Attempt each operation...
                foreach ( $performOps as $index => $fileOp ) {
                        if ( $fileOp->failed() ) {
@@ -432,63 +426,6 @@ abstract class FileOp {
        }
 }
 
-/**
- * FileOp helper class to expand PHP execution time for a function.
- * On construction, set_time_limit() is called and set to $seconds.
- * When the object goes out of scope, the timer is restarted, with
- * the original time limit minus the time the object existed.
- */
-class FileOpScopedPHPTimeout {
-       protected $startTime; // float; seconds
-       protected $oldTimeout; // integer; seconds
-
-       protected static $stackDepth = 0; // integer
-       protected static $totalCalls = 0; // integer
-       protected static $totalElapsed = 0; // float; seconds
-
-       /* Prevent callers in infinite loops from running forever */
-       const MAX_TOTAL_CALLS = 1000000;
-       const MAX_TOTAL_TIME = 300; // seconds
-
-       /**
-        * @param $seconds integer
-        */
-       public function __construct( $seconds ) {
-               if ( ini_get( 'max_execution_time' ) > 0 ) { // CLI uses 0
-                       if ( self::$totalCalls >= self::MAX_TOTAL_CALLS ) {
-                               trigger_error( "Maximum invocations of " . __CLASS__ . " exceeded." );
-                       } elseif ( self::$totalElapsed >= self::MAX_TOTAL_TIME ) {
-                               trigger_error( "Time limit within invocations of " . __CLASS__ . " exceeded." );
-                       } elseif ( self::$stackDepth > 0 ) { // recursion guard
-                               trigger_error( "Resursive invocation of " . __CLASS__ . " attempted." );
-                       } else {
-                               $this->oldTimeout = ini_set( 'max_execution_time', $seconds );
-                               $this->startTime = microtime( true );
-                               ++self::$stackDepth;
-                               ++self::$totalCalls; // proof against < 1us scopes
-                       }
-               }
-       }
-
-       /**
-        * Restore the original timeout.
-        * This does not account for the timer value on __construct().
-        */
-       public function __destruct() {
-               if ( $this->oldTimeout ) {
-                       $elapsed = microtime( true ) - $this->startTime;
-                       // Note: a limit of 0 is treated as "forever"
-                       set_time_limit( max( 1, $this->oldTimeout - (int)$elapsed ) );
-                       // If each scoped timeout is for less than one second, we end up
-                       // restoring the original timeout without any decrease in value.
-                       // Thus web scripts in an infinite loop can run forever unless we 
-                       // take some measures to prevent this. Track total time and calls.
-                       self::$totalElapsed += $elapsed;
-                       --self::$stackDepth;
-               }
-       }
-}
-
 /**
  * Store a file into the backend from a file on the file system.
  * Parameters similar to FileBackendStore::storeInternal(), which include: