Massively speed up indexing for local files
parent
e9fab264fc
commit
e933c1c457
|
@ -83,12 +83,6 @@ class Index extends Command {
|
||||||
} catch (ContainerExceptionInterface $e) {
|
} catch (ContainerExceptionInterface $e) {
|
||||||
$this->globalService = null;
|
$this->globalService = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refuse to run without exiftool
|
|
||||||
if (!$this->testExif()) {
|
|
||||||
error_log('FATAL: exiftool could not be found or test failed');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Make sure exiftool is available */
|
/** Make sure exiftool is available */
|
||||||
|
@ -115,6 +109,13 @@ class Index extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||||
|
// Refuse to run without exiftool
|
||||||
|
\OCA\Memories\Exif::ensureStaticExiftoolProc();
|
||||||
|
if (!$this->testExif()) {
|
||||||
|
error_log('FATAL: exiftool could not be found or test failed');
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->encryptionManager->isEnabled()) {
|
if ($this->encryptionManager->isEnabled()) {
|
||||||
$output->writeln('Encryption is enabled. Aborted.');
|
$output->writeln('Encryption is enabled. Aborted.');
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -125,6 +126,9 @@ class Index extends Command {
|
||||||
$this->generateUserEntries($user);
|
$this->generateUserEntries($user);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Close the exiftool process
|
||||||
|
\OCA\Memories\Exif::closeStaticExiftoolProc();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
90
lib/Exif.php
90
lib/Exif.php
|
@ -8,6 +8,53 @@ use OCP\Files\File;
|
||||||
use OCP\IConfig;
|
use OCP\IConfig;
|
||||||
|
|
||||||
class Exif {
|
class Exif {
|
||||||
|
/** Opened instance of exiftool when running in command mode */
|
||||||
|
private static $staticProc = null;
|
||||||
|
private static $staticPipes = null;
|
||||||
|
private static $noStaticProc = false;
|
||||||
|
|
||||||
|
/** Initialize static exiftool process for local reads */
|
||||||
|
private static function initializeStaticExiftoolProc() {
|
||||||
|
self::closeStaticExiftoolProc();
|
||||||
|
self::$staticProc = proc_open(['exiftool', '-stay_open', 'true', '-@', '-'], [
|
||||||
|
0 => array('pipe', 'r'),
|
||||||
|
1 => array('pipe', 'w'),
|
||||||
|
2 => array('pipe', 'w'),
|
||||||
|
], self::$staticPipes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function closeStaticExiftoolProc() {
|
||||||
|
try {
|
||||||
|
if (self::$staticProc) {
|
||||||
|
fclose(self::$staticPipes[0]);
|
||||||
|
fclose(self::$staticPipes[1]);
|
||||||
|
fclose(self::$staticPipes[2]);
|
||||||
|
proc_terminate(self::$staticProc);
|
||||||
|
}
|
||||||
|
} catch (\Exception $ex) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function ensureStaticExiftoolProc() {
|
||||||
|
if (self::$noStaticProc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self::$staticProc) {
|
||||||
|
self::initializeStaticExiftoolProc();
|
||||||
|
if (!proc_get_status(self::$staticProc)["running"]) {
|
||||||
|
error_log("Failed to create stay_open exiftool process");
|
||||||
|
self::$noStaticProc = true;
|
||||||
|
self::$staticProc = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!proc_get_status(self::$staticProc)["running"]) {
|
||||||
|
self::$staticProc = null;
|
||||||
|
self::ensureStaticExiftoolProc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the path to the user's configured photos directory.
|
* Get the path to the user's configured photos directory.
|
||||||
* @param IConfig $config
|
* @param IConfig $config
|
||||||
|
@ -47,7 +94,35 @@ class Exif {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get exif data as a JSON object from a local file path */
|
/** Get exif data as a JSON object from a local file path */
|
||||||
public static function getExifFromLocalPath(string $path) {
|
public static function getExifFromLocalPath(string &$path) {
|
||||||
|
self::ensureStaticExiftoolProc();
|
||||||
|
if (!is_null(self::$staticProc)) {
|
||||||
|
return self::getExifFromLocalPathWithStaticProc($path);
|
||||||
|
} else {
|
||||||
|
return self::getExifFromLocalPathWithSeparateProc($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getExifFromLocalPathWithStaticProc(string &$path) {
|
||||||
|
fwrite(self::$staticPipes[0], "$path\n-json\n-execute\n");
|
||||||
|
fflush(self::$staticPipes[0]);
|
||||||
|
|
||||||
|
$buf = "";
|
||||||
|
$readyToken = "\n{ready}\n";
|
||||||
|
while (!str_ends_with($buf, $readyToken)) {
|
||||||
|
$r = fread(self::$staticPipes[1], 1);
|
||||||
|
if ($r === false) {
|
||||||
|
error_log("Something went wrong with static exiftool process");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$buf .= $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
$buf = substr($buf, 0, strrpos($buf, $readyToken));
|
||||||
|
return self::processStdout($buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getExifFromLocalPathWithSeparateProc(string &$path) {
|
||||||
$pipes = [];
|
$pipes = [];
|
||||||
$proc = proc_open(['exiftool', '-json', $path], [
|
$proc = proc_open(['exiftool', '-json', $path], [
|
||||||
1 => array('pipe', 'w'),
|
1 => array('pipe', 'w'),
|
||||||
|
@ -60,12 +135,7 @@ class Exif {
|
||||||
fclose($pipes[2]);
|
fclose($pipes[2]);
|
||||||
proc_close($proc);
|
proc_close($proc);
|
||||||
|
|
||||||
// Parse the json
|
return self::processStdout($stdout);
|
||||||
$json = json_decode($stdout, true);
|
|
||||||
if (!$json) {
|
|
||||||
throw new \Exception('Could not read exif data');
|
|
||||||
}
|
|
||||||
return $json[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,7 +164,11 @@ class Exif {
|
||||||
fclose($pipes[2]);
|
fclose($pipes[2]);
|
||||||
proc_close($proc);
|
proc_close($proc);
|
||||||
|
|
||||||
// Parse the json
|
return self::processStdout($stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get json array from stdout of exiftool */
|
||||||
|
private static function processStdout(string &$stdout) {
|
||||||
$json = json_decode($stdout, true);
|
$json = json_decode($stdout, true);
|
||||||
if (!$json) {
|
if (!$json) {
|
||||||
throw new \Exception('Could not read exif data');
|
throw new \Exception('Could not read exif data');
|
||||||
|
|
Loading…
Reference in New Issue