Merge branch 'master' of ralfj.de:saartuer
[saartuer.git] / libtuer.py
1 import logging, logging.handlers, os, time, queue, threading, subprocess
2
3 # logging function
4 class Logger:
5         def __init__ (self):
6                 self.logger = logging.getLogger("tuerd")
7                 self.logger.setLevel(logging.INFO)
8                 self.handler = logging.handlers.SysLogHandler(address = '/dev/log', facility = logging.handlers.SysLogHandler.LOG_LOCAL0)
9                 self.logger.addHandler(self.handler)
10         
11         def log (self, lvl, what):
12                 thestr = "%s[%d]: %s" % ("osspd", os.getpid(), what)
13                 print (thestr)
14                 self.logger.log(lvl, thestr)
15         
16         def debug(self, what):
17                 self.log(logging.DEBUG, what)
18         def info(self, what):
19                 self.log(logging.INFO, what)
20         def warning(self, what):
21                 self.log(logging.WARNING, what)
22         def error(self, what):
23                 self.log(logging.ERROR, what)
24         def critical(self, what):
25                 self.log(logging.CRITICAL, what)
26
27 logger = Logger()
28
29 # run a command asynchronously and log the return value if not 0
30 # prefix must be a string identifying the code position where the call came from
31 def fire_and_forget (cmd, log, prefix):
32         def _fire_and_forget ():
33                 with open("/dev/null", "w") as fnull:
34                         retcode = subprocess.call(cmd, stdout=fnull, stderr=fnull)
35                         if retcode is not 0:
36                                 log("%sReturn code %d at command: %s" % (prefix,retcode,str(cmd)))
37         t = threading.Thread(target=_fire_and_forget)
38         t.start()
39
40 # Threaded callback class
41 class ThreadFunction():
42         _CALL = 0
43         _TERM = 1
44         
45         def __init__(self, f):
46                 self._f = f
47                 self._q = queue.Queue()
48                 self._t = threading.Thread(target=self._thread_func)
49                 self._t.start()
50         
51         def _thread_func(self):
52                 while True:
53                         (cmd, data) = self._q.get()
54                         # run command
55                         if cmd == _CALL:
56                                 try:
57                                         self._f(*data)
58                                 except Exception:
59                                         logger.error("ThreadFunction: Got exception out of handler thread: %s" % str(e))
60                         elif cmd == _TERM:
61                                 assert data is None
62                                 break
63                         else:
64                                 logger.error("ThreadFunction: Command %d does not exist" % cmd)
65         
66         def __call__(self, *arg):
67                 self._q.put((self._CALL, arg))
68         
69         def stop(self):
70                 self._q.put((_TERM, None))
71                 self._t.join()
72
73 # Thread timer-repeater class: Call a function every <sleep_time> seconds
74 class ThreadRepeater():
75         def __init__(self, f, sleep_time):
76                 self._f = f
77                 self._stop = False
78                 self._sleep_time = sleep_time
79                 self._t = threading.Thread(target=self._thread_func)
80                 self._t.start()
81         
82         def _thread_func():
83                 while True:
84                         if self._stop:
85                                 break
86                         self._f()
87                         time.sleep(sleep_time)
88         
89         def stop(self):
90                 self._stop = True
91                 self._t.join()