2016-12-30 03:59:59 +01:00
|
|
|
<?php
|
2016-08-30 21:05:14 +02:00
|
|
|
|
|
|
|
namespace Amp\File;
|
|
|
|
|
2017-06-17 23:41:57 +02:00
|
|
|
use Amp\Coroutine;
|
|
|
|
use Amp\Deferred;
|
2017-05-18 16:33:52 +02:00
|
|
|
use Amp\Parallel\Worker;
|
2017-06-17 23:41:57 +02:00
|
|
|
use Amp\Parallel\Worker\Pool;
|
|
|
|
use Amp\Parallel\Worker\TaskException;
|
|
|
|
use Amp\Parallel\Worker\WorkerException;
|
|
|
|
use Amp\Promise;
|
2016-08-30 21:05:14 +02:00
|
|
|
|
|
|
|
class ParallelDriver implements Driver {
|
|
|
|
/**
|
|
|
|
* @var \Amp\Parallel\Worker\Pool
|
|
|
|
*/
|
|
|
|
private $pool;
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* @param \Amp\Parallel\Worker\Pool|null $pool
|
|
|
|
*/
|
|
|
|
public function __construct(Pool $pool = null) {
|
|
|
|
$this->pool = $pool ?: Worker\pool();
|
|
|
|
if (!$this->pool->isRunning()) {
|
|
|
|
$this->pool->start();
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function open(string $path, string $mode): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
$worker = $this->pool->get();
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
$task = new Internal\FileTask("fopen", [$path, $mode]);
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
$deferred = new Deferred;
|
2016-11-15 06:17:19 +01:00
|
|
|
$promise = $worker->enqueue($task);
|
2017-03-22 00:53:55 +01:00
|
|
|
$promise->onResolve(static function ($exception, array $result = null) use ($worker, $deferred, $path) {
|
2016-08-30 21:05:14 +02:00
|
|
|
if ($exception) {
|
|
|
|
$deferred->fail($exception);
|
|
|
|
return;
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
list($id, $size, $mode) = $result;
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
$deferred->resolve(new ParallelHandle($worker, $id, $path, $size, $mode));
|
|
|
|
});
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-11-15 06:17:19 +01:00
|
|
|
return $deferred->promise();
|
2016-08-30 21:05:14 +02:00
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
private function runFileTask(Internal\FileTask $task): \Generator {
|
|
|
|
try {
|
|
|
|
return yield $this->pool->enqueue($task);
|
|
|
|
} catch (TaskException $exception) {
|
|
|
|
if (\strcasecmp(\substr($exception->getName(), -5), "Error") === 0) {
|
|
|
|
throw new \Error($exception->getMessage());
|
|
|
|
}
|
|
|
|
throw new FilesystemException("The file operation failed", $exception);
|
|
|
|
} catch (WorkerException $exception) {
|
|
|
|
throw new FilesystemException("Could not send the file task to worker", $exception);
|
|
|
|
}
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function unlink(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("unlink", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function stat(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("stat", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function rename(string $from, string $to): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("rename", [$from, $to])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function isfile(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("isfile", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function isdir(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("isdir", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function link(string $target, string $link): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("link", [$target, $link])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function symlink(string $target, string $link): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("symlink", [$target, $link])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function readlink(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("readlink", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2017-01-11 07:05:35 +01:00
|
|
|
public function mkdir(string $path, int $mode = 0644, bool $recursive = false): Promise {
|
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("mkdir", [$path, $mode, $recursive])));
|
2016-08-30 21:05:14 +02:00
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function scandir(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("scandir", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function rmdir(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("rmdir", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function chmod(string $path, int $mode): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("chmod", [$path, $mode])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function chown(string $path, int $uid, int $gid): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("chown", [$path, $uid, $gid])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function exists(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("exists", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function size(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("size", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function mtime(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("mtime", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function atime(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("atime", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function ctime(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("ctime", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function lstat(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("lstat", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function touch(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("touch", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function get(string $path): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("get", [$path])));
|
|
|
|
}
|
2017-01-11 14:22:06 +01:00
|
|
|
|
2016-08-30 21:05:14 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
2016-11-15 06:17:19 +01:00
|
|
|
public function put(string $path, string $contents): Promise {
|
2016-08-30 21:05:14 +02:00
|
|
|
return new Coroutine($this->runFileTask(new Internal\FileTask("put", [$path, $contents])));
|
2017-06-17 23:41:57 +02:00
|
|
|
}
|
|
|
|
}
|