From 5b4d34d1cb6cf1443535d8c02609d9d4cf4fcab5 Mon Sep 17 00:00:00 2001 From: djmaze <> Date: Fri, 17 Dec 2021 01:17:06 +0100 Subject: [PATCH] Improved Storage garbage collection Improved RecRmDir() and RecTimeDirRemove() --- plugins/demo-account/storage.php | 3 +- .../0.0.0/app/libraries/MailSo/Base/Utils.php | 33 +++++++++++-------- .../0.0.0/app/libraries/RainLoop/Actions.php | 4 +-- .../app/libraries/RainLoop/Actions/User.php | 4 +++ .../libraries/RainLoop/Providers/Storage.php | 10 ++++-- .../Providers/Storage/FileStorage.php | 30 ++++++++++------- 6 files changed, 52 insertions(+), 32 deletions(-) diff --git a/plugins/demo-account/storage.php b/plugins/demo-account/storage.php index 0d4ece443..aafb26e4c 100644 --- a/plugins/demo-account/storage.php +++ b/plugins/demo-account/storage.php @@ -26,7 +26,7 @@ class DemoStorage extends \RainLoop\Providers\Storage\FileStorage // Garbage collection if (!static::$gc_done) { static::$gc_done = true; - if (\is_dir($sDataPath) && 0 === \random_int(0, 100)) { + if (!\random_int(0, \max(50, \ini_get('session.gc_divisor')))) { \MailSo\Base\Utils::RecTimeDirRemove($sDataPath, 3600 * 3); // 3 hours } } @@ -37,7 +37,6 @@ class DemoStorage extends \RainLoop\Providers\Storage\FileStorage } else if (StorageType::SESSION === $iStorageType) { $sDataPath .= '/.sessions'; } - \is_dir($sDataPath) || \mkdir($sDataPath, 0700, true); return $sDataPath . '/' . ($sKey ? \RainLoop\Utils::fixName($sKey) : ''); } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Base/Utils.php b/snappymail/v/0.0.0/app/libraries/MailSo/Base/Utils.php index 5eed7ca62..8df3d1fab 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Base/Utils.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Base/Utils.php @@ -886,8 +886,8 @@ abstract class Utils public static function RecRmDir(string $sDir) : bool { - if (\is_dir($sDir)) - { + \clearstatcache(); + if (\is_dir($sDir)) { $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($sDir, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST); @@ -899,27 +899,34 @@ abstract class Utils } } \clearstatcache(); - +// \realpath_cache_size() && \clearstatcache(true); return \rmdir($sDir); } return false; } - public static function RecTimeDirRemove(string $sTempPath, int $iTime2Kill, int $iNow = 0) : bool + public static function RecTimeDirRemove(string $sDir, int $iTime2Kill) : bool { - $iTime = ($iNow ?: \time()) - $iTime2Kill; \clearstatcache(); - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($sTempPath, \FilesystemIterator::SKIP_DOTS), - \RecursiveIteratorIterator::CHILD_FIRST); - foreach ($iterator as $path) { - if ($path->isFile() && '.' !== $path->getBasename()[0] && $path->getMTime() < $iTime) { - \unlink($path); + if (\is_dir($sDir)) { + $iTime = \time() - $iTime2Kill; + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($sDir, \FilesystemIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST); + foreach ($iterator as $path) { + if ($path->isFile() && $path->getMTime() < $iTime) { + \unlink($path); + } else if ($path->isDir() && !(new \FilesystemIterator($path))->valid()) { + \rmdir($path); + } } + \clearstatcache(); +// \realpath_cache_size() && \clearstatcache(true); + return !(new \FilesystemIterator($sDir))->valid() && \rmdir($sDir); } - \clearstatcache(); - return true; + + return false; } public static function Utf8Truncate(string $sUtfString, int $iLength) : string diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 782d91a8e..9d13bdaf6 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -466,14 +466,14 @@ class Actions public function StorageProvider(bool $bLocal = false): Providers\Storage { if ($bLocal) { - if (null === $this->oLocalStorageProvider) { + if (!$this->oLocalStorageProvider) { $this->oLocalStorageProvider = new Providers\Storage( $this->fabrica('storage-local')); } return $this->oLocalStorageProvider; } else { - if (null === $this->oStorageProvider) { + if (!$this->oStorageProvider) { $this->oStorageProvider = new Providers\Storage( $this->fabrica('storage')); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php index 8e8c73e05..2d266bb31 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php @@ -253,6 +253,10 @@ trait User $this->Logger()->Write('Cacher GC: Begin'); $this->Cacher()->GC(48); $this->Logger()->Write('Cacher GC: End'); + + $this->Logger()->Write('Storage GC: Begin'); + $this->StorageProvider()->GC(); + $this->Logger()->Write('Storage GC: End'); } else if ($bFilesCache) { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php index 7788e3684..18c302c31 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php @@ -81,12 +81,16 @@ class Storage extends \RainLoop\Providers\AbstractProvider public function IsActive() : bool { - return $this->oDriver instanceof \RainLoop\Providers\Storage\IStorage; + return true; } public function IsLocal() : bool { - return $this->oDriver instanceof \RainLoop\Providers\Storage\IStorage && - $this->oDriver->IsLocal(); + return $this->oDriver->IsLocal(); + } + + public function GC() : void + { + $this->oDriver->GC(); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php index 460ab17c9..435cddbc8 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php @@ -24,7 +24,7 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage public function __construct(string $sStoragePath, bool $bLocal = false) { $this->sDataPath = \rtrim(\trim($sStoragePath), '\\/'); - $this->bLocal = !!$bLocal; + $this->bLocal = $bLocal; $this->oLogger = null; } @@ -34,7 +34,13 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage public function Put($mAccount, int $iStorageType, string $sKey, string $sValue) : bool { $sFileName = $this->generateFileName($mAccount, $iStorageType, $sKey, true); - return $sFileName && false !== \file_put_contents($sFileName, $sValue); + try { + $sFileName && \RainLoop\Utils::saveFile($sFileName, $sValue); + return true; + } catch (\Throwable $e) { + \error_log("{$e->getMessage()}: {$sFileName}"); + } + return false; } /** @@ -138,16 +144,6 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage } } - // Cleanup SignMe - if (StorageType::SIGN_ME === $iStorageType && $sKey && 0 === \random_int(0, 25) && \is_dir($sFilePath)) { - \MailSo\Base\Utils::RecTimeDirRemove(\is_dir($sFilePath), 3600 * 24 * 30); // 30 days - } - - // Cleanup sessions - if (StorageType::SESSION === $iStorageType && $sKey && 0 === \random_int(0, 25) && \is_dir($sFilePath)) { - \MailSo\Base\Utils::RecTimeDirRemove(\is_dir($sFilePath), 3600 * 3); // 3 hours - } - return $sFilePath; } @@ -155,4 +151,14 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage { $this->oLogger = $oLogger; } + + public function GC() : void + { + foreach (\glob("{$this->sDataPath}/*", GLOB_ONLYDIR) as $sDomain) { + foreach (\glob("{$sDomain}/*", GLOB_ONLYDIR) as $sLocal) { + \MailSo\Base\Utils::RecTimeDirRemove("{$sLocal}/.sign_me", 3600 * 24 * 30); // 30 days + \MailSo\Base\Utils::RecTimeDirRemove("{$sLocal}/.sessions", 3600 * 3); // 3 hours + } + } + } }