[FEATURE] Cache method results in WebDAV frontend
authorAndreas Wolf <andreas.wolf@typo3.org>
Wed, 3 Jun 2015 19:08:49 +0000 (21:08 +0200)
committerAndreas Wolf <andreas.wolf@typo3.org>
Sun, 7 Jun 2015 19:50:15 +0000 (21:50 +0200)
Classes/Dav/CachingWebDavFrontend.php [new file with mode: 0644]
Classes/Dav/WebDavFrontend.php
Classes/Driver/WebDavDriver.php

diff --git a/Classes/Dav/CachingWebDavFrontend.php b/Classes/Dav/CachingWebDavFrontend.php
new file mode 100644 (file)
index 0000000..a3ff8b2
--- /dev/null
@@ -0,0 +1,155 @@
+<?php
+namespace TYPO3\FalWebdav\Dav;
+
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+
+class CachingWebDavFrontend extends WebDavFrontend {
+
+       /**
+        * @var FrontendInterface
+        */
+       protected $cache;
+
+       protected $cacheHits = array(
+               'propFind' => 0,
+               'listFiles' => 0,
+               'listFolders' => 0,
+               'getFileInfo' => 0,
+       );
+
+       protected $cacheMisses = array(
+               'propFind' => 0,
+               'listFiles' => 0,
+               'listFolders' => 0,
+               'getFileInfo' => 0,
+       );
+
+
+       public function __construct(WebDavClient $client, $baseUrl, $storageUid, FrontendInterface $cache) {
+               parent::__construct($client, $baseUrl, $storageUid);
+
+               $this->cache = $cache;
+       }
+
+       /**
+        * @return FrontendInterface
+        */
+       protected function getCache() {
+               if (!$this->cache) {
+                       /** @var CacheManager $cacheManager */
+                       $cacheManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager');
+                       $this->cache = $cacheManager->getCache('tx_falwebdav_directorylisting');
+               }
+
+               return $this->cache;
+       }
+
+       public function propFind($path) {
+               $cacheKey = $this->getCacheIdentifierForResponse($path);
+
+               if (!$this->getCache()->has($cacheKey)) {
+                       ++$this->cacheMisses[__FUNCTION__];
+                       // TODO also extract information on all files/folders
+                       $this->getCache()->set($cacheKey, parent::propFind($path));
+               } else {
+                       ++$this->cacheHits[__FUNCTION__];
+               }
+
+               return $this->getCache()->get($cacheKey);
+       }
+
+       public function listFiles($path) {
+               $cacheKey = $this->getCacheIdentifierForFileList($path);
+               if (!$this->getCache()->has($cacheKey)) {
+                       ++$this->cacheMisses[__FUNCTION__];
+                       $this->getCache()->set($cacheKey, parent::listFiles($path));
+               } else {
+                       ++$this->cacheHits[__FUNCTION__];
+               }
+
+               return $this->getCache()->get($cacheKey);
+       }
+
+       public function listFolders($path) {
+               $cacheKey = $this->getCacheIdentifierForFolderList($path);
+               if (!$this->getCache()->has($cacheKey)) {
+                       ++$this->cacheMisses[__FUNCTION__];
+                       $this->getCache()->set($cacheKey, parent::listFolders($path));
+               } else {
+                       ++$this->cacheHits[__FUNCTION__];
+               }
+
+               return $this->getCache()->get($cacheKey);
+       }
+
+       public function getFileInfo($path) {
+               $cacheKey = $this->getCacheIdentifierForFileInfo($path);
+               if (!$this->getCache()->has($cacheKey)) {
+                       ++$this->cacheMisses[__FUNCTION__];
+                       $this->getCache()->set($cacheKey, parent::getFileInfo($path));
+               } else {
+                       ++$this->cacheHits[__FUNCTION__];
+               }
+
+               return $this->getCache()->get($cacheKey);
+       }
+
+       public function logCacheStatistics() {
+               print_r(sprintf('WebDAV frontend cache stats (hits/misses): '
+                       .'propFind %d/%d, listFiles %d/%d, listFolders %d/%d, getFileInfo %d/%d',
+                       $this->cacheHits['propFind'], $this->cacheMisses['propFind'],
+                       $this->cacheHits['listFiles'], $this->cacheMisses['listFiles'],
+                       $this->cacheHits['listFolders'], $this->cacheMisses['listFolders'],
+                       $this->cacheHits['getFileInfo'], $this->cacheMisses['getFileInfo']
+                       )
+               );
+       }
+
+       /**
+        * Returns the cache identifier for the raw response for a given path
+        *
+        * @param string $url
+        * @return string
+        */
+       protected function getCacheIdentifierForResponse($url) {
+               return 'davResponse-' . sha1($url);
+       }
+
+       /**
+        * Returns the cache identifier for the file list of a given path.
+        *
+        * @param string $path
+        * @return string
+        */
+       protected function getCacheIdentifierForFileList($path) {
+               return 'filelist-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
+       }
+
+       /**
+        * Returns the cache identifier for the folder list of a given path.
+        *
+        * @param string $path
+        * @return string
+        */
+       protected function getCacheIdentifierForFolderList($path) {
+               return 'folderlist-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
+       }
+
+       /**
+        * Returns the cache identifier for the file list of a given path.
+        *
+        * @param string $path
+        * @return string
+        */
+       protected function getCacheIdentifierForFileInfo($path) {
+               return 'fileinfo-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
+       }
+
+       function __destruct() {
+               $this->logCacheStatistics();
+       }
+
+}
index a0a9ab1..6fc85c0 100644 (file)
@@ -97,8 +97,6 @@ class WebDavFrontend {
                        // At least Apache does not sort them before returning
                        uksort($propfindResultArray, 'strnatcasecmp');
 
-                       // TODO store result in cache
-
                        return $propfindResultArray;
                } catch (DAV\Exception\NotFound $exception) {
                        $this->logger->warning('URL not found: ' . $url);
@@ -121,10 +119,6 @@ class WebDavFrontend {
         * @return array A list of file names in the path
         */
        public function listFiles($path) {
-               $this->logger->debug("cache identifier: " . $this->getCacheIdentifierForResponse($path));
-
-               // TODO check cache
-
                $files = $this->listItems($path, function ($currentItem) {
                        if (substr($currentItem, -1) == '/') {
                                return FALSE;
@@ -132,8 +126,6 @@ class WebDavFrontend {
                        return TRUE;
                });
 
-               // TODO store result in cache
-
                return $files;
        }
 
@@ -142,7 +134,6 @@ class WebDavFrontend {
         * @return array A list of folder names in the path
         */
        public function listFolders($path) {
-               // TODO caching
                $folders = $this->listItems($path, function ($currentItem) {
                        if (substr($currentItem, -1) != '/') {
                                return FALSE;
@@ -204,7 +195,6 @@ class WebDavFrontend {
        }
 
        protected function extractFileInfo($path, $propFindArray) {
-$this->logger->debug("File info for $path: " . json_encode($propFindArray));
                $fileInfo = array(
                        'mtime' => (int)strtotime($propFindArray['{DAV:}getlastmodified']),
                        'ctime' => (int)strtotime($propFindArray['{DAV:}creationdate']),
@@ -219,36 +209,6 @@ $this->logger->debug("File info for $path: " . json_encode($propFindArray));
        }
 
        /**
-        * Returns the cache identifier for the raw response for a given path
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForResponse($path) {
-               return 'davResponse-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
-       }
-
-       /**
-        * Returns the cache identifier for the file list of a given path.
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForFileList($path) {
-               return 'filelist-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
-       }
-
-       /**
-        * Returns the cache identifier for the file list of a given path.
-        *
-        * @param string $path
-        * @return string
-        */
-       protected function getCacheIdentifierForFileInfo($path) {
-               return 'fileinfo-' . sha1($this->baseUrl . ':' . trim($path, '/') . '/');
-       }
-
-       /**
         * @param $path
         * @return string
         */
index 53548bf..b374d2e 100644 (file)
@@ -25,6 +25,7 @@ use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException;
 use TYPO3\CMS\Core\Resource\ResourceStorage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
+use TYPO3\FalWebdav\Dav\CachingWebDavFrontend;
 use TYPO3\FalWebdav\Dav\WebDavFrontend;
 use TYPO3\FalWebdav\Dav\WebDavClient;
 use TYPO3\FalWebdav\Utility\EncryptionUtility;
@@ -133,7 +134,7 @@ class WebDavDriver extends AbstractDriver {
 
        protected function getFrontend() {
                if (!$this->frontend) {
-                       $this->frontend = new WebDavFrontend($this->davClient, $this->baseUrl, $this->storageUid);
+                       $this->frontend = new CachingWebDavFrontend($this->davClient, $this->baseUrl, $this->storageUid, $this->getCache());
                }
                return $this->frontend;
        }