summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-05-13 19:18:18 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2009-05-13 19:18:18 -0300
commit5d72a221ae7d231143d63f4f0096db76bdce0a5d (patch)
tree334df62051db4f5ec8402fe7484bbea77cd7f8a2
parent1a14596fbfca85ab8c06c3a287e318aee34a1540 (diff)
downloadtuna-5d72a221ae7d231143d63f4f0096db76bdce0a5d.tar.gz
cmdline: Add --show_sockets/-n to show thread's sockets
Using the python-inet_diag package, that is now required. For now only the inet_diag supported protocols are shown: TCP and DCCP. To support the other protocols new classes will be added to the python-linux-procfs to process the /proc/net/{udp,unix,etc} files. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--rpm/SPECS/tuna.spec6
-rwxr-xr-xsetup.py2
-rwxr-xr-xtuna-cmd.py91
3 files changed, 85 insertions, 14 deletions
diff --git a/rpm/SPECS/tuna.spec b/rpm/SPECS/tuna.spec
index 2a50dc0..e74f49f 100644
--- a/rpm/SPECS/tuna.spec
+++ b/rpm/SPECS/tuna.spec
@@ -2,7 +2,7 @@
%{!?python_ver: %define python_ver %(%{__python} -c "import sys ; print sys.version[:3]")}
Name: tuna
-Version: 0.8.4
+Version: 0.9
Release: 1%{?dist}
License: GPLv2
Summary: Application tuning GUI & command line utility
@@ -13,6 +13,7 @@ BuildRequires: python-devel
Requires: python-ethtool
Requires: python-linux-procfs >= 0.4.2
Requires: python-schedutils >= 0.2
+Requires: python-inet_diag
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
%description
@@ -76,6 +77,9 @@ rm -rf %{buildroot}
%{_bindir}/oscilloscope
%changelog
+* Wed May 13 2009 Arnaldo Carvalho de Melo <acme@redhat.com> - 0.9-1
+- cmdline: add --show_sockets/-n
+
* Mon Oct 27 2008 Arnaldo Carvalho de Melo <acme@redhat.com> - 0.8.4-1
- cmdline: Allow globbing --irqs/-q
- cmdline: Allow globbing --threads/-t
diff --git a/setup.py b/setup.py
index f80c40e..58e4eb1 100755
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@ if isfile("MANIFEST"):
PYTHONLIB = join(get_python_lib(standard_lib=1, prefix=''), 'site-packages')
setup(name="tuna",
- version = "0.8.4",
+ version = "0.9",
description = "Application tuning GUI",
author = "Arnaldo Carvalho de Melo",
author_email = "acme@redhat.com",
diff --git a/tuna-cmd.py b/tuna-cmd.py
index 5685cb1..8432f11 100755
--- a/tuna-cmd.py
+++ b/tuna-cmd.py
@@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
-import getopt, ethtool, fnmatch, procfs, re, schedutils, sys
+import getopt, ethtool, fnmatch, inet_diag, os, procfs, re, schedutils, sys
from tuna import tuna, sysfs
try:
@@ -28,7 +28,7 @@ except:
nr_cpus = None
ps = None
irqs = None
-version = "0.8.4"
+version = "0.9"
def usage():
print '''Usage: tuna [OPTIONS]
@@ -41,6 +41,7 @@ def usage():
-I, --include Allow all threads to run on CPU-LIST
-K, --no_kthreads Operations will not affect kernel threads
-m, --move move selected entities to CPU-LIST
+ -n, --show_sockets show network sockets in use by threads
-p, --priority=[POLICY]:RTPRIO set thread scheduler POLICY and RTPRIO
-P, --show_threads show thread list
-q, --irqs=IRQ-LIST IRQ-LIST affected by commands
@@ -91,7 +92,40 @@ def ps_show_header(has_ctxt_switch_info):
has_ctxt_switch_info and " %9s %12s" % ("voluntary", "nonvoluntary") or "",
"cmd")
-def ps_show_thread(pid, affect_children, ps, cpuinfo, nics, has_ctxt_switch_info):
+def ps_show_sockets(pid, ps, inodes, inode_re, indent = 0):
+ header_printed = False
+ dirname = "/proc/%s/fd" % pid
+ try:
+ filenames = os.listdir(dirname)
+ except: # Process died
+ return
+ sindent = " " * indent
+ for filename in filenames:
+ pathname = os.path.join(dirname, filename)
+ try:
+ linkto = os.readlink(pathname)
+ except: # Process died
+ continue
+ inode_match = inode_re.match(linkto)
+ if not inode_match:
+ continue
+ inode = int(inode_match.group(1))
+ if not inodes.has_key(inode):
+ continue
+ if not header_printed:
+ print "%s%-10s %-6s %-6s %15s:%-5s %15s:%-5s" % \
+ (sindent, "State", "Recv-Q", "Send-Q",
+ "Local Address", "Port",
+ "Peer Address", "Port")
+ header_printed = True
+ s = inodes[inode]
+ print "%s%-10s %-6d %-6d %15s:%-5d %15s:%-5d" % \
+ (sindent, s.state(),
+ s.receive_queue(), s.write_queue(),
+ s.saddr(), s.sport(), s.daddr(), s.dport())
+
+def ps_show_thread(pid, affect_children, ps, cpuinfo, nics,
+ has_ctxt_switch_info, sock_inodes, sock_inode_re):
global irqs
try:
affinity = schedutils.get_affinity(pid)
@@ -131,14 +165,19 @@ def ps_show_thread(pid, affect_children, ps, cpuinfo, nics, has_ctxt_switch_info
print " %-5d" % pid,
print "%6s %5d %8s%s %15s %s" % (sched, rtprio, affinity,
ctxt_switch_info, cmd, users)
+ if sock_inodes:
+ ps_show_sockets(pid, ps, sock_inodes, sock_inode_re,
+ affect_children and 3 or 4)
if affect_children and ps[pid].has_key("threads"):
for tid in ps[pid]["threads"].keys():
ps_show_thread(tid, False, ps[pid]["threads"],
- cpuinfo, nics, has_ctxt_switch_info)
+ cpuinfo, nics, has_ctxt_switch_info,
+ sock_inodes, sock_inode_re)
def ps_show(ps, affect_children, cpuinfo, thread_list, cpu_list,
- irq_list_numbers, show_uthreads, show_kthreads, has_ctxt_switch_info):
+ irq_list_numbers, show_uthreads, show_kthreads,
+ has_ctxt_switch_info, sock_inodes, sock_inode_re):
ps_list = []
for pid in ps.keys():
@@ -176,20 +215,45 @@ def ps_show(ps, affect_children, cpuinfo, thread_list, cpu_list,
nics = ethtool.get_active_devices()
for pid in ps_list:
- ps_show_thread(pid, affect_children, ps, cpuinfo, nics, has_ctxt_switch_info)
+ ps_show_thread(pid, affect_children, ps, cpuinfo, nics,
+ has_ctxt_switch_info, sock_inodes,
+ sock_inode_re)
+
+def load_socktype(socktype, inodes):
+ idiag = inet_diag.create(socktype = socktype)
+ while True:
+ try:
+ s = idiag.get()
+ except:
+ break
+ inodes[s.inode()] = s
+
+def load_sockets():
+ inodes = {}
+ for socktype in (inet_diag.TCPDIAG_GETSOCK,
+ inet_diag.DCCPDIAG_GETSOCK):
+ load_socktype(socktype, inodes)
+ return inodes
def do_ps(thread_list, cpu_list, irq_list, show_uthreads,
- show_kthreads, affect_children):
+ show_kthreads, affect_children, show_sockets):
ps = procfs.pidstats()
if affect_children:
ps.reload_threads()
+
+ sock_inodes = None
+ sock_inode_re = None
+ if show_sockets:
+ sock_inodes = load_sockets()
+ sock_inode_re = re.compile(r"socket:\[(\d+)\]")
+
cpuinfo = procfs.cpuinfo()
has_ctxt_switch_info = ps[1]["status"].has_key("voluntary_ctxt_switches")
try:
ps_show_header(has_ctxt_switch_info)
ps_show(ps, affect_children, cpuinfo, thread_list,
cpu_list, irq_list, show_uthreads, show_kthreads,
- has_ctxt_switch_info)
+ has_ctxt_switch_info, sock_inodes, sock_inode_re)
except IOError:
# 'tuna -P | head' for instance
pass
@@ -243,12 +307,12 @@ def pick_op(argument):
def main():
try:
opts, args = getopt.getopt(sys.argv[1:],
- "c:CfghiIKmp:Pq:s:S:t:UvWx",
+ "c:CfghiIKmnp:Pq:s:S:t:UvWx",
("cpus=", "affect_children",
"filter", "gui", "help",
"isolate", "include",
- "no_kthreads",
- "move", "priority=",
+ "no_kthreads", "move",
+ "show_sockets", "priority=",
"show_threads", "irqs=",
"save=", "sockets=", "threads=",
"no_uthreads", "version", "what_is",
@@ -268,6 +332,7 @@ def main():
thread_list_str = None
filter = False
affect_children = False
+ show_sockets = False
for o, a in opts:
if o in ("-h", "--help"):
@@ -317,7 +382,9 @@ def main():
if thread_list_str or irq_list_str:
continue
do_ps(thread_list, cpu_list, irq_list, uthreads,
- kthreads, affect_children)
+ kthreads, affect_children, show_sockets)
+ elif o in ("-n", "--show_sockets"):
+ show_sockets = True
elif o in ("-m", "--move", "-x", "--spread"):
if not cpu_list:
print "tuna: --move requires a cpu list!"