From 3c6a0543f51138119daf27e8674f24b2fd28b4c9 Mon Sep 17 00:00:00 2001 From: Tobias Sauerwein Date: Wed, 31 Jul 2013 23:52:24 +0200 Subject: [PATCH 1/7] Scanner: Fix deadlock on incorrectly identified files --- mopidy/backends/local/__init__.py | 1 + mopidy/backends/local/ext.conf | 1 + mopidy/scanner.py | 22 ++++++++++++++++++++-- tests/data/scanner/example.log | Bin 0 -> 206 bytes tests/scanner_test.py | 4 ++++ 5 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/data/scanner/example.log diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index f718eeb5..cf982220 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -18,6 +18,7 @@ class Extension(ext.Extension): def get_config_schema(self): schema = super(Extension, self).get_config_schema() + schema['scan_timeout'] = config.Integer(minimum=0) schema['media_dir'] = config.Path() schema['playlists_dir'] = config.Path() schema['tag_cache_file'] = config.Path() diff --git a/mopidy/backends/local/ext.conf b/mopidy/backends/local/ext.conf index 54c3ab78..ae30438f 100644 --- a/mopidy/backends/local/ext.conf +++ b/mopidy/backends/local/ext.conf @@ -1,5 +1,6 @@ [local] enabled = true +scan_timeout = 1000 media_dir = $XDG_MUSIC_DIR playlists_dir = $XDG_DATA_DIR/mopidy/local/playlists tag_cache_file = $XDG_DATA_DIR/mopidy/local/tag_cache diff --git a/mopidy/scanner.py b/mopidy/scanner.py index 9f13d454..cdfdad96 100644 --- a/mopidy/scanner.py +++ b/mopidy/scanner.py @@ -97,9 +97,14 @@ def main(): logging.warning('Failed %s: %s', uri, error) logging.debug('Debug info for %s: %s', uri, debug) + if not config['local']['scan_timeout']: + scan_timeout = 1000 + else: + scan_timeout = config['local']['scan_timeout'] + logging.info('Scanning new and modified tracks.') # TODO: just pass the library in instead? - scanner = Scanner(uris_update, store, debug) + scanner = Scanner(uris_update, store, debug, scan_timeout) try: scanner.start() except KeyboardInterrupt: @@ -176,12 +181,14 @@ def translator(data): class Scanner(object): - def __init__(self, uris, data_callback, error_callback=None): + def __init__(self, uris, data_callback, error_callback=None, scan_timeout=1000): self.data = {} self.uris = iter(uris) self.data_callback = data_callback self.error_callback = error_callback + self.scan_timeout = scan_timeout self.loop = gobject.MainLoop() + self.timeout_id = None self.fakesink = gst.element_factory_make('fakesink') self.fakesink.set_property('signal-handoffs', True) @@ -252,6 +259,13 @@ class Scanner(object): self.error_callback(uri, error, debug) self.next_uri() + def process_timeout(self): + if self.error_callback: + uri = self.uribin.get_property('uri') + self.error_callback(uri, 'Processing timeout after %i seconds' % self.timeout, 'debug') + self.next_uri() + return True + def get_duration(self): self.pipe.get_state() # Block until state change is done. try: @@ -262,6 +276,9 @@ class Scanner(object): def next_uri(self): self.data = {} + if self.timeout_id: + gobject.source_remove(self.timeout_id) + self.timeout_id = None try: uri = next(self.uris) except StopIteration: @@ -269,6 +286,7 @@ class Scanner(object): return False self.pipe.set_state(gst.STATE_NULL) self.uribin.set_property('uri', uri) + self.timeout_id = gobject.timeout_add(self.scan_timeout, self.process_timeout) self.pipe.set_state(gst.STATE_PLAYING) return True diff --git a/tests/data/scanner/example.log b/tests/data/scanner/example.log new file mode 100644 index 0000000000000000000000000000000000000000..c49a044d01813d3ce57031f8fc41fe7e7abb2974 GIT binary patch literal 206 zcmYL@%L>9U5Jk^g@E`mD5z~sGJ1Jedbze1>f{&sV^yk&nbRl7qn_=#`^Zk^(s5sCu zVZ)On4L5b+-SSrL2+WwP_C)6@Rc@WQJ9ANGtehD9wTwriWqN{V%qUeUzi=v=*y$Zo j`?Rawvu`c4QAPiMdSH?0TOIvA12<=?4sNoxvrGv;5;`AM literal 0 HcmV?d00001 diff --git a/tests/scanner_test.py b/tests/scanner_test.py index dcf891c0..903d6510 100644 --- a/tests/scanner_test.py +++ b/tests/scanner_test.py @@ -210,6 +210,10 @@ class ScannerTest(unittest.TestCase): self.scan('scanner/image') self.assert_(self.errors) + def test_log_file_is_ignored(self): + self.scan('scanner/example.log') + self.assert_(self.errors) + @unittest.SkipTest def test_song_without_time_is_handeled(self): pass From dee0d01e20db0be447ce0fa6ef714c11feaaea88 Mon Sep 17 00:00:00 2001 From: Tobias Sauerwein Date: Thu, 1 Aug 2013 09:31:44 +0200 Subject: [PATCH 2/7] Throw an error when scan_timeout config is not loaded. --- mopidy/scanner.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mopidy/scanner.py b/mopidy/scanner.py index cdfdad96..d280785c 100644 --- a/mopidy/scanner.py +++ b/mopidy/scanner.py @@ -98,9 +98,9 @@ def main(): logging.debug('Debug info for %s: %s', uri, debug) if not config['local']['scan_timeout']: - scan_timeout = 1000 - else: - scan_timeout = config['local']['scan_timeout'] + self.error_callback(uri, 'Config value local/scan_timeout is not set.', 'debug') + + scan_timeout = config['local']['scan_timeout'] logging.info('Scanning new and modified tracks.') # TODO: just pass the library in instead? @@ -262,7 +262,7 @@ class Scanner(object): def process_timeout(self): if self.error_callback: uri = self.uribin.get_property('uri') - self.error_callback(uri, 'Processing timeout after %i seconds' % self.timeout, 'debug') + self.error_callback(uri, 'Processing timeout after %i seconds' % self.scan_timeout, 'debug') self.next_uri() return True From 66f367048d2a0e2249ad99eb8194393eebe3fffa Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 5 Aug 2013 23:09:04 +0200 Subject: [PATCH 3/7] docs: Document local/scan_timeout config value --- docs/ext/local.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/ext/local.rst b/docs/ext/local.rst index fc89e69a..1abebb1d 100644 --- a/docs/ext/local.rst +++ b/docs/ext/local.rst @@ -47,6 +47,11 @@ Configuration values Path to tag cache for local media. +.. confval:: local/scan_timeout + + Number of milliseconds before giving up scanning a file and moving on to + the next file. + Usage ===== From a5d8f02454cb938cdca25703c048b137d1011683 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 5 Aug 2013 23:18:07 +0200 Subject: [PATCH 4/7] scanner: Fix local/scan_timeout value check --- mopidy/scanner.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mopidy/scanner.py b/mopidy/scanner.py index d280785c..53ded736 100644 --- a/mopidy/scanner.py +++ b/mopidy/scanner.py @@ -54,6 +54,10 @@ def main(): logging.warning('Config value local/media_dir is not set.') return + if not config['local']['scan_timeout']: + logging.warning('Config value local/scan_timeout is not set.') + return + # TODO: missing config error checking and other default setup code. audio = dummy_audio.DummyAudio() @@ -97,9 +101,6 @@ def main(): logging.warning('Failed %s: %s', uri, error) logging.debug('Debug info for %s: %s', uri, debug) - if not config['local']['scan_timeout']: - self.error_callback(uri, 'Config value local/scan_timeout is not set.', 'debug') - scan_timeout = config['local']['scan_timeout'] logging.info('Scanning new and modified tracks.') From 022bcd089fe9e0a227b3d308371968adf2ace998 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 5 Aug 2013 23:18:37 +0200 Subject: [PATCH 5/7] scanner: Fix unregistering of the timeout callback --- mopidy/scanner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/scanner.py b/mopidy/scanner.py index 53ded736..5aeb2768 100644 --- a/mopidy/scanner.py +++ b/mopidy/scanner.py @@ -265,7 +265,7 @@ class Scanner(object): uri = self.uribin.get_property('uri') self.error_callback(uri, 'Processing timeout after %i seconds' % self.scan_timeout, 'debug') self.next_uri() - return True + return False def get_duration(self): self.pipe.get_state() # Block until state change is done. From e2bec7922011cd78e512db16fb9b893519813ed0 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 5 Aug 2013 23:19:39 +0200 Subject: [PATCH 6/7] scanner: Reorder config values --- mopidy/backends/local/__init__.py | 2 +- mopidy/backends/local/ext.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index cf982220..3e2561a1 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -18,10 +18,10 @@ class Extension(ext.Extension): def get_config_schema(self): schema = super(Extension, self).get_config_schema() - schema['scan_timeout'] = config.Integer(minimum=0) schema['media_dir'] = config.Path() schema['playlists_dir'] = config.Path() schema['tag_cache_file'] = config.Path() + schema['scan_timeout'] = config.Integer(minimum=0) return schema def validate_environment(self): diff --git a/mopidy/backends/local/ext.conf b/mopidy/backends/local/ext.conf index ae30438f..7e0f0f2b 100644 --- a/mopidy/backends/local/ext.conf +++ b/mopidy/backends/local/ext.conf @@ -1,6 +1,6 @@ [local] enabled = true -scan_timeout = 1000 media_dir = $XDG_MUSIC_DIR playlists_dir = $XDG_DATA_DIR/mopidy/local/playlists tag_cache_file = $XDG_DATA_DIR/mopidy/local/tag_cache +scan_timeout = 1000 From f35b45bf579da0721fbe07f0da42870e5c1e28b6 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 5 Aug 2013 23:24:43 +0200 Subject: [PATCH 7/7] scanner: Fix time unit in log message. Formatting --- mopidy/scanner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mopidy/scanner.py b/mopidy/scanner.py index 5aeb2768..669f8182 100644 --- a/mopidy/scanner.py +++ b/mopidy/scanner.py @@ -263,7 +263,8 @@ class Scanner(object): def process_timeout(self): if self.error_callback: uri = self.uribin.get_property('uri') - self.error_callback(uri, 'Processing timeout after %i seconds' % self.scan_timeout, 'debug') + self.error_callback( + uri, 'Scan timed out after %d ms' % self.scan_timeout, None) self.next_uri() return False