From fd2469ad9b744ae4f7dd51aa9d2bf7112a503687 Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Thu, 17 Mar 2016 17:27:28 -0400 Subject: [PATCH 01/10] enable loading asynchronously instead of always blocking on exiftool --- lib/mini_exiftool.rb | 32 ++++++++++++++++++++++++++++++-- test/test_async.rb | 17 +++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 test/test_async.rb diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index ddcac9c..7b17ab5 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -116,6 +116,11 @@ def initialize_from_json json # :nodoc: # Load the tags of filename. def load filename + start_load filename + finish_load + end + + def start_load filename MiniExiftool.setup unless filename && File.exist?(filename) raise MiniExiftool::Error.new("File '#{filename}' does not exist.") @@ -131,7 +136,12 @@ def load filename params << (@opts[:composite] ? '' : '-e ') params << (@opts[:coord_format] ? "-c \"#{@opts[:coord_format]}\"" : '') params << generate_encoding_params - if run(cmd_gen(params, @filename)) + + start_cmd(cmd_gen(params, @filename)) + end + + def finish_load + if finish_cmd parse_output else raise MiniExiftool::Error.new(@error_text) @@ -371,11 +381,29 @@ def cmd_gen arg_str='', filename end def run cmd + start_cmd cmd + finish_cmd + end + + def start_cmd cmd if $DEBUG $stderr.puts cmd end - @output = `#{cmd} 2>#{@@error_file.path}` + + @pipe, w = IO.pipe + @pid = Process.spawn("#{cmd} 2>#{@@error_file.path}", :out=>w) + w.close # used in child process but not here + end + + def finish_cmd + @output = @pipe.read + @pipe.close + @pipe = nil + + Process.wait @pid @status = $? + @pid = nil + unless @status.exitstatus == 0 @error_text = File.readlines(@@error_file.path).join @error_text.force_encoding('UTF-8') diff --git a/test/test_async.rb b/test/test_async.rb new file mode 100644 index 0000000..049b481 --- /dev/null +++ b/test/test_async.rb @@ -0,0 +1,17 @@ +# -- encoding: utf-8 -- +require 'helpers_for_test' + +class TestAsync < TestCase + + def setup + @data_dir = File.dirname(__FILE__) + '/data' + @filename_test = @data_dir + '/test.jpg' + @mini_exiftool = MiniExiftool.new + end + + def test_load_async + @mini_exiftool.start_load @filename_test + @mini_exiftool.finish_load + assert_equal 'DYNAX 7D', @mini_exiftool['Model'] + end +end From 83862b907d9fda0bb3dc79bebec830f8cb1afa0f Mon Sep 17 00:00:00 2001 From: Ben Cherry Date: Tue, 18 Oct 2016 15:49:00 -0700 Subject: [PATCH 02/10] use posix-spawn for miniexiftool --- Gemfile | 2 ++ lib/mini_exiftool.rb | 16 ++++++++++++---- test/test_class_methods.rb | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index fa75df1..dcc6f6d 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ source 'https://rubygems.org' gemspec + +gem 'posix-spawn' \ No newline at end of file diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index ca4980f..98c9757 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -15,13 +15,14 @@ require 'fileutils' require 'json' -require 'open3' require 'pstore' require 'rational' require 'rbconfig' require 'set' require 'tempfile' require 'time' +require 'posix/spawn' +require 'open3' # Simple OO access to the ExifTool command-line application. class MiniExiftool @@ -390,7 +391,10 @@ def run cmd if $DEBUG $stderr.puts cmd end - status = Open3.popen3(cmd) do |inp, out, err, thr| + + puts cmd.inspect + begin + pid, inp, out, err = POSIX::Spawn.popen4(cmd) if @io begin IO.copy_stream @io, inp @@ -403,11 +407,15 @@ def run cmd end @output = out.read @error_text = err.read - thr.value.exitstatus + ensure + [inp, out, err].each { |io| io.close if !io.closed? } + Process::waitpid(pid) end - status == 0 + + $?.exitstatus == 0 end + def convert_before_save val case val when Time diff --git a/test/test_class_methods.rb b/test/test_class_methods.rb index bd694ce..afe2c78 100644 --- a/test/test_class_methods.rb +++ b/test/test_class_methods.rb @@ -12,7 +12,7 @@ def test_new MiniExiftool.new nil end assert_raises MiniExiftool::Error do - MiniExiftool.new false + MiniExiftool.new false end assert_raises MiniExiftool::Error do MiniExiftool.new '' @@ -36,7 +36,7 @@ def test_command MiniExiftool.command = 'non_existend' assert_equal 'non_existend', MiniExiftool.command assert_raises MiniExiftool::Error do - met = MiniExiftool.new(File.join(File.dirname(__FILE__), + met = MiniExiftool.new(File.join(File.dirname(__FILE__), 'data/test.jpg')) end MiniExiftool.command = cmd From 32a76db900532f9e9926c4d66ab8cd03d501eafa Mon Sep 17 00:00:00 2001 From: Ben Cherry Date: Tue, 18 Oct 2016 15:51:51 -0700 Subject: [PATCH 03/10] d --- mini_exiftool.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/mini_exiftool.gemspec b/mini_exiftool.gemspec index 321c926..432e50f 100644 --- a/mini_exiftool.gemspec +++ b/mini_exiftool.gemspec @@ -30,6 +30,7 @@ Gem::Specification.new do |s| s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) + s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, ["~> 2.9"]) s.add_dependency(%q.freeze, [">= 0"]) From 67302cfc6b60e672e2b926871a4458e4500d3546 Mon Sep 17 00:00:00 2001 From: Ben Cherry Date: Tue, 18 Oct 2016 15:52:20 -0700 Subject: [PATCH 04/10] d --- mini_exiftool.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mini_exiftool.gemspec b/mini_exiftool.gemspec index 432e50f..8bd2279 100644 --- a/mini_exiftool.gemspec +++ b/mini_exiftool.gemspec @@ -36,11 +36,13 @@ Gem::Specification.new do |s| s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) + s.add_development_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, ["~> 2.9"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) + s.add_development_dependency(%q.freeze, [">= 0"]) end end From 50b05eb00e929526c84b757966d1675c1e6509fc Mon Sep 17 00:00:00 2001 From: Ben Cherry Date: Tue, 18 Oct 2016 16:03:23 -0700 Subject: [PATCH 05/10] remove puts --- lib/mini_exiftool.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index 98c9757..630942e 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -392,7 +392,6 @@ def run cmd $stderr.puts cmd end - puts cmd.inspect begin pid, inp, out, err = POSIX::Spawn.popen4(cmd) if @io From 2f864d9826d5bae659d24e2d4a8b8f3d8fdd64e4 Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Tue, 18 Oct 2016 21:03:39 -0400 Subject: [PATCH 06/10] cleanup --- lib/mini_exiftool.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index 03b4e14..241bb8a 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -129,7 +129,7 @@ def initialize_from_json json # :nodoc: self end - # Load the tags of filename. + # Load the tags of filename or io. def load filename_or_io start_load filename_or_io finish_load @@ -427,19 +427,19 @@ def finish_cmd @status = $? @pid = nil - unless @status.exitstatus == 0 + if @status.exitstatus == 0 + @error_text = '' + true + else @error_text = @err.read @error_text.force_encoding('UTF-8') false - else - @error_text = '' - true end ensure @out.close unless @out.closed? @out = nil @err.close unless @err.closed? - @out = nil + @err = nil end def convert_before_save val From ee7db87923d8a5ec9d90449d2477488c5d690227 Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Wed, 19 Oct 2016 12:50:48 -0400 Subject: [PATCH 07/10] use waitpid to be more similar --- lib/mini_exiftool.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index 241bb8a..e104fb8 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -423,7 +423,7 @@ def start_cmd cmd def finish_cmd @output = @out.read - Process.wait @pid + Process::waitpid(@pid) @status = $? @pid = nil From 354af47d2265b5b889b3161a7a3bed480b98ba5c Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Wed, 19 Oct 2016 13:02:24 -0400 Subject: [PATCH 08/10] even more similar to ben and posix_spawn examples --- lib/mini_exiftool.rb | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index e104fb8..69745cb 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -421,25 +421,20 @@ def start_cmd cmd end def finish_cmd - @output = @out.read - - Process::waitpid(@pid) - @status = $? - @pid = nil - - if @status.exitstatus == 0 - @error_text = '' - true - else + begin + @output = @out.read @error_text = @err.read @error_text.force_encoding('UTF-8') - false + ensure + @out.close unless @out.closed? + @out = nil + @err.close unless @err.closed? + @err = nil + Process::waitpid(@pid) + @pid = nil end - ensure - @out.close unless @out.closed? - @out = nil - @err.close unless @err.closed? - @err = nil + + $?.exitstatus == 0 end def convert_before_save val From 306a00ef42b69d16ea971757b4af41881be5b7f2 Mon Sep 17 00:00:00 2001 From: Ben Cherry Date: Wed, 19 Oct 2016 11:07:05 -0700 Subject: [PATCH 09/10] async --- lib/mini_exiftool.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index 69745cb..0f82a8c 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -35,7 +35,7 @@ class MiniExiftool # Hash of the standard options used when call MiniExiftool.new @@opts = { :numerical => false, :composite => true, :fast => false, :fast2 => false, :ignore_minor_errors => false, :replace_invalid_chars => false, - :timestamps => Time } + :timestamps => Time, :async => false } # Encoding of the filesystem (filenames in command line) @@fs_enc = Encoding.find('filesystem') @@ -113,7 +113,13 @@ def initialize filename_or_io=nil, opts={} @values = TagHash.new @changed_values = TagHash.new @errors = TagHash.new - load filename_or_io unless filename_or_io.nil? + unless filename_or_io.nil? + if opts[:async] + start_load filename_or_io + else + load filename_or_io + end + end end def initialize_from_hash hash # :nodoc: From 8e4484b568df7e58dea7f2a3516432e5542372dc Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Wed, 30 Nov 2016 17:22:49 -0500 Subject: [PATCH 10/10] include stdout in error since it includes actual error message --- lib/mini_exiftool.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mini_exiftool.rb b/lib/mini_exiftool.rb index 0f82a8c..28f26dc 100644 --- a/lib/mini_exiftool.rb +++ b/lib/mini_exiftool.rb @@ -173,7 +173,7 @@ def finish_load if finish_cmd parse_output else - raise MiniExiftool::Error.new(@error_text) + raise MiniExiftool::Error.new("stderr: #{@error_text} stdout: #{@output}") end self end