X-Git-Url: https://git.llucax.com/software/pymin.git/blobdiff_plain/4de8ac8cb2dc9d60d6e80687e0b41dac2ba95001..1017502ba4bfa740fd73812f11feea2e3476e71d:/pymin/procman.py?ds=sidebyside diff --git a/pymin/procman.py b/pymin/procman.py index adfa792..554fdba 100644 --- a/pymin/procman.py +++ b/pymin/procman.py @@ -6,13 +6,13 @@ import signal import subprocess import logging ; log = logging.getLogger('pymin.procman') -__all__ = ('ProcessManager', 'manager', 'register', 'unregister', 'call', +__all__ = ('ProcessManager', 'manager', 'register', 'unregister', 'once', 'start', 'stop', 'restart', 'kill', 'get', 'has', 'sigchild_handler') class ProcessInfo: def __init__(self, name, command, callback=None, persist=False, max_errors=3, args=None, kwargs=None): - self.name = name + self._name = name self.command = command self.callback = callback if args is None: args = list() @@ -23,9 +23,9 @@ class ProcessInfo: self.max_errors = max_errors self.clear() def clear(self): - self.dont_run = False - self.signal = None - self.process = None + self._dont_run = False + self._signal = None + self._process = None self.error_count = 0 def start(self): assert self.process is None @@ -33,11 +33,12 @@ class ProcessInfo: def restart(self): self.clear() log.debug(u'ProcessInfo.restart(): executing %s', self.command) - self.process = subprocess.Popen(self.command, *self.args, **self.kwargs) + self._process = subprocess.Popen(self.command, + *self.args, **self.kwargs) def stop(self): assert self.process is not None - self.dont_run = True - if self.signal == signal.SIGTERM or self.signal == signal.SIGKILL: + self._dont_run = True + if self._signal == signal.SIGTERM or self._signal == signal.SIGKILL: # Allready stopped, kill it self.kill(signal.SIGKILL) else: @@ -48,10 +49,16 @@ class ProcessInfo: self.process.pid, signum) assert self.process is not None os.kill(self.process.pid, signum) - self.signal = signum + self._signal = signum @property def running(self): return self.process is not None and self.process.poll() is None + @property + def name(self): + return self._name + @property + def process(self): + return self._process def __repr__(self): pid = None if self.process is not None: @@ -72,6 +79,7 @@ class ProcessManager: max_errors=3, *args, **kwargs): log.debug(u'ProcessManager.register(%s, %s, %s, %s, %s, %s, %s)', name, command, callback, persist, max_errors, args, kwargs) + assert not self.has(name) self.services[name] = ProcessInfo(name, command, callback, persist, max_errors, args, kwargs) @@ -83,10 +91,11 @@ class ProcessManager: pi.start() self.namemap[pi.name] = self.pidmap[pi.process.pid] = pi - def call(self, name, command, callback=None, persist=False, + def once(self, name, command, callback=None, persist=False, max_errors=3, *args, **kwargs): - log.debug(u'ProcessManager.call(%s, %s, %s, %s, %s, %s, %s)', + log.debug(u'ProcessManager.once(%s, %s, %s, %s, %s, %s, %s)', name, command, callback, persist, max_errors, args, kwargs) + assert not self.has(name) pi = ProcessInfo(name, command, callback, persist, max_errors, args, kwargs) self._call(pi) @@ -104,7 +113,7 @@ class ProcessManager: def restart(self, name): log.debug(u'ProcessManager.restart(%s)', name) # we have to check first in namemap in case is an unregistered - # process (added with call()) + # process (added with once()) if name in self.namemap: pi = self.namemap[name] pi.stop() @@ -138,10 +147,10 @@ class ProcessManager: log.debug(u'ProcessManager.sigchild_handler: ' u'calling %s(%s)', p.callback.__name__, p) p.callback(self, p) - if p.dont_run or not p.persist or p.error_count >= p.max_errors: + if p._dont_run or not p.persist or p.error_count >= p.max_errors: log.debug(u"ProcessManager.sigchild_handler: can't " u'persist, dont_run=%s, persist=%s, error_cout=%s, ' - u'max_errors=%s', p.dont_run, p.persist, + u'max_errors=%s', p._dont_run, p.persist, p.error_count, p.max_errors) del self.namemap[p.name] del self.pidmap[pid] @@ -176,6 +185,8 @@ class ProcessManager: if name in self.pidmap: return self.pidmap[name] raise KeyError, name + # Syntax sugar for self[name] + __getitem__ = get def has(self, name): if isinstance(name, basestring): # is a name @@ -187,12 +198,8 @@ class ProcessManager: if name in self.pidmap: return True return False - - def __getitem__(self, name): - return self.get(name) - - def __contains__(self, name): - return self.has(name) + # Syntax sugar for name in self + __contains__ = has if __name__ == '__main__': @@ -207,7 +214,7 @@ if __name__ == '__main__': manager = ProcessManager() register = manager.register unregister = manager.unregister -call = manager.call +once = manager.once start = manager.start stop = manager.stop restart = manager.restart @@ -248,6 +255,9 @@ if __name__ == '__main__': assert 'test-service' in manager.services assert 'test-service' not in manager.namemap assert not get('test-service').running + assert manager['test-service'] == get('test-service') + assert has('test-service') + assert 'test-service' in manager register('test-service-2', ('sleep', '3'), notify, False) assert 'test-service-2' in manager.services @@ -256,7 +266,7 @@ if __name__ == '__main__': signal.signal(signal.SIGCHLD, SIGCHLD_handler) - call('test-once', ('sleep', '5'), notify) + once('test-once', ('sleep', '5'), notify) assert 'test-once' not in manager.services assert 'test-once' in manager.namemap assert get('test-once').running @@ -281,7 +291,7 @@ if __name__ == '__main__': assert 'test-once' not in manager.services assert 'test-once' not in manager.namemap - call('test-wait', ('sleep', '2')) + once('test-wait', ('sleep', '2')) print 'test-wait returned?', get('test-wait').process.poll() assert get('test-wait').running print 'Waiting test-wait to return...'