diff --git a/README.md b/README.md index 8e06000..a2270ba 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Configuration files must respect a structure similar to Windows INI file, with The sample configuration (`config.sample`) looks like this: -``` +```ini [base] ; A Storm database URI. See the 'schema' folder for schema creation scripts ; Default: sqlite:///tmp/supysonic/supysonic.db @@ -107,6 +107,11 @@ log_level = WARNING ;mount_webui = on [daemon] +; Delay before triggering scanning operation after a change have been detected +; This prevents running too many scans when multiple changes are detected for a +; single file over a short time span. Default: 5 +wait_delay = 5 + ; Optional rotating log file for the scanner daemon log_file = /var/supysonic/supysonic-daemon.log log_level = INFO diff --git a/config.sample b/config.sample index aa03851..f584c9f 100644 --- a/config.sample +++ b/config.sample @@ -25,6 +25,11 @@ log_level = WARNING ;mount_webui = on [daemon] +; Delay before triggering scanning operation after a change have been detected +; This prevents running too many scans when multiple changes are detected for a +; single file over a short time span. Default: 5 +wait_delay = 5 + ; Optional rotating log file for the scanner daemon log_file = /var/supysonic/supysonic-daemon.log log_level = INFO diff --git a/supysonic/config.py b/supysonic/config.py index 2f0a97a..a40fefc 100644 --- a/supysonic/config.py +++ b/supysonic/config.py @@ -32,6 +32,7 @@ class DefaultConfig(object): 'mount_api': True } DAEMON = { + 'wait_delay': 5, 'log_file': None, 'log_level': 'WARNING' } @@ -68,12 +69,15 @@ class IniConfig(DefaultConfig): try: return int(value) except ValueError: - lv = value.lower() - if lv in ('yes', 'true', 'on'): - return True - elif lv in ('no', 'false', 'off'): - return False - return value + try: + return float(value) + except ValueError: + lv = value.lower() + if lv in ('yes', 'true', 'on'): + return True + elif lv in ('no', 'false', 'off'): + return False + return value @classmethod def from_common_locations(cls): diff --git a/supysonic/watcher.py b/supysonic/watcher.py index 2b5fda7..b24aa35 100644 --- a/supysonic/watcher.py +++ b/supysonic/watcher.py @@ -108,10 +108,11 @@ class Event(object): return self.__src class ScannerProcessingQueue(Thread): - def __init__(self, database_uri, logger): + def __init__(self, database_uri, delay, logger): super(ScannerProcessingQueue, self).__init__() self.__logger = logger + self.__timeout = delay self.__database_uri = database_uri self.__cond = Condition() self.__timer = None @@ -123,6 +124,7 @@ class ScannerProcessingQueue(Thread): self.__run() except Exception, e: self.__logger.critical(e) + raise e def __run(self): while self.__running: @@ -181,7 +183,7 @@ class ScannerProcessingQueue(Thread): if self.__timer: self.__timer.cancel() - self.__timer = Timer(5, self.__wakeup) + self.__timer = Timer(self.__timeout, self.__wakeup) self.__timer.start() def __wakeup(self): @@ -195,7 +197,7 @@ class ScannerProcessingQueue(Thread): return None next = min(self.__queue.iteritems(), key = lambda i: i[1].time) - if not self.__running or next[1].time + 5 <= time.time(): + if not self.__running or next[1].time + self.__timeout <= time.time(): del self.__queue[next[0]] return next[1] @@ -204,6 +206,7 @@ class ScannerProcessingQueue(Thread): class SupysonicWatcher(object): def __init__(self, config): self.__config = config + self.__running = True def run(self): logger = logging.getLogger(__name__) @@ -231,19 +234,21 @@ class SupysonicWatcher(object): store.close() return - queue = ScannerProcessingQueue(self.__config.BASE['database_uri'], logger) + queue = ScannerProcessingQueue(self.__config.BASE['database_uri'], self.__config.DAEMON['wait_delay'], logger) handler = SupysonicWatcherEventHandler(self.__config.BASE['scanner_extensions'], queue, logger) observer = Observer() for folder in folders: logger.info("Starting watcher for %s", folder.path) observer.schedule(handler, folder.path, recursive = True) - store.close() - signal(SIGTERM, self.__terminate) - signal(SIGINT, self.__terminate) - self.__running = True + try: + signal(SIGTERM, self.__terminate) + signal(SIGINT, self.__terminate) + except: + logger.warning('Unable to set signal handlers') + queue.start() observer.start() while self.__running: