Commit | Line | Data |
---|---|---|
4ed24f86 JD |
1 | #!/usr/bin/env python3 |
2 | # | |
3 | # The MIT License (MIT) | |
4 | # | |
a3fa57c0 | 5 | # Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com> |
4ed24f86 JD |
6 | # |
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | # of this software and associated documentation files (the "Software"), to deal | |
9 | # in the Software without restriction, including without limitation the rights | |
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | # copies of the Software, and to permit persons to whom the Software is | |
12 | # furnished to do so, subject to the following conditions: | |
13 | # | |
14 | # The above copyright notice and this permission notice shall be included in | |
15 | # all copies or substantial portions of the Software. | |
16 | # | |
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
23 | # SOFTWARE. | |
24 | ||
bd3cd7c5 JD |
25 | import math |
26 | import re | |
27 | import time | |
28 | import datetime | |
29 | import socket | |
30 | import struct | |
bd3cd7c5 JD |
31 | from linuxautomaton import sv |
32 | ||
33 | NSEC_PER_SEC = 1000000000 | |
34 | MSEC_PER_NSEC = 1000000 | |
35 | ||
36 | O_CLOEXEC = 0o2000000 | |
37 | ||
38 | ||
bd3cd7c5 JD |
39 | def convert_size(size, padding_after=False, padding_before=False): |
40 | if padding_after and size < 1024: | |
3f52a605 | 41 | space_after = ' ' |
bd3cd7c5 | 42 | else: |
3f52a605 | 43 | space_after = '' |
bd3cd7c5 | 44 | if padding_before and size < 1024: |
3f52a605 | 45 | space_before = ' ' |
bd3cd7c5 | 46 | else: |
3f52a605 | 47 | space_before = '' |
bd3cd7c5 | 48 | if size <= 0: |
3f52a605 AB |
49 | return '0 ' + space_before + 'B' + space_after |
50 | size_name = ('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB') | |
bd3cd7c5 JD |
51 | i = int(math.floor(math.log(size, 1024))) |
52 | p = math.pow(1024, i) | |
53 | s = round(size/p, 2) | |
ced36aab | 54 | if s > 0: |
bd3cd7c5 | 55 | try: |
3f52a605 | 56 | v = '%0.02f' % s |
8e05871d | 57 | return '%s %s%s%s' % (v, space_before, size_name[i], space_after) |
bd3cd7c5 JD |
58 | except: |
59 | print(i, size_name) | |
3f52a605 | 60 | raise Exception('Too big to be true') |
bd3cd7c5 JD |
61 | else: |
62 | return '0 B' | |
63 | ||
64 | ||
ced36aab AB |
65 | def is_multi_day_trace_collection(handles): |
66 | time_begin = None | |
67 | ||
68 | for handle in handles.values(): | |
69 | if time_begin is None: | |
70 | time_begin = time.localtime(handle.timestamp_begin / NSEC_PER_SEC) | |
71 | year_begin = time_begin.tm_year | |
72 | month_begin = time_begin.tm_mon | |
73 | day_begin = time_begin.tm_mday | |
74 | ||
75 | time_end = time.localtime(handle.timestamp_end / NSEC_PER_SEC) | |
76 | year_end = time_end.tm_year | |
77 | month_end = time_end.tm_mon | |
78 | day_end = time_end.tm_mday | |
79 | ||
80 | if year_begin != year_end: | |
bd3cd7c5 | 81 | return True |
ced36aab | 82 | elif month_begin != month_end: |
bd3cd7c5 | 83 | return True |
ced36aab | 84 | elif day_begin != day_end: |
bd3cd7c5 | 85 | return True |
ced36aab | 86 | |
bd3cd7c5 JD |
87 | return False |
88 | ||
89 | ||
ced36aab AB |
90 | def trace_collection_date(handles): |
91 | if is_multi_day_trace_collection(handles): | |
bd3cd7c5 | 92 | return None |
ced36aab | 93 | |
652bc6b7 AB |
94 | for handle in handles.values(): |
95 | trace_time = time.localtime(handle.timestamp_begin / NSEC_PER_SEC) | |
96 | year = trace_time.tm_year | |
97 | month = trace_time.tm_mon | |
98 | day = trace_time.tm_mday | |
99 | return (year, month, day) | |
bd3cd7c5 JD |
100 | |
101 | ||
ced36aab | 102 | def extract_timerange(handles, timerange, gmt): |
5b395a93 AB |
103 | pattern = re.compile(r'^\[(?P<begin>.*),(?P<end>.*)\]$') |
104 | if not pattern.match(timerange): | |
bd3cd7c5 | 105 | return None |
5b395a93 AB |
106 | begin_str = pattern.search(timerange).group('begin').strip() |
107 | end_str = pattern.search(timerange).group('end').strip() | |
ced36aab AB |
108 | begin = date_to_epoch_nsec(handles, begin_str, gmt) |
109 | end = date_to_epoch_nsec(handles, end_str, gmt) | |
bd3cd7c5 JD |
110 | return (begin, end) |
111 | ||
112 | ||
ced36aab | 113 | def date_to_epoch_nsec(handles, date, gmt): |
bd3cd7c5 | 114 | # match 2014-12-12 17:29:43.802588035 or 2014-12-12T17:29:43.802588035 |
5b395a93 AB |
115 | pattern1 = re.compile(r'^(?P<year>\d\d\d\d)-(?P<mon>[01]\d)-' |
116 | r'(?P<day>[0123]\d)[\sTt]' | |
117 | r'(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d).' | |
118 | r'(?P<nsec>\d\d\d\d\d\d\d\d\d)$') | |
bd3cd7c5 | 119 | # match 2014-12-12 17:29:43 or 2014-12-12T17:29:43 |
5b395a93 AB |
120 | pattern2 = re.compile(r'^(?P<year>\d\d\d\d)-(?P<mon>[01]\d)-' |
121 | r'(?P<day>[0123]\d)[\sTt]' | |
122 | r'(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d)$') | |
bd3cd7c5 | 123 | # match 17:29:43.802588035 |
5b395a93 AB |
124 | pattern3 = re.compile(r'^(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d).' |
125 | r'(?P<nsec>\d\d\d\d\d\d\d\d\d)$') | |
bd3cd7c5 | 126 | # match 17:29:43 |
5b395a93 AB |
127 | pattern4 = re.compile(r'^(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d)$') |
128 | ||
129 | if pattern1.match(date): | |
130 | year = pattern1.search(date).group('year') | |
131 | month = pattern1.search(date).group('mon') | |
132 | day = pattern1.search(date).group('day') | |
133 | hour = pattern1.search(date).group('hour') | |
134 | minute = pattern1.search(date).group('min') | |
135 | sec = pattern1.search(date).group('sec') | |
136 | nsec = pattern1.search(date).group('nsec') | |
137 | elif pattern2.match(date): | |
138 | year = pattern2.search(date).group('year') | |
139 | month = pattern2.search(date).group('mon') | |
140 | day = pattern2.search(date).group('day') | |
141 | hour = pattern2.search(date).group('hour') | |
142 | minute = pattern2.search(date).group('min') | |
143 | sec = pattern2.search(date).group('sec') | |
bd3cd7c5 | 144 | nsec = 0 |
5b395a93 | 145 | elif pattern3.match(date): |
ced36aab AB |
146 | collection_date = trace_collection_date(handles) |
147 | if collection_date is None: | |
bd3cd7c5 JD |
148 | print("Use the format 'yyyy-mm-dd hh:mm:ss[.nnnnnnnnn]' " |
149 | "for multi-day traces") | |
150 | return None | |
ced36aab | 151 | (year, month, day) = collection_date |
5b395a93 AB |
152 | hour = pattern3.search(date).group('hour') |
153 | minute = pattern3.search(date).group('min') | |
154 | sec = pattern3.search(date).group('sec') | |
155 | nsec = pattern3.search(date).group('nsec') | |
156 | elif pattern4.match(date): | |
ced36aab AB |
157 | collection_date = trace_collection_date(handles) |
158 | if collection_date is None: | |
bd3cd7c5 JD |
159 | print("Use the format 'yyyy-mm-dd hh:mm:ss[.nnnnnnnnn]' " |
160 | "for multi-day traces") | |
161 | return None | |
ced36aab | 162 | (year, month, day) = collection_date |
5b395a93 AB |
163 | hour = pattern4.search(date).group('hour') |
164 | minute = pattern4.search(date).group('min') | |
165 | sec = pattern4.search(date).group('sec') | |
bd3cd7c5 JD |
166 | nsec = 0 |
167 | else: | |
168 | return None | |
169 | ||
ced36aab | 170 | date_time = datetime.datetime(int(year), int(month), int(day), int(hour), |
5b395a93 | 171 | int(minute), int(sec)) |
bd3cd7c5 | 172 | if gmt: |
ced36aab AB |
173 | date_time = date_time + datetime.timedelta(seconds=time.timezone) |
174 | return int(date_time.timestamp()) * NSEC_PER_SEC + int(nsec) | |
bd3cd7c5 JD |
175 | |
176 | ||
177 | def ns_to_asctime(ns): | |
178 | return time.asctime(time.localtime(ns/NSEC_PER_SEC)) | |
179 | ||
180 | ||
181 | def ns_to_hour(ns): | |
ced36aab AB |
182 | date = time.localtime(ns / NSEC_PER_SEC) |
183 | return '%02d:%02d:%02d' % (date.tm_hour, date.tm_min, date.tm_sec) | |
bd3cd7c5 JD |
184 | |
185 | ||
186 | def ns_to_hour_nsec(ns, multi_day=False, gmt=False): | |
187 | if gmt: | |
ced36aab | 188 | date = time.gmtime(ns / NSEC_PER_SEC) |
bd3cd7c5 | 189 | else: |
ced36aab | 190 | date = time.localtime(ns / NSEC_PER_SEC) |
bd3cd7c5 | 191 | if multi_day: |
ced36aab AB |
192 | return ('%04d-%02d-%02d %02d:%02d:%02date.%09d' % |
193 | (date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour, | |
194 | date.tm_min, date.tm_sec, ns % NSEC_PER_SEC)) | |
bd3cd7c5 | 195 | else: |
ced36aab AB |
196 | return ('%02d:%02d:%02date.%09d' % |
197 | (date.tm_hour, date.tm_min, date.tm_sec, ns % NSEC_PER_SEC)) | |
bd3cd7c5 JD |
198 | |
199 | ||
200 | def ns_to_sec(ns): | |
ced36aab | 201 | return '%lu.%09u' % (ns / NSEC_PER_SEC, ns % NSEC_PER_SEC) |
bd3cd7c5 JD |
202 | |
203 | ||
204 | def ns_to_day(ns): | |
ced36aab AB |
205 | date = time.localtime(ns/NSEC_PER_SEC) |
206 | return '%04d-%02d-%02d' % (date.tm_year, date.tm_mon, date.tm_mday) | |
bd3cd7c5 JD |
207 | |
208 | ||
209 | def sec_to_hour(ns): | |
ced36aab AB |
210 | date = time.localtime(ns) |
211 | return '%02d:%02d:%02d' % (date.tm_hour, date.tm_min, date.tm_sec) | |
bd3cd7c5 JD |
212 | |
213 | ||
214 | def sec_to_nsec(sec): | |
215 | return sec * NSEC_PER_SEC | |
216 | ||
217 | ||
218 | def seq_to_ipv4(ip): | |
3f52a605 | 219 | return '{}.{}.{}.{}'.format(ip[0], ip[1], ip[2], ip[3]) |
bd3cd7c5 JD |
220 | |
221 | ||
222 | def int_to_ipv4(ip): | |
3f52a605 | 223 | return socket.inet_ntoa(struct.pack('!I', ip)) |
bd3cd7c5 JD |
224 | |
225 | ||
226 | def str_to_bytes(value): | |
3f52a605 AB |
227 | num = '' |
228 | unit = '' | |
bd3cd7c5 | 229 | for i in value: |
3f52a605 | 230 | if i.isdigit() or i == '.': |
bd3cd7c5 JD |
231 | num = num + i |
232 | elif i.isalnum(): | |
233 | unit = unit + i | |
234 | num = float(num) | |
5faa923d | 235 | if not unit: |
bd3cd7c5 | 236 | return int(num) |
3f52a605 | 237 | if unit in ['B']: |
bd3cd7c5 | 238 | return int(num) |
3f52a605 | 239 | if unit in ['k', 'K', 'kB', 'KB']: |
bd3cd7c5 | 240 | return int(num * 1024) |
3f52a605 | 241 | if unit in ['m', 'M', 'mB', 'MB']: |
bd3cd7c5 | 242 | return int(num * 1024 * 1024) |
3f52a605 | 243 | if unit in ['g', 'G', 'gB', 'GB']: |
bd3cd7c5 | 244 | return int(num * 1024 * 1024 * 1024) |
3f52a605 | 245 | if unit in ['t', 'T', 'tB', 'TB']: |
bd3cd7c5 | 246 | return int(num * 1024 * 1024 * 1024 * 1024) |
3f52a605 | 247 | print('Unit', unit, 'not understood') |
bd3cd7c5 JD |
248 | return None |
249 | ||
250 | ||
251 | def get_v4_addr_str(ip): | |
252 | # depending on the version of lttng-modules, the v4addr is a | |
253 | # string (< 2.6) or sequence (>= 2.6) | |
254 | try: | |
255 | return seq_to_ipv4(ip) | |
256 | except TypeError: | |
257 | return int_to_ipv4(ip) |