/** * scan all the files and folders in a folder * * @param string $path * @param bool $recursive * @param int $reuse * @param int $folderId id for the folder to be scanned * @param bool $lock set to false to disable getting an additional read lock during scanning * @return int the size of the scanned folder or -1 if the size is unknown at this stage */ protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $folderId = null, $lock = true) { if ($reuse === -1) { $reuse = $recursive === self::SCAN_SHALLOW ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG; } $this->emit('\\OC\\Files\\Cache\\Scanner', 'scanFolder', array($path, $this->storageId)); $size = 0; if (!is_null($folderId)) { $folderId = $this->cache->getId($path); } $childQueue = $this->handleChildren($path, $recursive, $reuse, $folderId, $lock, $size); foreach ($childQueue as $child => $childId) { $childSize = $this->scanChildren($child, $recursive, $reuse, $childId, $lock); if ($childSize === -1) { $size = -1; } else { if ($size !== -1) { $size += $childSize; } } } if ($this->cacheActive) { $this->cache->update($folderId, array('size' => $size)); } $this->emit('\\OC\\Files\\Cache\\Scanner', 'postScanFolder', array($path, $this->storageId)); return $size; }
/** * update the storage_mtime of the direct parent in the cache to the mtime from the storage * * @param string $internalPath */ private function correctParentStorageMtime($internalPath) { $parentId = $this->cache->getParentId($internalPath); $parent = dirname($internalPath); if ($parentId != -1) { $this->cache->update($parentId, array('storage_mtime' => $this->storage->filemtime($parent))); } }
/** * @param string $path * @param array $data * @param int $fileId */ protected function updateCache($path, $data, $fileId = -1) { \OC_Hook::emit('Scanner', 'addToCache', array('file' => $path, 'data' => $data)); $this->emit('\OC\Files\Cache\Scanner', 'updateCache', array($path, $this->storageId, $data)); if ($this->cacheActive) { if ($fileId !== -1) { $this->cache->update($fileId, $data); } else { $this->cache->put($path, $data); } } }
/** * scan a single file and store it in the cache * * @param string $file * @param int $reuseExisting * @param bool $parentExistsInCache * @return array with metadata of the scanned file */ public function scanFile($file, $reuseExisting = 0, $parentExistsInCache = false) { if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) { $this->emit('\\OC\\Files\\Cache\\Scanner', 'scanFile', array($file, $this->storageId)); \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); $data = $this->getData($file); if ($data) { if ($file and !$parentExistsInCache) { $parent = dirname($file); if ($parent === '.' or $parent === '/') { $parent = ''; } if (!$this->cache->inCache($parent)) { $this->scanFile($parent); } } $newData = $data; $cacheData = $this->cache->get($file); if ($cacheData) { if (isset($cacheData['fileid'])) { $this->permissionsCache->remove($cacheData['fileid']); } if ($reuseExisting) { // prevent empty etag $etag = $cacheData['etag']; $propagateETagChange = false; if (empty($etag)) { $etag = $data['etag']; $propagateETagChange = true; } // only reuse data if the file hasn't explicitly changed if (isset($data['mtime']) && isset($cacheData['mtime']) && $data['mtime'] === $cacheData['mtime']) { if ($reuseExisting & self::REUSE_SIZE && $data['size'] === -1) { $data['size'] = $cacheData['size']; } if ($reuseExisting & self::REUSE_ETAG) { $data['etag'] = $etag; if ($propagateETagChange) { $parent = $file; while ($parent !== '') { $parent = dirname($parent); if ($parent === '.') { $parent = ''; } $parentCacheData = $this->cache->get($parent); $this->cache->update($parentCacheData['fileid'], array('etag' => $this->storage->getETag($parent))); } } } } // Only update metadata that has changed $newData = array_diff_assoc($data, $cacheData); if (isset($newData['etag'])) { $cacheDataString = print_r($cacheData, true); $dataString = print_r($data, true); \OCP\Util::writeLog('OC\\Files\\Cache\\Scanner', "!!! No reuse of etag for '{$file}' !!! \ncache: {$cacheDataString} \ndata: {$dataString}", \OCP\Util::DEBUG); } } } if (!empty($newData)) { $this->cache->put($file, $newData); $this->emit('\\OC\\Files\\Cache\\Scanner', 'postScanFile', array($file, $this->storageId)); \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId)); } } else { $this->cache->remove($file); } return $data; } return null; }
/** * update the metadata in the cache * * @param int $id * @param array $data */ public function update($id, array $data) { $this->cache->update($id, $data); }