Pipe improvements, misc cleanup
* Pipe improvements; better filter code, pipeline etc. * Moved commands in PDO plugin to dedicated namespace
This commit is contained in:
10
src/Pipe/Filters/FilterInterface.php
Normal file
10
src/Pipe/Filters/FilterInterface.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Spark\Pipe\Filters;
|
||||
|
||||
interface FilterInterface
|
||||
{
|
||||
public function setArguments(array $args);
|
||||
|
||||
public function pipe(?string $chunk);
|
||||
}
|
32
src/Pipe/Filters/PhpFilter.php
Normal file
32
src/Pipe/Filters/PhpFilter.php
Normal 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);
|
||||
}
|
||||
|
||||
}
|
98
src/Pipe/Filters/ProgressFilter.php
Normal file
98
src/Pipe/Filters/ProgressFilter.php
Normal 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
55
src/Pipe/Pipeline.php
Normal 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();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user