]> source.dussan.org Git - nextcloud-server.git/commitdiff
add function to invalidate one opcache file, use it if possible #9885
authorAdam Williamson <awilliam@redhat.com>
Sat, 13 Sep 2014 06:33:18 +0000 (23:33 -0700)
committerAdam Williamson <awilliam@redhat.com>
Fri, 7 Nov 2014 01:58:58 +0000 (17:58 -0800)
Issue #9885 appears to be triggered by ownCloud invalidating the entire
PHP opcache. Testing indicates it can be avoided by only invalidating the
single file that was written from the opcache, instead of clearing the
whole thing. In general it is more efficient to invalidate only the single
file that was changed, rather than the whole cache.

This adds a deleteFromOpcodeCache() function which invalidates a single
file from the opcache if possible, returning true if the underlying
function returns true (which may mean 'success', or 'file does not exist',
or 'file exists but is not in opcache', all of which are OK to treat as
good for our purposes). It also changes writeData() in config.php to try
using deleteFromOpcodeCache() and only fall back on clearOpcodeCache() if
that fails.

lib/private/config.php
lib/private/util.php

index f0548442ab55200236b2297c33a7bb6989152971..8bb2a5c48d1cc515a9f683f64394f264e51995b8 100644 (file)
@@ -207,8 +207,11 @@ class Config {
                flock($filePointer, LOCK_UN);
                fclose($filePointer);
 
-               // Clear the opcode cache
-               \OC_Util::clearOpcodeCache();
+               // Try invalidating the opcache just for the file we wrote...
+               if (!\OC_Util::deleteFromOpcodeCache($this->configFilename)) {
+                       // But if that doesn't work, clear the whole cache.
+                       \OC_Util::clearOpcodeCache();
+               }
        }
 }
 
index bee0a579192a625dc29d851f31a44767e228c4b1..fa0c6f13c9aa7849a3ef0ca88c939949ae486f67 100644 (file)
@@ -1249,6 +1249,31 @@ class OC_Util {
                return $theme;
        }
 
+       /**
+        * Clear a single file from the opcode cache
+        * This is useful for writing to the config file
+        * in case the opcode cache does not re-validate files
+        * Returns true if successful, false if unsuccessful:
+        * caller should fall back on clearing the entire cache
+        * with clearOpcodeCache() if unsuccessful
+        *
+        * @return bool true if underlying function returns true, otherwise false
+        */
+       public static function deleteFromOpcodeCache($path=NULL) {
+               $ret = false;
+               if ($path) {
+                       // APC >= 3.1.1
+                       if (function_exists('apc_delete_file')) {
+                               $ret = @apc_delete_file($path);
+                       }
+                       // Zend OpCache >= 7.0.0, PHP >= 5.5.0
+                       if (function_exists('opcache_invalidate')) {
+                               $ret = opcache_invalidate($path);
+                       }
+               }
+               return $ret;
+       }
+
        /**
         * Clear the opcode cache if one exists
         * This is necessary for writing to the config file