Pipe improvements, misc cleanup

* Pipe improvements; better filter code, pipeline etc.
* Moved commands in PDO plugin to dedicated namespace
This commit is contained in:
2021-12-23 15:31:26 +01:00
parent 9050c74a08
commit f4257b39e4
11 changed files with 254 additions and 15 deletions

View File

@ -0,0 +1,10 @@
<?php
namespace Spark\Pipe\Filters;
interface FilterInterface
{
public function setArguments(array $args);
public function pipe(?string $chunk);
}

View File

@ -0,0 +1,32 @@
<?php
namespace Spark\Pipe\Filters;
class PhpFilter implements FilterInterface
{
private $method;
private array $args = [];
private static $defaultArgs = [
];
public function __construct(string|callable $method)
{
$this->method = $method;
}
public function setArguments(array $args)
{
$this->args = array_merge(self::$defaultArgs, $args);
}
public function pipe(?string $chunk)
{
if ($chunk === null) {
return;
}
return call_user_func($this->method, $chunk);
}
}

View File

@ -0,0 +1,98 @@
<?php
namespace Spark\Pipe\Filters;
class ProgressFilter implements FilterInterface
{
private array $args = [];
private static $defaultArgs = [
'max' => null,
];
private ?int $max = null;
private int $current = 0;
private int $lastCurrent = 0;
private ?int $nextRefresh = null;
private array $deltas = [];
private array $times = [];
public function setArguments(array $args)
{
$this->args = array_merge(self::$defaultArgs, $args);
$max = $this->args['max'];
if (str_starts_with($max, '@')) {
$this->max = filesize(substr($max,1));
} else {
$this->max = $max;
}
}
public function pipe(?string $chunk)
{
if ($chunk === null) {
$this->nextRefresh = 0;
$this->refresh();
fwrite(STDERR, "\n");
return;
}
$this->current += strlen($chunk);
$this->refresh();
return $chunk;
}
private function refresh()
{
if (microtime(true) < $this->nextRefresh) {
return;
}
$now = microtime(true);
$delta = $this->current - $this->lastCurrent;
array_push($this->deltas, $delta);
array_push($this->times, $now);
while (count($this->deltas) > 10) {
array_shift($this->deltas);
array_shift($this->times);
}
$deltaTime = end($this->times) - reset($this->times);
if ($deltaTime > 0) {
$rate = array_sum($this->deltas) / $deltaTime;
$rateu = "b/s";
if ($rate > 1024) {
$rate /= 1024;
$rateu = "KiB/s";
if ($rate > 1024) {
$rate /= 1024;
$rateu = "MiB/s";
if ($rate > 1024) {
$rate /= 1024;
$rateu = "GiB/s";
}
}
}
} else {
$rate = null;
}
if ($this->max) {
fprintf(STDERR, "\r%.1fMiB/%.1fMiB (%.1f%%) ", $this->current/1024/1024, $this->max/1024/1024, 100/$this->max*$this->current);
} else {
fprintf(STDERR, "\r%.1fMiB ", $this->current/1024/1024);
}
if ($rate) {
fprintf(STDERR, "(%.1f%s)", $rate, $rateu);
}
fprintf(STDERR, "\e[K");
$this->lastCurrent = $this->current;
$this->nextRefresh = $now + .1;
}
}

55
src/Pipe/Pipeline.php Normal file
View File

@ -0,0 +1,55 @@
<?php
namespace Spark\Pipe;
use Spark\Pipe\Filters\FilterInterface;
class Pipeline
{
private $fdin;
private $fdout;
private array $filters = [];
public function setInputFile(string $filename)
{
if (ctype_digit($filename) && !file_exists($filename)) {
$filename = "php://fd/" . $filename;
}
$this->fdin = fopen($filename, 'rb');
}
public function setOutputFile(string $filename)
{
if (ctype_digit($filename) && !file_exists($filename)) {
$filename = "php://fd/" . $filename;
}
$this->fdout = fopen($filename, 'wb');
}
public function addFilter(FilterInterface $filter)
{
$this->filters[] = $filter;
}
public function run()
{
while (!feof($this->fdin)) {
ob_start();
$buf = fread($this->fdin, 8192);
foreach ($this->filters as $filter) {
$buf = $filter->pipe($buf);
}
ob_end_clean();
fwrite($this->fdout, $buf);
}
ob_start();
foreach ($this->filters as $filter) {
$filter->pipe(null);
}
ob_end_clean();
}
}