summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/Upload
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2017-06-22 18:36:34 +0200
committerRoeland Jago Douma <roeland@famdouma.nl>2017-07-21 12:49:39 +0200
commit89b747d0669f6e907cc7690abd17d77396c42b80 (patch)
tree13010344b359c279e2962fd501b3c41a2a0b1478 /apps/dav/lib/Upload
parent86d2fe516e5a6e5cc61c55c63d54d40177b75518 (diff)
downloadnextcloud-server-89b747d0669f6e907cc7690abd17d77396c42b80.tar.gz
nextcloud-server-89b747d0669f6e907cc7690abd17d77396c42b80.zip
refactor chunked assembly stream
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'apps/dav/lib/Upload')
-rw-r--r--apps/dav/lib/Upload/AssemblyStream.php88
1 files changed, 32 insertions, 56 deletions
diff --git a/apps/dav/lib/Upload/AssemblyStream.php b/apps/dav/lib/Upload/AssemblyStream.php
index b623f717b31..4b327cecaac 100644
--- a/apps/dav/lib/Upload/AssemblyStream.php
+++ b/apps/dav/lib/Upload/AssemblyStream.php
@@ -20,6 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
namespace OCA\DAV\Upload;
use Sabre\DAV\IFile;
@@ -44,15 +45,15 @@ class AssemblyStream implements \Icewind\Streams\File {
/** @var int */
private $pos = 0;
- /** @var array */
- private $sortedNodes;
-
/** @var int */
- private $size;
+ private $size = 0;
/** @var resource */
private $currentStream = null;
+ /** @var int */
+ private $currentNode = 0;
+
/**
* @param string $path
* @param string $mode
@@ -63,24 +64,18 @@ class AssemblyStream implements \Icewind\Streams\File {
public function stream_open($path, $mode, $options, &$opened_path) {
$this->loadContext('assembly');
- // sort the nodes
$nodes = $this->nodes;
// http://stackoverflow.com/a/10985500
- @usort($nodes, function(IFile $a, IFile $b) {
+ @usort($nodes, function (IFile $a, IFile $b) {
return strnatcmp($a->getName(), $b->getName());
});
- $this->nodes = $nodes;
-
- // build additional information
- $this->sortedNodes = [];
- $start = 0;
- foreach($this->nodes as $node) {
- $size = $node->getSize();
- $name = $node->getName();
- $this->sortedNodes[$name] = ['node' => $node, 'start' => $start, 'end' => $start + $size];
- $start += $size;
- $this->size = $start;
+ $this->nodes = array_values($nodes);
+ if (count($this->nodes) > 0) {
+ $this->currentStream = $this->getStream($this->nodes[0]);
}
+ $this->size = array_reduce($this->nodes, function ($size, IFile $file) {
+ return $size + $file->getSize();
+ }, 0);
return true;
}
@@ -105,36 +100,27 @@ class AssemblyStream implements \Icewind\Streams\File {
* @return string
*/
public function stream_read($count) {
- do {
- if ($this->currentStream === null) {
- list($node, $posInNode) = $this->getNodeForPosition($this->pos);
- if (is_null($node)) {
- // reached last node, no more data
- return '';
- }
- $this->currentStream = $this->getStream($node);
- fseek($this->currentStream, $posInNode);
- }
+ if (is_null($this->currentStream)) {
+ return '';
+ }
+ do {
$data = fread($this->currentStream, $count);
- // isset is faster than strlen
- if (isset($data[$count - 1])) {
- // we read the full count
- $read = $count;
- } else {
- // reaching end of stream, which happens less often so strlen is ok
- $read = strlen($data);
- }
+ $read = strlen($data);
if (feof($this->currentStream)) {
fclose($this->currentStream);
- $this->currentNode = null;
- $this->currentStream = null;
+ $this->currentNode++;
+ if ($this->currentNode < count($this->nodes)) {
+ $this->currentStream = $this->getStream($this->nodes[$this->currentNode]);
+ } else {
+ $this->currentStream = null;
+ }
}
// if no data read, try again with the next node because
// returning empty data can make the caller think there is no more
// data left to read
- } while ($read === 0);
+ } while ($read === 0 && !is_null($this->currentStream));
// update position
$this->pos += $read;
@@ -235,9 +221,10 @@ class AssemblyStream implements \Icewind\Streams\File {
public static function wrap(array $nodes) {
$context = stream_context_create([
'assembly' => [
- 'nodes' => $nodes]
+ 'nodes' => $nodes
+ ]
]);
- stream_wrapper_register('assembly', '\OCA\DAV\Upload\AssemblyStream');
+ stream_wrapper_register('assembly', self::class);
try {
$wrapped = fopen('assembly://', 'r', null, $context);
} catch (\BadMethodCallException $e) {
@@ -249,19 +236,6 @@ class AssemblyStream implements \Icewind\Streams\File {
}
/**
- * @param $pos
- * @return IFile | null
- */
- private function getNodeForPosition($pos) {
- foreach($this->sortedNodes as $node) {
- if ($pos >= $node['start'] && $pos < $node['end']) {
- return [$node['node'], $pos - $node['start']];
- }
- }
- return null;
- }
-
- /**
* @param IFile $node
* @return resource
*/
@@ -269,9 +243,11 @@ class AssemblyStream implements \Icewind\Streams\File {
$data = $node->get();
if (is_resource($data)) {
return $data;
+ } else {
+ $tmp = fopen('php://temp', 'w+');
+ fwrite($tmp, $data);
+ rewind($tmp);
+ return $tmp;
}
-
- return fopen('data://text/plain,' . $data,'r');
}
-
}