Mercurial > templog
annotate py/utils.py @ 261:c3600a9fa747
merge long polling
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 09 Jun 2015 23:39:22 +0800 |
parents | 26eee8591f61 |
children | 78c542f03030 |
rev | line source |
---|---|
141 | 1 import os |
2 import sys | |
3 #import ctypes | |
4 import time | |
5 import select | |
6 import logging | |
253
0a1b642e3086
long polling config updates
Matt Johnston <matt@ucc.asn.au>
parents:
230
diff
changeset
|
7 import binascii |
259 | 8 import json |
141 | 9 |
149
d686b111dab4
working better. logging works properly, cleanup fridge.off() happens.
Matt Johnston <matt@ucc.asn.au>
parents:
145
diff
changeset
|
10 D = logging.debug |
141 | 11 L = logging.info |
12 W = logging.warning | |
13 E = logging.error | |
14 | |
15 DEFAULT_TRIES = 3 | |
16 READLINE_SELECT_TIMEOUT = 1 | |
17 | |
144 | 18 def EX(msg, *args, **kwargs): |
19 kwargs['exc_info'] = True | |
20 logging.error(msg, *args, **kwargs) | |
21 | |
141 | 22 clock_gettime = None |
23 no_clock_gettime = True | |
24 def monotonic_time(): | |
25 global clock_gettime | |
26 global no_clock_gettime | |
27 if no_clock_gettime: | |
28 return time.time() | |
29 | |
30 class timespec(ctypes.Structure): | |
31 _fields_ = [ | |
32 ('tv_sec', ctypes.c_long), | |
33 ('tv_nsec', ctypes.c_long) | |
34 ] | |
35 if not clock_gettime: | |
36 try: | |
37 librt = ctypes.CDLL('librt.so.0', use_errno=True) | |
38 clock_gettime = librt.clock_gettime | |
39 clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)] | |
40 except: | |
41 W("No clock_gettime(), using fake fallback.") | |
42 no_clock_gettime = True | |
43 return time.time() | |
44 | |
45 t = timespec() | |
46 CLOCK_MONOTONIC = 1 # see <linux/time.h> | |
47 | |
48 if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0: | |
49 errno_ = ctypes.get_errno() | |
50 raise OSError(errno_, os.strerror(errno_)) | |
51 return t.tv_sec + t.tv_nsec * 1e-9 | |
52 | |
53 # decorator, tries a number of times, returns None on failure, sleeps between | |
54 # Must be used as "@retry()" if arguments are defaulted | |
55 def retry(retries=DEFAULT_TRIES, try_time = 1): | |
56 def inner(func): | |
57 def new_f(*args, **kwargs): | |
58 for i in range(retries): | |
59 d = func(*args, **kwargs) | |
60 if d is not None: | |
61 return d | |
62 time.sleep(try_time) | |
63 return None | |
64 | |
230 | 65 new_f.__name__ = func.__name__ |
141 | 66 return new_f |
67 return inner | |
68 | |
69 def readline(sock): | |
70 timeout = READLINE_SELECT_TIMEOUT | |
71 buf = '' | |
72 while True: | |
73 (rlist, wlist, xlist) = select.select([sock], [], [], timeout) | |
74 if sock not in rlist: | |
75 # hit timeout | |
76 return None | |
77 | |
78 c = sock.recv(1) | |
79 if c == '': | |
80 # lightblue timeout | |
81 return None | |
82 if c == '\r': | |
83 continue | |
84 | |
85 buf += c | |
86 if c == '\n': | |
87 return buf | |
88 | |
89 # from http://blog.stalkr.net/2011/04/pctf-2011-32-thats-no-bluetooth.html | |
90 def crc16(buff, crc = 0, poly = 0x8408): | |
91 l = len(buff) | |
92 i = 0 | |
93 while i < l: | |
94 ch = ord(buff[i]) | |
95 uc = 0 | |
96 while uc < 8: | |
97 if (crc & 1) ^ (ch & 1): | |
98 crc = (crc >> 1) ^ poly | |
99 else: | |
100 crc >>= 1 | |
101 ch >>= 1 | |
102 uc += 1 | |
103 i += 1 | |
104 return crc | |
105 | |
106 def cheap_daemon(): | |
107 L("Daemonising.") | |
108 sys.stdout.flush() | |
109 sys.stderr.flush() | |
110 out = file('/dev/null', 'a+') | |
111 os.dup2(out.fileno(), sys.stdout.fileno()) | |
112 os.dup2(out.fileno(), sys.stderr.fileno()) | |
113 | |
114 try: | |
115 pid = os.fork() | |
116 if pid > 0: | |
117 sys.exit(0) | |
230 | 118 except OSError as e: |
141 | 119 E("Bad fork()") |
120 sys.exit(1) | |
121 | |
122 os.setsid() | |
123 | |
124 try: | |
125 pid = os.fork() | |
126 if pid > 0: | |
127 sys.exit(0) | |
230 | 128 except OSError as e: |
141 | 129 E("Bad fork()") |
130 sys.exit(1) | |
131 | |
145 | 132 def uptime(): |
133 try: | |
134 return float(open('/proc/uptime', 'r').read().split(' ', 1)[0]) | |
230 | 135 except Exception as e: |
145 | 136 return -1 |
141 | 137 |
259 | 138 |
139 def json_load_round_float(s, **args): | |
140 return json.loads(s,parse_float = lambda f: round(float(f), 2), **args) |