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 | ||
c16e0164 JD |
25 | from linuxautomaton import sp, sv, common |
26 | ||
27 | ||
28 | class StatedumpStateProvider(sp.StateProvider): | |
29 | def __init__(self, state): | |
30 | self.state = state | |
31 | self.tids = state.tids | |
32 | self.disks = state.disks | |
33 | cbs = { | |
34 | 'lttng_statedump_process_state': | |
35 | self._process_lttng_statedump_process_state, | |
36 | 'lttng_statedump_file_descriptor': | |
37 | self._process_lttng_statedump_file_descriptor, | |
38 | 'lttng_statedump_block_device': | |
39 | self._process_lttng_statedump_block_device, | |
40 | } | |
41 | self._register_cbs(cbs) | |
42 | ||
43 | def process_event(self, ev): | |
44 | self._process_event_cb(ev) | |
45 | ||
46 | def merge_fd_dict(self, p, parent): | |
47 | if len(p.fds.keys()) != 0: | |
48 | toremove = [] | |
49 | for fd in p.fds.keys(): | |
50 | if fd not in parent.fds.keys(): | |
51 | parent.fds[fd] = p.fds[fd] | |
15079839 | 52 | parent.chrono_fds[fd] = p.chrono_fds[fd] |
c16e0164 JD |
53 | else: |
54 | # best effort to fix the filename | |
55 | if len(parent.fds[fd].filename) == 0: | |
56 | parent.fds[fd].filename = p.fds[fd].filename | |
15079839 AB |
57 | chrono_fd = parent.chrono_fds[fd] |
58 | last_ts = next(reversed(chrono_fd)) | |
59 | chrono_fd[last_ts]["filename"] = p.fds[fd].filename | |
c16e0164 JD |
60 | # merge the values as they are for the same sv.FD |
61 | parent.fds[fd].net_read += p.fds[fd].net_read | |
62 | parent.fds[fd].net_write += p.fds[fd].net_write | |
63 | parent.fds[fd].disk_read += p.fds[fd].disk_read | |
64 | parent.fds[fd].disk_write += p.fds[fd].disk_write | |
65 | parent.fds[fd].open += p.fds[fd].open | |
66 | parent.fds[fd].close += p.fds[fd].close | |
67 | toremove.append(fd) | |
68 | for fd in toremove: | |
69 | p.fds.pop(fd, None) | |
15079839 | 70 | p.chrono_fds.pop(fd, None) |
c16e0164 JD |
71 | if len(p.closed_fds.keys()) != 0: |
72 | for fd in p.closed_fds.keys(): | |
73 | if fd not in parent.closed_fds.keys(): | |
74 | parent.closed_fds[fd] = p.closed_fds[fd] | |
75 | else: | |
76 | # best effort to fix the filename | |
77 | if len(parent.closed_fds[fd].name) == 0: | |
78 | parent.closed_fds[fd].name = p.closed_fds[fd].name | |
79 | # merge the values as they are for the same sv.FD | |
80 | parent.closed_fds[fd].read += p.closed_fds[fd].read | |
81 | parent.closed_fds[fd].write += p.closed_fds[fd].write | |
82 | parent.closed_fds[fd].open += p.closed_fds[fd].open | |
83 | parent.closed_fds[fd].close += p.closed_fds[fd].close | |
84 | p.closed_fds.pop(fd, None) | |
85 | ||
86 | def _process_lttng_statedump_process_state(self, event): | |
87 | tid = event["tid"] | |
88 | pid = event["pid"] | |
89 | name = event["name"] | |
90 | if tid not in self.tids: | |
91 | p = sv.Process() | |
92 | p.tid = tid | |
93 | self.tids[tid] = p | |
94 | else: | |
95 | p = self.tids[tid] | |
96 | # Even if the process got created earlier, some info might be | |
97 | # missing, add it now. | |
98 | p.pid = pid | |
99 | p.comm = name | |
100 | ||
101 | if pid != tid: | |
102 | # create the parent | |
103 | if pid not in self.tids: | |
104 | parent = sv.Process() | |
105 | parent.tid = pid | |
106 | parent.pid = pid | |
107 | parent.comm = name | |
108 | self.tids[pid] = parent | |
109 | else: | |
110 | parent = self.tids[pid] | |
111 | # If the thread had opened sv.FDs, they need to be assigned | |
112 | # to the parent. | |
113 | self.merge_fd_dict(p, parent) | |
114 | ||
115 | def _process_lttng_statedump_file_descriptor(self, event): | |
116 | pid = event["pid"] | |
117 | fd = event["fd"] | |
118 | filename = event["filename"] | |
119 | ||
120 | if pid not in self.tids: | |
121 | p = sv.Process() | |
122 | p.pid = pid | |
123 | p.tid = pid | |
124 | self.tids[pid] = p | |
125 | else: | |
126 | p = self.tids[pid] | |
127 | ||
128 | if fd not in p.fds.keys(): | |
129 | newfile = sv.FD() | |
130 | newfile.filename = filename | |
131 | newfile.fd = fd | |
132 | # FIXME: we don't have the info, just assume for now | |
133 | newfile.cloexec = 1 | |
134 | p.fds[fd] = newfile | |
44823c31 | 135 | fdtype = newfile.fdtype |
c16e0164 JD |
136 | else: |
137 | # just fix the filename | |
138 | p.fds[fd].filename = filename | |
44823c31 AB |
139 | fdtype = p.fds[fd].fdtype |
140 | ||
141 | p.track_chrono_fd(fd, filename, fdtype, event.timestamp) | |
c16e0164 JD |
142 | |
143 | def _process_lttng_statedump_block_device(self, event): | |
144 | d = common.get_disk(event["dev"], self.disks) | |
145 | d.prettyname = event["diskname"] |