Skip to content

Commit a157ba7

Browse files
committed
feat: rework object listing
Signed-off-by: Robin Appelman <[email protected]>
1 parent 18e9980 commit a157ba7

File tree

3 files changed

+42
-38
lines changed

3 files changed

+42
-38
lines changed

apps/files/lib/Command/Object/Info.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use OC\Core\Command\Base;
1212
use OCP\Files\IMimeTypeDetector;
1313
use OCP\Files\ObjectStore\IObjectStoreMetaData;
14+
use OCP\Util;
1415
use Symfony\Component\Console\Input\InputArgument;
1516
use Symfony\Component\Console\Input\InputInterface;
1617
use Symfony\Component\Console\Input\InputOption;
@@ -59,7 +60,7 @@ public function execute(InputInterface $input, OutputInterface $output): int {
5960
}
6061

6162
if ($input->getOption('output') === 'plain' && isset($meta['size'])) {
62-
$meta['size'] = \OC_Helper::humanFileSize($meta['size']);
63+
$meta['size'] = Util::humanFileSize($meta['size']);
6364
}
6465
if (isset($meta['mtime'])) {
6566
$meta['mtime'] = $meta['mtime']->format(\DateTimeImmutable::ATOM);

apps/files/lib/Command/Object/ObjectUtil.php

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OCP\Files\ObjectStore\IObjectStore;
1414
use OCP\IConfig;
1515
use OCP\IDBConnection;
16+
use OCP\Util;
1617
use Symfony\Component\Console\Input\InputInterface;
1718
use Symfony\Component\Console\Output\OutputInterface;
1819

@@ -97,32 +98,28 @@ public function objectExistsInDb(string $object): int|false {
9798
public function writeIteratorToOutput(InputInterface $input, OutputInterface $output, \Iterator $objects, int $chunkSize): void {
9899
$outputType = $input->getOption('output');
99100
$humanOutput = $outputType === Base::OUTPUT_FORMAT_PLAIN;
100-
$first = true;
101101

102-
if (!$humanOutput) {
103-
$output->writeln('[');
104-
}
102+
if ($humanOutput) {
103+
// we can't write tables in a streaming way, so we print them in chunks instead
104+
foreach ($this->chunkIterator($objects, $chunkSize) as $chunk) {
105+
$this->outputChunkHuman($input, $output, $chunk);
106+
}
107+
} else {
108+
$first = true;
105109

106-
foreach ($this->chunkIterator($objects, $chunkSize) as $chunk) {
107-
if ($outputType === Base::OUTPUT_FORMAT_PLAIN) {
108-
$this->outputChunk($input, $output, $chunk);
109-
} else {
110-
foreach ($chunk as $object) {
111-
if (!$first) {
112-
$output->writeln(',');
113-
}
114-
$row = $this->formatObject($object, $humanOutput);
115-
if ($outputType === Base::OUTPUT_FORMAT_JSON_PRETTY) {
116-
$output->write(json_encode($row, JSON_PRETTY_PRINT));
117-
} else {
118-
$output->write(json_encode($row));
119-
}
120-
$first = false;
110+
$output->writeln('[');
111+
foreach ($objects as $object) {
112+
if (!$first) {
113+
$output->writeln(',');
121114
}
115+
$row = $this->formatObject($object, false);
116+
if ($outputType === self::OUTPUT_FORMAT_JSON_PRETTY) {
117+
$output->write(json_encode($row, JSON_PRETTY_PRINT));
118+
} else {
119+
$output->write(json_encode($row));
120+
}
121+
$first = false;
122122
}
123-
}
124-
125-
if (!$humanOutput) {
126123
$output->writeln("\n]");
127124
}
128125
}
@@ -133,20 +130,18 @@ private function formatObject(array $object, bool $humanOutput): array {
133130
], ($object['metadata'] ?? []));
134131

135132
if ($humanOutput && isset($row['size'])) {
136-
$row['size'] = \OC_Helper::humanFileSize($row['size']);
133+
$row['size'] = Util::humanFileSize($row['size']);
137134
}
138135
if (isset($row['mtime'])) {
139136
$row['mtime'] = $row['mtime']->format(\DateTimeImmutable::ATOM);
140137
}
141138
return $row;
142139
}
143140

144-
private function outputChunk(InputInterface $input, OutputInterface $output, iterable $chunk): void {
141+
private function outputChunkHuman(InputInterface $input, OutputInterface $output, iterable $chunk): void {
145142
$result = [];
146-
$humanOutput = $input->getOption('output') === 'plain';
147-
148143
foreach ($chunk as $object) {
149-
$result[] = $this->formatObject($object, $humanOutput);
144+
$result[] = $this->formatObject($object, true);
150145
}
151146
$this->writeTableInOutputFormat($input, $output, $result);
152147
}
@@ -158,12 +153,14 @@ public function chunkIterator(\Iterator $iterator, int $count): \Iterator {
158153
$chunk[] = $iterator->current();
159154
$iterator->next();
160155
if (count($chunk) == $count) {
156+
// Got a full chunk, yield and start a new one
161157
yield $chunk;
162158
$chunk = [];
163159
}
164160
}
165161

166162
if (count($chunk)) {
163+
// Yield the last chunk even if incomplete
167164
yield $chunk;
168165
}
169166
}

apps/files/lib/Command/Object/Orphans.php

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,23 @@
1919
class Orphans extends Base {
2020
private const CHUNK_SIZE = 100;
2121

22-
private IQueryBuilder $query;
22+
private ?IQueryBuilder $query = null;
2323

2424
public function __construct(
2525
private readonly ObjectUtil $objectUtils,
26-
IDBConnection $connection,
26+
private readonly IDBConnection $connection,
2727
) {
2828
parent::__construct();
29+
}
2930

30-
$this->query = $connection->getQueryBuilder();
31-
$this->query->select('fileid')
32-
->from('filecache')
33-
->where($this->query->expr()->eq('fileid', $this->query->createParameter('file_id')));
31+
private function getQuery(): IQueryBuilder {
32+
if (!$this->query) {
33+
$this->query = $this->connection->getQueryBuilder();
34+
$this->query->select('fileid')
35+
->from('filecache')
36+
->where($this->query->expr()->eq('fileid', $this->query->createParameter('file_id')));
37+
}
38+
return $this->query;
3439
}
3540

3641
protected function configure(): void {
@@ -54,20 +59,21 @@ public function execute(InputInterface $input, OutputInterface $output): int {
5459
$prefixLength = strlen('urn:oid:');
5560

5661
$objects = $objectStore->listObjects('urn:oid:');
57-
$objects->rewind();
5862
$orphans = new \CallbackFilterIterator($objects, function (array $object) use ($prefixLength) {
5963
$fileId = (int)substr($object['urn'], $prefixLength);
6064
return !$this->fileIdInDb($fileId);
6165
});
62-
$orphans = new \ArrayIterator(iterator_to_array($orphans));
66+
$orphans->rewind();
67+
6368
$this->objectUtils->writeIteratorToOutput($input, $output, $orphans, self::CHUNK_SIZE);
6469

6570
return self::SUCCESS;
6671
}
6772

6873
private function fileIdInDb(int $fileId): bool {
69-
$this->query->setParameter('file_id', $fileId, IQueryBuilder::PARAM_INT);
70-
$result = $this->query->executeQuery();
74+
$query = $this->getQuery();
75+
$query->setParameter('file_id', $fileId, IQueryBuilder::PARAM_INT);
76+
$result = $query->executeQuery();
7177
return $result->fetchOne() !== false;
7278
}
7379
}

0 commit comments

Comments
 (0)