updater.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. /**
  3. * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace OC\Files\Cache;
  9. use OCP\Util;
  10. /**
  11. * listen to filesystem hooks and change the cache accordingly
  12. */
  13. class Updater {
  14. /**
  15. * resolve a path to a storage and internal path
  16. *
  17. * @param string $path the relative path
  18. * @return array consisting of the storage and the internal path
  19. */
  20. static public function resolvePath($path) {
  21. $view = \OC\Files\Filesystem::getView();
  22. return $view->resolvePath($path);
  23. }
  24. /**
  25. * perform a write update
  26. *
  27. * @param string $path the relative path of the file
  28. */
  29. static public function writeUpdate($path) {
  30. /**
  31. * @var \OC\Files\Storage\Storage $storage
  32. * @var string $internalPath
  33. */
  34. list($storage, $internalPath) = self::resolvePath($path);
  35. if ($storage) {
  36. $cache = $storage->getCache($internalPath);
  37. $scanner = $storage->getScanner($internalPath);
  38. $scanner->scan($internalPath, Scanner::SCAN_SHALLOW);
  39. $cache->correctFolderSize($internalPath);
  40. self::correctFolder($path, $storage->filemtime($internalPath));
  41. self::correctParentStorageMtime($storage, $internalPath);
  42. }
  43. }
  44. /**
  45. * perform a delete update
  46. *
  47. * @param string $path the relative path of the file
  48. */
  49. static public function deleteUpdate($path) {
  50. /**
  51. * @var \OC\Files\Storage\Storage $storage
  52. * @var string $internalPath
  53. */
  54. list($storage, $internalPath) = self::resolvePath($path);
  55. if ($storage) {
  56. $cache = $storage->getCache($internalPath);
  57. $cache->remove($internalPath);
  58. $cache->correctFolderSize($internalPath);
  59. self::correctFolder($path, time());
  60. self::correctParentStorageMtime($storage, $internalPath);
  61. }
  62. }
  63. /**
  64. * preform a rename update
  65. *
  66. * @param string $from the relative path of the source file
  67. * @param string $to the relative path of the target file
  68. */
  69. static public function renameUpdate($from, $to) {
  70. /**
  71. * @var \OC\Files\Storage\Storage $storageFrom
  72. * @var \OC\Files\Storage\Storage $storageTo
  73. * @var string $internalFrom
  74. * @var string $internalTo
  75. */
  76. list($storageFrom, $internalFrom) = self::resolvePath($from);
  77. list($storageTo, $internalTo) = self::resolvePath($to);
  78. if ($storageFrom && $storageTo) {
  79. if ($storageFrom === $storageTo) {
  80. $cache = $storageFrom->getCache($internalFrom);
  81. $cache->move($internalFrom, $internalTo);
  82. $cache->correctFolderSize($internalFrom);
  83. $cache->correctFolderSize($internalTo);
  84. self::correctFolder($from, time());
  85. self::correctFolder($to, time());
  86. self::correctParentStorageMtime($storageFrom, $internalFrom);
  87. self::correctParentStorageMtime($storageTo, $internalTo);
  88. } else {
  89. self::deleteUpdate($from);
  90. self::writeUpdate($to);
  91. }
  92. }
  93. }
  94. /**
  95. * @brief get file owner and path
  96. * @param string $filename
  97. * @return array with the oweners uid and the owners path
  98. */
  99. private static function getUidAndFilename($filename) {
  100. $uid = \OC\Files\Filesystem::getOwner($filename);
  101. \OC\Files\Filesystem::initMountPoints($uid);
  102. if ($uid != \OCP\User::getUser()) {
  103. $info = \OC\Files\Filesystem::getFileInfo($filename);
  104. $ownerView = new \OC\Files\View('/' . $uid . '/files');
  105. $filename = $ownerView->getPath($info['fileid']);
  106. }
  107. return array($uid, '/files/' . $filename);
  108. }
  109. /**
  110. * Update the mtime and ETag of all parent folders
  111. *
  112. * @param string $path
  113. * @param string $time
  114. */
  115. static public function correctFolder($path, $time) {
  116. if ($path !== '' && $path !== '/') {
  117. list($owner, $realPath) = self::getUidAndFilename(dirname($path));
  118. /**
  119. * @var \OC\Files\Storage\Storage $storage
  120. * @var string $internalPath
  121. */
  122. $view = new \OC\Files\View('/' . $owner);
  123. list($storage, $internalPath) = $view->resolvePath($realPath);
  124. $cache = $storage->getCache();
  125. $id = $cache->getId($internalPath);
  126. while ($id !== -1) {
  127. $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath)));
  128. if ($realPath !== '') {
  129. $realPath = dirname($realPath);
  130. if($realPath === '/') {
  131. $realPath = "";
  132. }
  133. // check storage for parent in case we change the storage in this step
  134. list($storage, $internalPath) = $view->resolvePath($realPath);
  135. $cache = $storage->getCache();
  136. $id = $cache->getId($internalPath);
  137. } else {
  138. $id = -1;
  139. }
  140. }
  141. }
  142. }
  143. /**
  144. * update the storage_mtime of the parent
  145. *
  146. * @param \OC\Files\Storage\Storage $storage
  147. * @param string $internalPath
  148. */
  149. static private function correctParentStorageMtime($storage, $internalPath) {
  150. $cache = $storage->getCache();
  151. $parentId = $cache->getParentId($internalPath);
  152. $parent = dirname($internalPath);
  153. if ($parentId != -1) {
  154. $cache->update($parentId, array('storage_mtime' => $storage->filemtime($parent)));
  155. }
  156. }
  157. /**
  158. * @param array $params
  159. */
  160. static public function writeHook($params) {
  161. self::writeUpdate($params['path']);
  162. }
  163. /**
  164. * @param array $params
  165. */
  166. static public function touchHook($params) {
  167. $path = $params['path'];
  168. list($storage, $internalPath) = self::resolvePath($path);
  169. $cache = $storage->getCache();
  170. $id = $cache->getId($internalPath);
  171. if ($id !== -1) {
  172. $cache->update($id, array('etag' => $storage->getETag($internalPath)));
  173. }
  174. self::writeUpdate($path);
  175. }
  176. /**
  177. * @param array $params
  178. */
  179. static public function renameHook($params) {
  180. self::renameUpdate($params['oldpath'], $params['newpath']);
  181. }
  182. /**
  183. * @param array $params
  184. */
  185. static public function deleteHook($params) {
  186. self::deleteUpdate($params['path']);
  187. }
  188. }