diff --git a/CHANGELOG.md b/CHANGELOG.md index 1084972e..8113f3a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 2.6.3 +**Maintainer**: Raffael Sahli \ +**Date**: Wed Aug 21 10:30:42 CEST 2019 + +* CORE: [FIX] SMB folder does not get synced correctly (failed sync child node) #368 + + ## 2.6.2 **Maintainer**: Raffael Sahli \ **Date**: Thu Jul 11 12:25:42 CEST 2019 diff --git a/src/lib/Async/SmbScanner.php b/src/lib/Async/SmbScanner.php index a204bdb1..8fe7cea1 100755 --- a/src/lib/Async/SmbScanner.php +++ b/src/lib/Async/SmbScanner.php @@ -13,7 +13,6 @@ use Balloon\Filesystem\Node\Collection; use Balloon\Filesystem\Node\File; -use Balloon\Filesystem\Node\NodeInterface; use Balloon\Filesystem\Storage\Adapter\Blackhole; use Balloon\Filesystem\Storage\Adapter\Smb; use Balloon\Helper; @@ -44,6 +43,11 @@ class SmbScanner extends AbstractJob */ protected $logger; + /** + * Dummy storage. + */ + protected $dummy; + /** * Constructor. */ @@ -51,6 +55,7 @@ public function __construct(Server $server, LoggerInterface $logger) { $this->server = $server; $this->logger = $logger; + $this->dummy = new Blackhole(); } /** @@ -58,7 +63,6 @@ public function __construct(Server $server, LoggerInterface $logger) */ public function start(): bool { - $dummy = new Blackhole(); $fs = $this->server->getFilesystem(); $mount = $collection = $fs->findNodeById($this->data['id']); $user = $this->server->getUserById($collection->getOwner()); @@ -73,7 +77,7 @@ public function start(): bool $collection ->setFilesystem($user_fs) - ->setStorage($dummy); + ->setStorage($this->dummy); $path = $smb->getRoot(); if (isset($this->data['path'])) { @@ -88,7 +92,7 @@ public function start(): bool $parent_path = dirname($path); if ($path !== '.') { $collection = $this->getParent($collection, $share, $parent_path, $action); - $collection->setStorage($dummy); + $collection->setStorage($this->dummy); } } @@ -97,7 +101,7 @@ public function start(): bool $recursive = $this->data['recursive']; } - $this->recursiveIterator($collection, $mount, $share, $dummy, $user, $smb, $path, $recursive, $action); + $this->recursiveIterator($collection, $mount, $share, $user, $smb, $path, $recursive, $action); return true; } @@ -110,7 +114,6 @@ protected function getParent(Collection $mount, IShare $share, string $path, int $parent = $mount; $nodes = explode(DIRECTORY_SEPARATOR, $path); $sub = ''; - $dummy = $mount->getStorage(); foreach ($nodes as $child) { if ($child === '.') { @@ -120,7 +123,7 @@ protected function getParent(Collection $mount, IShare $share, string $path, int try { $sub .= DIRECTORY_SEPARATOR.$child; $parent = $parent->getChild($child); - $parent->setStorage($dummy); + $parent->setStorage($this->dummy); } catch (\Exception $e) { if ($action === INotifyHandler::NOTIFY_REMOVED) { throw $e; @@ -139,28 +142,16 @@ protected function getParent(Collection $mount, IShare $share, string $path, int } /** - * Delete node. + * Iterate recursively through smb share. */ - protected function deleteNode(NodeInterface $node, Blackhole $dummy): bool + protected function recursiveIterator(Collection $parent, Collection $mount, IShare $share, User $user, Smb $smb, string $path, bool $recursive, int $action): void { - if ($node instanceof Collection) { - $node->doRecursiveAction(function (NodeInterface $node) use ($dummy) { - if ($node instanceof Collection) { - $node->setStorage($dummy); - } - }); - } - - $node->delete(true); + $system_path = $path.DIRECTORY_SEPARATOR.$smb->getSystemFolder(); - return true; - } + if ($path === $system_path) { + return; + } - /** - * Iterate recursively through smb share. - */ - protected function recursiveIterator(Collection $parent, Collection $mount, IShare $share, Blackhole $dummy, User $user, Smb $smb, string $path, bool $recursive, int $action): void - { $this->logger->debug('sync smb path ['.$path.'] in mount ['.$mount->getId().'] from operation ['.$action.']', [ 'category' => get_class($this), 'recursive' => $recursive, @@ -177,16 +168,14 @@ protected function recursiveIterator(Collection $parent, Collection $mount, ISha } catch (NotFoundException $e) { if ($action === INotifyHandler::NOTIFY_REMOVED) { $node = $parent->getChild(Helper::mb_basename($path)); - $node->getParent()->setStorage($dummy); - $this->deleteNode($node, $dummy); + $node->getParent()->setStorage($this->dummy); + $node->delete(true); } return; } if ($node->isDirectory()) { - $parent->setStorage($dummy); - if ($path === DIRECTORY_SEPARATOR) { $child = $parent; } else { @@ -198,7 +187,7 @@ protected function recursiveIterator(Collection $parent, Collection $mount, ISha } if ($recursive === true) { - $child->setStorage($dummy); + $child->setStorage($this->dummy); $nodes = []; foreach ($share->dir($path) as $node) { @@ -210,7 +199,7 @@ protected function recursiveIterator(Collection $parent, Collection $mount, ISha $child_path = ($path === DIRECTORY_SEPARATOR) ? $path.$node->getName() : $path.DIRECTORY_SEPARATOR.$node->getName(); try { - $this->recursiveIterator($child, $mount, $share, $dummy, $user, $smb, $child_path, $recursive, $action); + $this->recursiveIterator($child, $mount, $share, $user, $smb, $child_path, $recursive, $action); } catch (\Exception $e) { $this->logger->error('failed sync child node ['.$child_path.'] in smb mount', [ 'category' => get_class($this), @@ -219,11 +208,11 @@ protected function recursiveIterator(Collection $parent, Collection $mount, ISha } } - foreach ($child->getChildren() as $sub_child) { + foreach ($child->getChildNodes() as $sub_child) { $sub_name = Normalizer::normalize($sub_child->getName()); if (!in_array($sub_name, $nodes)) { - $this->deleteNode($sub_child, $dummy); + $sub_child->delete(true); } } } diff --git a/src/lib/Filesystem.php b/src/lib/Filesystem.php index e3aae1bc..f08ba741 100755 --- a/src/lib/Filesystem.php +++ b/src/lib/Filesystem.php @@ -237,9 +237,9 @@ public function findNodeById($id, ?string $class = null, int $deleted = NodeInte /** * Find one. */ - public function findOne(array $filter, int $deleted = NodeInterface::DELETED_INCLUDE): NodeInterface + public function findOne(array $filter, int $deleted = NodeInterface::DELETED_INCLUDE, ?Collection $parent = null): NodeInterface { - $result = iterator_to_array($this->findNodesByFilterRecursiveChildren($filter, $deleted, 0, 1)); + $result = iterator_to_array($this->findNodesByFilterRecursiveChildren($filter, $deleted, 0, 1, $parent)); if (count($result) === 0) { throw new Exception\NotFound( @@ -512,7 +512,7 @@ public function getTrash(array $query = [], ?int $offset = null, ?int $limit = n /** * Find nodes with custom filter recursive. */ - public function findNodesByFilterRecursiveChildren(array $parent_filter, int $deleted, ?int $offset = null, ?int $limit = null): Generator + public function findNodesByFilterRecursiveChildren(array $parent_filter, int $deleted, ?int $offset = null, ?int $limit = null, ?Collection $parent = null): Generator { $query = [ ['$match' => $parent_filter], @@ -538,7 +538,7 @@ public function findNodesByFilterRecursiveChildren(array $parent_filter, int $de ['$group' => ['_id' => null, 'total' => ['$sum' => 1]]], ]; - return $this->executeAggregation($query, $offset, $limit); + return $this->executeAggregation($query, $offset, $limit, $parent); } /** @@ -565,7 +565,7 @@ public function findNodesByFilterRecursive(Collection $collection, array $filter ['$group' => ['_id' => null, 'total' => ['$sum' => 1]]], ]; - return $this->executeAggregation($query, $offset, $limit); + return $this->executeAggregation($query, $offset, $limit, $collection); } /** @@ -598,7 +598,7 @@ public function findNodesByFilterUser(int $deleted, array $filter, ?int $offset /** * Init node. */ - public function initNode(array $node): NodeInterface + public function initNode(array $node, ?Collection $parent = null): NodeInterface { $id = $node['_id']; @@ -607,11 +607,11 @@ public function initNode(array $node): NodeInterface } if (isset($node['parent'])) { - $parent = $this->findNodeById($node['parent']); + if ($parent === null || $parent->getId() != $node['parent']) { + $parent = $this->findNodeById($node['parent']); + } } elseif ($node['_id'] !== null) { $parent = $this->getRoot(); - } else { - $parent = null; } if (!array_key_exists('directory', $node)) { @@ -733,7 +733,7 @@ protected function prepareChildrenFilter(int $deleted) /** * Execute complex aggregation. */ - protected function executeAggregation(array $query, ?int $offset = null, ?int $limit = null): Generator + protected function executeAggregation(array $query, ?int $offset = null, ?int $limit = null, ?Collection $parent = null): Generator { $result = $this->db->storage->aggregate($query); @@ -751,7 +751,7 @@ protected function executeAggregation(array $query, ?int $offset = null, ?int $l foreach ($result as $node) { try { - yield $this->initNode($node); + yield $this->initNode($node, $parent); } catch (\Exception $e) { $this->logger->error('remove node from result list, failed load node', [ 'category' => get_class($this), diff --git a/src/lib/Filesystem/Node/Collection.php b/src/lib/Filesystem/Node/Collection.php index 2b7cc782..ee6f5c98 100644 --- a/src/lib/Filesystem/Node/Collection.php +++ b/src/lib/Filesystem/Node/Collection.php @@ -243,7 +243,7 @@ public function getChildNodes(int $deleted = NodeInterface::DELETED_EXCLUDE, arr $filter = $this->getChildrenFilter($deleted, $filter); if ($recursive === false) { - return $this->_fs->findNodesByFilterRecursiveChildren($filter, $deleted, $offset, $limit); + return $this->_fs->findNodesByFilterRecursiveChildren($filter, $deleted, $offset, $limit, $this); } unset($filter['parent']); @@ -320,7 +320,7 @@ public function getChild($name, int $deleted = NodeInterface::DELETED_EXCLUDE, a $filter = $this->getChildrenFilter($deleted, $filter); $filter['name'] = new Regex('^'.preg_quote($name).'$', 'i'); - return $this->_fs->findOne($filter); + return $this->_fs->findOne($filter, $deleted, $this); } /** @@ -606,7 +606,7 @@ public function addDirectory($name, array $attributes = [], int $conflict = Node $this->changed = $save['changed']; $this->save('changed'); - $new = $this->_fs->initNode($save); + $new = $this->_fs->initNode($save, $this); $this->_hook->run('postCreateCollection', [$this, $new, $clone]); return $new; @@ -676,7 +676,7 @@ public function addFile($name, ?ObjectId $session = null, array $attributes = [] $this->changed = $save['changed']; $this->save('changed'); - $file = $this->_fs->initNode($save); + $file = $this->_fs->initNode($save, $this); if ($session !== null) { $file->setContent($session, $attributes); diff --git a/src/lib/Filesystem/Node/Factory.php b/src/lib/Filesystem/Node/Factory.php index ca71e2d3..112562c2 100755 --- a/src/lib/Filesystem/Node/Factory.php +++ b/src/lib/Filesystem/Node/Factory.php @@ -105,6 +105,10 @@ public function build(Filesystem $fs, array $node, ?Collection $parent): NodeInt $storage = $this->storage; + if ($parent !== null) { + $storage = $parent->getStorage(); + } + if (isset($node['reference'])) { $share = $fs->findRawNode($node['reference']); if (isset($share['mount'])) {