Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate etags across shared storages #14764

Merged
merged 20 commits into from
Apr 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 22 additions & 15 deletions apps/files_sharing/appinfo/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\Files_Sharing\Appinfo;

$l = \OC::$server->getL10N('files_sharing');

OC::$CLASSPATH['OC_Share_Backend_File'] = 'files_sharing/lib/share/file.php';
OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'files_sharing/lib/share/folder.php';
OC::$CLASSPATH['OC\Files\Storage\Shared'] = 'files_sharing/lib/sharedstorage.php';
OC::$CLASSPATH['OC\Files\Cache\SharedScanner'] = 'files_sharing/lib/scanner.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'files_sharing/lib/cache.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'files_sharing/lib/permissions.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Updater'] = 'files_sharing/lib/updater.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'files_sharing/lib/watcher.php';
OC::$CLASSPATH['OCA\Files\Share\Maintainer'] = 'files_sharing/lib/maintainer.php';
OC::$CLASSPATH['OCA\Files\Share\Proxy'] = 'files_sharing/lib/proxy.php';
\OC::$CLASSPATH['OC_Share_Backend_File'] = 'files_sharing/lib/share/file.php';
\OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'files_sharing/lib/share/folder.php';
\OC::$CLASSPATH['OC\Files\Storage\Shared'] = 'files_sharing/lib/sharedstorage.php';
\OC::$CLASSPATH['OC\Files\Cache\SharedScanner'] = 'files_sharing/lib/scanner.php';
\OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'files_sharing/lib/cache.php';
\OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'files_sharing/lib/permissions.php';
\OC::$CLASSPATH['OC\Files\Cache\Shared_Updater'] = 'files_sharing/lib/updater.php';
\OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'files_sharing/lib/watcher.php';
\OC::$CLASSPATH['OCA\Files\Share\Maintainer'] = 'files_sharing/lib/maintainer.php';
\OC::$CLASSPATH['OCA\Files\Share\Proxy'] = 'files_sharing/lib/proxy.php';

// Exceptions
OC::$CLASSPATH['OCA\Files_Sharing\Exceptions\BrokenPath'] = 'files_sharing/lib/exceptions.php';
\OC::$CLASSPATH['OCA\Files_Sharing\Exceptions\BrokenPath'] = 'files_sharing/lib/exceptions.php';

$application = new Application();
$application->registerMountProviders();
$application->setupPropagation();

\OCP\App::registerAdmin('files_sharing', 'settings-admin');

\OCA\Files_Sharing\Helper::registerHooks();

OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
\OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
\OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');

OCP\Util::addScript('files_sharing', 'share');
OCP\Util::addScript('files_sharing', 'external');
\OCP\Util::addScript('files_sharing', 'share');
\OCP\Util::addScript('files_sharing', 'external');

// FIXME: registering a job here will cause additional useless SQL queries
// when the route is not cron.php, needs a better way
Expand Down
124 changes: 124 additions & 0 deletions apps/files_sharing/appinfo/application.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php
/**
* Copyright (c) 2015 Robin Appelman <[email protected]>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace OCA\Files_Sharing\Appinfo;

use OCA\Files_Sharing\Helper;
use OCA\Files_Sharing\MountProvider;
use OCA\Files_Sharing\Propagation\PropagationManager;
use OCP\AppFramework\App;
use OC\AppFramework\Utility\SimpleContainer;
use OCA\Files_Sharing\Controllers\ExternalSharesController;
use OCA\Files_Sharing\Controllers\ShareController;
use OCA\Files_Sharing\Middleware\SharingCheckMiddleware;
use \OCP\IContainer;

class Application extends App {
public function __construct(array $urlParams = array()) {
parent::__construct('files_sharing', $urlParams);

$container = $this->getContainer();
$server = $container->getServer();

/**
* Controllers
*/
$container->registerService('ShareController', function (SimpleContainer $c) use ($server) {
return new ShareController(
$c->query('AppName'),
$c->query('Request'),
$c->query('UserSession'),
$server->getAppConfig(),
$server->getConfig(),
$c->query('URLGenerator'),
$c->query('UserManager'),
$server->getLogger(),
$server->getActivityManager()
);
});
$container->registerService('ExternalSharesController', function (SimpleContainer $c) {
return new ExternalSharesController(
$c->query('AppName'),
$c->query('Request'),
$c->query('IsIncomingShareEnabled'),
$c->query('ExternalManager')
);
});

/**
* Core class wrappers
*/
$container->registerService('UserSession', function (SimpleContainer $c) use ($server) {
return $server->getUserSession();
});
$container->registerService('URLGenerator', function (SimpleContainer $c) use ($server) {
return $server->getUrlGenerator();
});
$container->registerService('UserManager', function (SimpleContainer $c) use ($server) {
return $server->getUserManager();
});
$container->registerService('IsIncomingShareEnabled', function (SimpleContainer $c) {
return Helper::isIncomingServer2serverShareEnabled();
});
$container->registerService('ExternalManager', function (SimpleContainer $c) use ($server) {
$user = $server->getUserSession()->getUser();
$uid = $user ? $user->getUID() : null;
return new \OCA\Files_Sharing\External\Manager(
$server->getDatabaseConnection(),
\OC\Files\Filesystem::getMountManager(),
\OC\Files\Filesystem::getLoader(),
$server->getHTTPHelper(),
$uid
);
});

/**
* Middleware
*/
$container->registerService('SharingCheckMiddleware', function (SimpleContainer $c) use ($server) {
return new SharingCheckMiddleware(
$c->query('AppName'),
$server->getConfig(),
$server->getAppManager()
);
});

// Execute middlewares
$container->registerMiddleware('SharingCheckMiddleware');

$container->registerService('MountProvider', function (IContainer $c) {
/** @var \OCP\IServerContainer $server */
$server = $c->query('ServerContainer');
return new MountProvider(
$server->getConfig(),
$c->query('PropagationManager')
);
});

$container->registerService('PropagationManager', function (IContainer $c) {
/** @var \OCP\IServerContainer $server */
$server = $c->query('ServerContainer');
return new PropagationManager(
$server->getUserSession(),
$server->getConfig()
);
});
}

public function registerMountProviders() {
/** @var \OCP\IServerContainer $server */
$server = $this->getContainer()->query('ServerContainer');
$mountProviderCollection = $server->getMountProviderCollection();
$mountProviderCollection->registerProvider($this->getContainer()->query('MountProvider'));
}

public function setupPropagation() {
$propagationManager = $this->getContainer()->query('PropagationManager');
\OCP\Util::connectHook('OC_Filesystem', 'setup', $propagationManager, 'globalSetup');
}
}
1 change: 0 additions & 1 deletion apps/files_sharing/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
*/
namespace OCA\Files_Sharing\AppInfo;

use OCA\Files_Sharing\Application;
use OCP\API;

$application = new Application();
Expand Down
115 changes: 0 additions & 115 deletions apps/files_sharing/application.php

This file was deleted.

2 changes: 0 additions & 2 deletions apps/files_sharing/lib/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
class Helper {

public static function registerHooks() {
\OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
\OCP\Util::connectHook('OC_Filesystem', 'setup', '\OCA\Files_Sharing\External\Manager', 'setup');
\OCP\Util::connectHook('OC_Filesystem', 'post_write', '\OC\Files\Cache\Shared_Updater', 'writeHook');
\OCP\Util::connectHook('OC_Filesystem', 'delete', '\OC\Files\Cache\Shared_Updater', 'deleteHook');
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Shared_Updater', 'renameHook');
\OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren');
Expand Down
72 changes: 72 additions & 0 deletions apps/files_sharing/lib/mountprovider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
/**
* Copyright (c) 2015 Robin Appelman <[email protected]>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace OCA\Files_Sharing;

use OC\Files\Filesystem;
use OCA\Files_Sharing\Propagation\PropagationManager;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Storage\IStorageFactory;
use OCP\IConfig;
use OCP\IUser;

class MountProvider implements IMountProvider {
/**
* @var \OCP\IConfig
*/
protected $config;

/**
* @var \OCA\Files_Sharing\Propagation\PropagationManager
*/
protected $propagationManager;

/**
* @param \OCP\IConfig $config
* @param \OCA\Files_Sharing\Propagation\PropagationManager $propagationManager
*/
public function __construct(IConfig $config, PropagationManager $propagationManager) {
$this->config = $config;
$this->propagationManager = $propagationManager;
}


/**
* Get all mountpoints applicable for the user and check for shares where we need to update the etags
*
* @param \OCP\IUser $user
* @param \OCP\Files\Storage\IStorageFactory $storageFactory
* @return \OCP\Files\Mount\IMountPoint[]
*/
public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) {
$shares = \OCP\Share::getItemsSharedWithUser('file', $user->getUID());
$propagator = $this->propagationManager->getSharePropagator($user->getUID());
$propagator->propagateDirtyMountPoints($shares);
$shares = array_filter($shares, function ($share) {
return $share['permissions'] > 0;
});
return array_map(function ($share) use ($user, $storageFactory) {
Filesystem::initMountPoints($share['uid_owner']);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand well, this doesn't interfere with the current user's mount point and simply mount the mount point of every share owner (in the case of reshares) into their own file tree.

I hope this doesn't become expensive in the long run, if many users are involved with many mount points / unrelated shared mount points. Ideal would be able to only mount the mount points relevant to this interaction.
Perhaps a potential performance improvement for a separate ticket ?

@icewind1991 what do you think ?

// for updating etags for the share owner when we make changes to this share.
$ownerPropagator = $this->propagationManager->getChangePropagator($share['uid_owner']);

// for updating our etags when changes are made to the share from the owners side (probably indirectly by us trough another share)
$this->propagationManager->listenToOwnerChanges($share['uid_owner'], $user->getUID());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... this one is for the logged in user to listen to changes made by share recipients ? (the dirty shares case ?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am user "current_user", this line would listen to changes made by a user "user_recipient1". Can this even happen within this same PHP request ? Is for the situations where we re-setupFS for another user within the same PHP call ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what I mean is that only "current_user" will be able to make changes since we're setting up "current_user" 's FS. "user_recipient1" won't.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In light of the new suggested comment, this means that: "The SharePropagator of the user "$user" will listen to the ChangePropagator of the user $share['uid_owner']".

return new SharedMount(
'\OC\Files\Storage\Shared',
'/' . $user->getUID() . '/' . $share['file_target'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: file_target already contains a leading slash usually, hopefully nothing to worry about

array(
'propagator' => $ownerPropagator,
'share' => $share,
'user' => $user->getUID()
),
$storageFactory
);
}, $shares);
}
}
Loading