statedump handling
authorJulien Desfossez <jdesfossez@efficios.com>
Wed, 12 Mar 2014 17:51:08 +0000 (13:51 -0400)
committerJulien Desfossez <jdesfossez@efficios.com>
Wed, 12 Mar 2014 17:51:08 +0000 (13:51 -0400)
Signed-off-by: Julien Desfossez <jdesfossez@efficios.com>
LTTngAnalyzes/common.py
LTTngAnalyzes/statedump.py [new file with mode: 0644]
LTTngAnalyzes/syscalls.py
analyzes.py

index 49413a8dc0a294e2ffbafe5dd5ea7e8985445e32..a22568fae1640addaa81a5942830fc5746906c3b 100644 (file)
@@ -4,6 +4,7 @@ MSEC_PER_NSEC = 1000000
 class Process():
     def __init__(self):
         self.tid = -1
+        self.pid = -1
         self.comm = ""
         self.cpu_ns = 0
         self.migrate_count = 0
diff --git a/LTTngAnalyzes/statedump.py b/LTTngAnalyzes/statedump.py
new file mode 100644 (file)
index 0000000..5094ada
--- /dev/null
@@ -0,0 +1,86 @@
+from LTTngAnalyzes.common import *
+
+class Statedump():
+    def __init__(self, tids):
+        self.tids = tids
+
+    def merge_fd_dict(self, p, parent):
+        if len(p.fds.keys()) != 0:
+            for fd in p.fds.keys():
+                if fd not in parent.fds.keys():
+                    parent.fds[fd] = p.fds[fd]
+                else:
+                    # best effort to fix the filename
+                    if len(parent.fds[fd].filename) == 0:
+                        parent.fds[fd].filename = p.fds[fd].filename
+                    # merge the values as they are for the same FD
+                    parent.fds[fd].read += p.fds[fd].read
+                    parent.fds[fd].write += p.fds[fd].write
+                    parent.fds[fd].open += p.fds[fd].open
+                    parent.fds[fd].close += p.fds[fd].close
+                p.fds.pop(fd, None)
+        if len(p.closed_fds.keys()) != 0:
+            for fd in p.closed_fds.keys():
+                if fd not in parent.closed_fds.keys():
+                    parent.closed_fds[fd] = p.closed_fds[fd]
+                else:
+                    # best effort to fix the filename
+                    if len(parent.closed_fds[fd].name) == 0:
+                        parent.closed_fds[fd].name = p.closed_fds[fd].name
+                    # merge the values as they are for the same FD
+                    parent.closed_fds[fd].read += p.closed_fds[fd].read
+                    parent.closed_fds[fd].write += p.closed_fds[fd].write
+                    parent.closed_fds[fd].open += p.closed_fds[fd].open
+                    parent.closed_fds[fd].close += p.closed_fds[fd].close
+                p.closed_fds.pop(fd, None)
+
+    def process_state(self, event):
+        tid = event["tid"]
+        pid = event["pid"]
+        name = event["name"]
+        if not tid in self.tids:
+            p = Process()
+            p.tid = tid
+            self.tids[tid] = p
+        else:
+            p = self.tids[tid]
+        # Even if the process got created earlier, some info might be
+        # missing, add it now.
+        p.pid = pid
+        p.comm = name
+
+        if pid != tid:
+            # create the parent
+            if not pid in self.tids:
+                parent = Process()
+                parent.tid = pid
+                parent.pid = pid
+                parent.comm = name
+                self.tids[pid] = parent
+            else:
+                parent = self.tids[pid]
+            # If the thread had opened FDs, they need to be assigned
+            # to the parent.
+            self.merge_fd_dict(p, parent)
+
+    def file_descriptor(self, event):
+        pid = event["pid"]
+        fd = event["fd"]
+        filename = event["filename"]
+
+        if not pid in self.tids:
+            p = Process()
+            p.pid = pid
+            p.tid = pid
+            self.tids[pid] = p
+        else:
+            p = self.tids[pid]
+
+        if not fd in p.fds.keys():
+            newfile = FD()
+            newfile.filename = filename
+            newfile.fd = fd
+            p.fds[fd] = newfile
+        else:
+            # just fix the filename
+            p.fds[fd].filename = filename
index 8a4647c619aa2684530fd81030bb618640c455e7..3aebf44cd23072e3f357d0a18f30d1e21d01257d 100644 (file)
@@ -6,7 +6,8 @@ class Syscalls():
         self.tids = tids
         self.syscalls = syscalls
         # list of syscalls that open a FD (in the exit_syscall event)
-        self.open_syscalls = ["sys_open", "sys_openat"]
+        self.open_syscalls = ["sys_open", "sys_openat", "sys_accept",
+                "sys_fcntl", "sys_socket", "sys_dup2"]
         # list of syscalls that close a FD (in the "fd =" field)
         self.close_syscalls = ["sys_close"]
 
@@ -36,32 +37,54 @@ class Syscalls():
             s = t.syscalls[name]
         s.count += 1
 
-    def track_open(self, name, event, cpu):
+    def track_open(self, name, proc, event, cpu):
         cpu.current_syscall = {}
-        cpu.current_syscall["name"] = name
         if name in ["sys_open", "sys_openat"]:
             cpu.current_syscall["filename"] = event["filename"]
+        elif name in ["sys_accept", "sys_socket"]:
+            cpu.current_syscall["filename"] = "socket"
+        elif name in ["sys_dup2"]:
+            newfd = event["newfd"]
+            oldfd = event["oldfd"]
+            if newfd in proc.fds.keys():
+                self.close_fd(proc, newfd)
+            if oldfd in proc.fds.keys():
+                cpu.current_syscall["filename"] = proc.fds[oldfd].filename
+            else:
+                cpu.current_syscall["filename"] = ""
+        elif name in ["sys_fcntl"]:
+            # F_DUPFD
+            if event["cmd"] != 0:
+                return
+            oldfd = event["fd"]
+            if oldfd in proc.fds.keys():
+                cpu.current_syscall["filename"] = proc.fds[oldfd].filename
+            else:
+                cpu.current_syscall["filename"] = ""
+        cpu.current_syscall["name"] = name
 
-    def track_close(self, name, event, cpu):
-        t = self.tids[cpu.current_tid]
-        fd = event["fd"]
-        if not fd in t.fds.keys():
-#            print("%lu : Closing FD %d in %d without open" %
-#                    (event.timestamp, fd, t.tid))
-            return
-        filename = t.fds[fd].filename
-        if filename in t.closed_fds.keys():
-            f = t.closed_fds[filename]
+    def close_fd(self, proc, fd):
+        filename = proc.fds[fd].filename
+        if filename in proc.closed_fds.keys():
+            f = proc.closed_fds[filename]
             f.close += 1
-            f.read += t.fds[fd].read
-            f.write += t.fds[fd].write
+            f.read += proc.fds[fd].read
+            f.write += proc.fds[fd].write
         else:
-            t.closed_fds[filename] = t.fds[fd]
-            t.closed_fds[filename].close = 1
+            proc.closed_fds[filename] = proc.fds[fd]
+            proc.closed_fds[filename].close = 1
 #        print("Close FD %s in %d (%d, %d, %d, %d)" %
-#                (filename, t.tid, t.fds[fd].read, t.fds[fd].write,
-#                    t.fds[fd].open, t.fds[fd].close))
-        t.fds.pop(fd, None)
+#                (filename, proc.tid, proc.fds[fd].read, proc.fds[fd].write,
+#                    proc.fds[fd].open, proc.fds[fd].close))
+        proc.fds.pop(fd, None)
+
+    def track_close(self, name, proc, event, cpu):
+        fd = event["fd"]
+        if not fd in proc.fds.keys():
+            print("%lu : Closing FD %d in %d without open" %
+                    (event.timestamp, fd, proc.tid))
+            return
+        self.close_fd(proc, fd)
 
     def track_fds(self, name, event, cpu_id):
         # we don't know which process is currently on this CPU
@@ -70,14 +93,21 @@ class Syscalls():
         c = self.cpus[cpu_id]
         if c.current_tid == -1:
             return
+        t = self.tids[c.current_tid]
+        # if it's a thread, we want the parent
+        if t.pid != -1 and t.tid != t.pid:
+            t = self.tids[t.pid]
         if name in self.open_syscalls:
-            self.track_open(name, event, c)
+            self.track_open(name, t, event, c)
         elif name in self.close_syscalls:
-            self.track_close(name, event, c)
+            self.track_close(name, t, event, c)
 
     def add_tid_fd(self, event, cpu):
         ret = event["ret"]
         t = self.tids[cpu.current_tid]
+        # if it's a thread, we want the parent
+        if t.pid != -1 and t.tid != t.pid:
+            t = self.tids[t.pid]
         name = cpu.current_syscall["filename"]
         if name in t.closed_fds.keys():
             fd = t.closed_fds[name]
@@ -90,12 +120,13 @@ class Syscalls():
             fd.fd = ret
         else:
             return
-#        if fd.fd in t.fds.keys():
-#            print("%lu : FD %d in tid %d was already there, untracked close" %
-#                    (event.timestamp, fd.fd, t.tid))
+        if fd.fd in t.fds.keys():
+            print("%lu : FD %d in tid %d was already there, untracked close" %
+                    (event.timestamp, fd.fd, t.tid))
         t.fds[fd.fd] = fd
-#        print("%lu : %s opened %s (%d times)" % (event.timestamp, t.comm,
-#            fd.filename, fd.open))
+        if t.pid == 21300:
+            print("%lu : %s opened %s (%d times)" % (event.timestamp, t.comm,
+                fd.filename, fd.open))
 
     def entry(self, event):
         name = event.name
index 28b3a9a99d0ee03137f06e8c6b80c9fc2a22be46..20f6a56a81eb727313bb7ff1104674d6acab9a2e 100755 (executable)
@@ -24,6 +24,7 @@ from LTTngAnalyzes.sched_migrate_task import *
 from LTTngAnalyzes.syscalls import *
 from LTTngAnalyzes.block_bio import *
 from LTTngAnalyzes.net import *
+from LTTngAnalyzes.statedump import *
 
 class Analyzes():
     def __init__(self, traces):
@@ -130,6 +131,7 @@ class Analyzes():
         syscall = Syscalls(self.cpus, self.tids, self.syscalls)
         block_bio = BlockBio(self.cpus, self.disks)
         net = Net(self.ifaces)
+        statedump = Statedump(self.tids)
 
         for event in self.traces.events:
             if self.start_ns == 0:
@@ -159,6 +161,10 @@ class Analyzes():
                 net.recv(event)
             elif event.name == "net_dev_xmit":
                 net.send(event)
+            elif event.name == "lttng_statedump_process_state":
+                statedump.process_state(event)
+            elif event.name == "lttng_statedump_file_descriptor":
+                statedump.file_descriptor(event)
         if args.refresh == 0:
             # stats for the whole trace
             self.compute_stats()
This page took 0.02785 seconds and 5 git commands to generate.