Skip to content

Commit

Permalink
Merge pull request #32414 from owncloud/backport/31851
Browse files Browse the repository at this point in the history
Backport/31851 async put
  • Loading branch information
Vincent Petry authored Sep 4, 2018
2 parents 92dc5ee + f25fcbf commit a5c8dd5
Show file tree
Hide file tree
Showing 29 changed files with 1,395 additions and 145 deletions.
34 changes: 34 additions & 0 deletions apps/dav/appinfo/Migrations/Version20180622095921.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
namespace OCA\dav\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Types\Type;
use OCP\Migration\ISchemaMigration;

class Version20180622095921 implements ISchemaMigration {
public function changeSchema(Schema $schema, array $options) {
$prefix = $options['tablePrefix'];
if ($schema->hasTable("${prefix}dav_job_status")) {
return;
}
$table = $schema->createTable("${prefix}dav_job_status");
$table->addColumn('id', Type::BIGINT, [
'autoincrement' => true,
'notnull' => true,
'length' => 20,
]);
$table->addColumn('uuid', Type::GUID, [
'notnull' => true,
]);
$table->addColumn('user_id', Type::STRING, [
'notnull' => true,
'length' => 64,
]);
$table->addColumn('status_info', Type::STRING, [
'notnull' => true,
'length' => 4000,
]);
$table->setPrimaryKey(['id']);
$table->addUniqueIndex(['uuid']);
}
}
2 changes: 1 addition & 1 deletion apps/dav/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<description>ownCloud WebDAV endpoint</description>
<licence>AGPL</licence>
<author>owncloud.org</author>
<version>0.3.2</version>
<version>0.4.0</version>
<default_enable/>
<use-migrations>true</use-migrations>
<types>
Expand Down
23 changes: 21 additions & 2 deletions apps/dav/lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,36 @@
namespace OCA\DAV;

use OCP\Capabilities\ICapability;
use OCP\IConfig;

class Capabilities implements ICapability {
/** @var IConfig */
private $config;

/**
* Capabilities constructor.
*
* @param IConfig $config
*/
public function __construct(IConfig $config) {
$this->config = $config;
}

public function getCapabilities() {
return [
$cap = [
'dav' => [
'chunking' => '1.0',
'zsync' => '1.0',
'reports' => [
'search-files',
],
]
]
];

if ($this->config->getSystemValue('dav.enable.async', false)) {
$cap['async'] = '1.0';
}

return $cap;
}
}
1 change: 1 addition & 0 deletions apps/dav/lib/Connector/Sabre/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Server extends \Sabre\DAV\Server {

/**
* @see \Sabre\DAV\Server
* @param null $treeOrNode
* @throws \Sabre\DAV\Exception
*/
public function __construct($treeOrNode = null) {
Expand Down
169 changes: 169 additions & 0 deletions apps/dav/lib/DAV/LazyOpsPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\DAV\DAV;

use OCA\DAV\JobStatus\Entity\JobStatus;
use OCA\DAV\JobStatus\Entity\JobStatusMapper;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\Shutdown\IShutdownManager;
use Sabre\DAV\Exception;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\DAV\UUIDUtil;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\Response;
use Sabre\HTTP\ResponseInterface;

/**
* Class LazyOpsPlugin
*
* @package OCA\DAV\DAV
*/
class LazyOpsPlugin extends ServerPlugin {

/** @var Server */
private $server;
/** @var string */
private $jobId;
/** @var JobStatus */
private $entity;
/** @var IUserSession */
private $userSession;
/** @var IURLGenerator */
private $urlGenerator;
/** @var IShutdownManager */
private $shutdownManager;
/** @var ILogger */
private $logger;
/** @var JobStatusMapper */
private $mapper;

public function __construct(IUserSession $userSession,
IURLGenerator $urlGenerator,
IShutdownManager $shutdownManager,
JobStatusMapper $jobStatusMapper,
ILogger $logger) {
$this->userSession = $userSession;
$this->urlGenerator = $urlGenerator;
$this->shutdownManager = $shutdownManager;
$this->logger = $logger;
$this->mapper = $jobStatusMapper;
}

/**
* @param Server $server
*/
public function initialize(Server $server) {
$this->server = $server;
$server->on('method:MOVE', [$this, 'httpMove'], 90);
}

/**
* @param RequestInterface $request
* @param ResponseInterface $response
* @return bool
* @throws Exception\NotAuthenticated
*/
public function httpMove(RequestInterface $request, ResponseInterface $response) {
if (!$request->getHeader('OC-LazyOps')) {
return true;
}

$this->jobId = UUIDUtil::getUUID();
$this->setJobStatus([
'status' => 'init'
]);
$userId = $this->getUserId();
$location = $this->urlGenerator
->linkTo('', 'remote.php') . "/dav/job-status/{$userId}/{$this->jobId}";

$response->setStatus(202);
$response->setHeader('Connection', 'close');
$response->setHeader('OC-JobStatus-Location', $location);

$this->shutdownManager->register(function () use ($request, $response) {
return $this->afterResponse($request, $response);
}, IShutdownManager::HIGH);

return false;
}

public function afterResponse(RequestInterface $request, ResponseInterface $response) {
if (!$request->getHeader('OC-LazyOps')) {
return true;
}

\flush();
$request->removeHeader('OC-LazyOps');
$responseDummy = new Response();
try {
$this->setJobStatus([
'status' => 'started'
]);
$this->server->emit('method:MOVE', [$request, $responseDummy]);

$this->setJobStatus([
'status' => 'finished',
'fileId' => $response->getHeader('OC-FileId'),
'ETag' => $response->getHeader('ETag')
]);
} catch (\Exception $ex) {
$this->logger->logException($ex);

$this->setJobStatus([
'status' => 'error',
'errorCode' => $ex instanceof Exception ? $ex->getHTTPCode() : 500,
'errorMessage' => $ex->getMessage()
]);
}
return false;
}

private function setJobStatus(array $status) {
if ($this->entity === null) {
$userId = $this->getUserId();

$this->entity = new JobStatus();
$this->entity->setStatusInfo(\json_encode($status));
$this->entity->setUserId($userId);
$this->entity->setUuid($this->jobId);
$this->mapper->insert($this->entity);
} else {
$this->entity->setStatusInfo(\json_encode($status));
$this->mapper->update($this->entity);
}
}

/**
* @return string
* @throws Exception\NotAuthenticated
*/
private function getUserId() {
$user = $this->userSession->getUser();
if ($user === null) {
throw new Exception\NotAuthenticated();
}
return $user->getUID();
}
}
42 changes: 42 additions & 0 deletions apps/dav/lib/JobStatus/Entity/JobStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\DAV\JobStatus\Entity;

use OCP\AppFramework\Db\Entity;

/**
* Class JobStatus
*
* @method string getUuid()
* @method void setUuid(string $uuid)
* @method string getUserId()
* @method void setUserId(string $userId)
* @method string getStatusInfo()
* @method void setStatusInfo(string $statusInfo)
*
* @package OCA\DAV\JobStatus\Entity
*/
class JobStatus extends Entity {
protected $uuid;
protected $userId;
protected $statusInfo;
}
47 changes: 47 additions & 0 deletions apps/dav/lib/JobStatus/Entity/JobStatusMapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\DAV\JobStatus\Entity;

use OCP\AppFramework\Db\Mapper;
use OCP\IDBConnection;

class JobStatusMapper extends Mapper {
public function __construct(IDBConnection $db) {
parent::__construct($db, 'dav_job_status');
}

/**
* @param string $userId
* @param string $jobId
* @return JobStatus
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
*/
public function findByUserIdAndJobId($userId, $jobId) {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from($this->getTableName())
->where($query->expr()->eq('uuid', $query->createNamedParameter($jobId)))
->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
return $this->mapRowToEntity($this->findOneQuery($query->getSQL(), $query->getParameters()));
}
}
Loading

0 comments on commit a5c8dd5

Please sign in to comment.