summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wong <markwkm@gmail.com>2009-03-03 20:09:51 -0800
committerMark Wong <markwkm@gmail.com>2009-03-03 20:09:51 -0800
commit843fddfd2484dc9353c50432cccc1e4a77015794 (patch)
treea75df6d9ccf99ff4feee8970f4a6ce37f890db84
parent26f15d8dd5193af6ff23c5b8a55a8b1865b6484c (diff)
Added the ability to sort i/o statistics. Since this was initially
developed for Linux, there will be compiler errors for the other platforms because of changes to parameters passed in a function call. That will need to be fixed.
-rw-r--r--commands.c14
-rw-r--r--help.h1
-rw-r--r--machine.h9
-rw-r--r--machine/m_linux.c251
-rw-r--r--pg_top.c42
5 files changed, 301 insertions, 16 deletions
diff --git a/commands.c b/commands.c
index 95a835d..b3f2bda 100644
--- a/commands.c
+++ b/commands.c
@@ -241,6 +241,7 @@ show_help(struct statics * stp)
{
static char *fullhelp;
char *p = NULL;
+ char *q = NULL;
if (fullhelp == NULL)
{
@@ -253,8 +254,17 @@ show_help(struct statics * stp)
{
p = "not supported";
}
- fullhelp = (char *) malloc(strlen(help_text) + strlen(p) + 2);
- sprintf(fullhelp, help_text, p);
+ if (stp->order_names != NULL)
+ {
+ q = string_list(stp->order_names_io);
+ }
+ if (q == NULL)
+ {
+ q = "not supported";
+ }
+ fullhelp = (char *) malloc(strlen(help_text) + strlen(p) + strlen(q) +
+ 2);
+ sprintf(fullhelp, help_text, p, q);
}
display_pager("Top version ");
diff --git a/help.h b/help.h
index c8d848b..f394225 100644
--- a/help.h
+++ b/help.h
@@ -34,6 +34,7 @@ o - specify sort order (%s)\n\
index stats (idx_scan, idx_tup_fetch, idx_tup_read)\n\
table stats (seq_scan, seq_tup_read, idx_scan, idx_tup_fetch,\n\
n_tup_ins, n_tup_upd, n_tup_del)\n\
+ i/o stats (%s)\n\
q - quit\n\
r - renice a process\n\
not avilable when connected to a remote database\n\
diff --git a/machine.h b/machine.h
index a296228..f8598fa 100644
--- a/machine.h
+++ b/machine.h
@@ -25,6 +25,12 @@
#define HZ sysconf(_SC_CLK_TCK)
#endif
+/* Display modes. */
+#define MODE_PROCESSES 0
+#define MODE_TABLE_STATS 1
+#define MODE_INDEX_STATS 2
+#define MODE_IO_STATS 3
+
#define QUERY_PROCESSES \
"SELECT procpid\n" \
"FROM pg_stat_activity;"
@@ -40,6 +46,7 @@ struct statics
char **memory_names;
char **swap_names; /* optional */
char **order_names; /* optional */
+ char **order_names_io; /* optional */
char **color_names; /* optional */
time_t boottime; /* optional */
struct
@@ -93,7 +100,7 @@ struct process_select
int machine_init(struct statics *);
void get_system_info(struct system_info *);
caddr_t get_process_info(struct system_info *, struct process_select *, int,
- char *);
+ char *, int);
char *format_header(char *);
char *format_next_io(caddr_t, char *(*) (uid_t));
char *format_next_process(caddr_t, char *(*) (uid_t));
diff --git a/machine/m_linux.c b/machine/m_linux.c
index d8037b5..8fb56b4 100644
--- a/machine/m_linux.c
+++ b/machine/m_linux.c
@@ -172,12 +172,25 @@ static char fmt_header[] =
/* these are names given to allowed sorting orders -- first is default */
static char *ordernames[] = {"cpu", "size", "res", "time", "command", NULL};
+static char *ordernames_io[] = {
+ "pid", "rchar", "wchar", "syscr", "syscw", "reads", "writes",
+ "cwrites", "command", NULL
+};
+
/* forward definitions for comparison functions */
int compare_cpu();
int compare_size();
int compare_res();
int compare_time();
int compare_cmd();
+int compare_pid();
+int compare_rchar();
+int compare_wchar();
+int compare_syscr();
+int compare_syscw();
+int compare_reads();
+int compare_writes();
+int compare_cwrites();
int (*proc_compares[]) () =
{
@@ -189,6 +202,20 @@ int (*proc_compares[]) () =
NULL
};
+int (*io_compares[]) () =
+{
+ compare_pid,
+ compare_rchar,
+ compare_wchar,
+ compare_syscr,
+ compare_syscw,
+ compare_reads,
+ compare_writes,
+ compare_cwrites,
+ compare_cmd,
+ NULL
+};
+
/*=SYSTEM STATE INFO====================================================*/
/* these are for calculating cpu state percentages */
@@ -425,6 +452,7 @@ machine_init(struct statics * statics)
statics->memory_names = memorynames;
statics->swap_names = swapnames;
statics->order_names = ordernames;
+ statics->order_names_io = ordernames_io;
statics->boottime = boottime;
statics->flags.fullcmds = 1;
statics->flags.warmup = 1;
@@ -787,7 +815,7 @@ read_one_proc_stat(pid_t pid, struct top_proc * proc, struct process_select * se
caddr_t
get_process_info(struct system_info * si,
struct process_select * sel,
- int compare_index, char *conninfo)
+ int compare_index, char *conninfo, int mode)
{
struct timeval thistime;
double timediff,
@@ -978,9 +1006,17 @@ get_process_info(struct system_info * si,
}
/* if requested, sort the "active" procs */
- if (si->p_active)
- qsort(pactive, si->p_active, sizeof(struct top_proc *),
- proc_compares[compare_index]);
+ if (si->p_active) {
+ if (mode == MODE_IO_STATS) {
+ qsort(pactive, si->p_active, sizeof(struct top_proc *),
+ io_compares[compare_index]);
+ }
+ else
+ {
+ qsort(pactive, si->p_active, sizeof(struct top_proc *),
+ proc_compares[compare_index]);
+ }
+ }
/* don't even pretend that the return value thing here isn't bogus */
nextactive = pactive;
@@ -1107,6 +1143,14 @@ format_next_process(caddr_t handle, char *(*get_userid) (uid_t))
#define ORDERKEY_RSSIZE if ((result = p2->rss - p1->rss) == 0)
#define ORDERKEY_MEM if ((result = p2->size - p1->size) == 0)
#define ORDERKEY_NAME if ((result = strcmp(p1->name, p2->name)) == 0)
+#define ORDERKEY_PID if ((result = p1->pid - p2->pid) == 0)
+#define ORDERKEY_RCHAR if ((result = p1->rchar - p2->rchar) == 0)
+#define ORDERKEY_WCHAR if ((result = p1->wchar - p2->wchar) == 0)
+#define ORDERKEY_SYSCR if ((result = p1->syscr - p2->syscr) == 0)
+#define ORDERKEY_SYSCW if ((result = p1->syscw - p2->syscw) == 0)
+#define ORDERKEY_READS if ((result = p1->read_bytes - p2->read_bytes) == 0)
+#define ORDERKEY_WRITES if ((result = p1->write_bytes - p2->write_bytes) == 0)
+#define ORDERKEY_CWRITES if ((result = p1->cancelled_write_bytes - p2->cancelled_write_bytes) == 0)
/* Now the array that maps process state to a weight */
@@ -1259,6 +1303,205 @@ compare_cmd(
return result == 0 ? 0 : result < 0 ? -1 : 1;
}
+int
+compare_pid(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_PID
+ ORDERKEY_RCHAR
+ ORDERKEY_WCHAR
+ ORDERKEY_SYSCR
+ ORDERKEY_SYSCW
+ ORDERKEY_READS
+ ORDERKEY_WRITES
+ ORDERKEY_CWRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
+
+int
+compare_rchar(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_RCHAR
+ ORDERKEY_PID
+ ORDERKEY_WCHAR
+ ORDERKEY_SYSCR
+ ORDERKEY_SYSCW
+ ORDERKEY_READS
+ ORDERKEY_WRITES
+ ORDERKEY_CWRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
+
+int
+compare_wchar(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_WCHAR
+ ORDERKEY_PID
+ ORDERKEY_RCHAR
+ ORDERKEY_SYSCR
+ ORDERKEY_SYSCW
+ ORDERKEY_READS
+ ORDERKEY_WRITES
+ ORDERKEY_CWRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
+
+int
+compare_syscr(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_SYSCR
+ ORDERKEY_PID
+ ORDERKEY_RCHAR
+ ORDERKEY_WCHAR
+ ORDERKEY_SYSCW
+ ORDERKEY_READS
+ ORDERKEY_WRITES
+ ORDERKEY_CWRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
+
+int
+compare_syscw(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_SYSCW
+ ORDERKEY_PID
+ ORDERKEY_RCHAR
+ ORDERKEY_WCHAR
+ ORDERKEY_SYSCR
+ ORDERKEY_READS
+ ORDERKEY_WRITES
+ ORDERKEY_CWRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
+
+int
+compare_reads(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_READS
+ ORDERKEY_PID
+ ORDERKEY_RCHAR
+ ORDERKEY_WCHAR
+ ORDERKEY_SYSCR
+ ORDERKEY_SYSCW
+ ORDERKEY_WRITES
+ ORDERKEY_CWRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
+
+int
+compare_writes(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_WRITES
+ ORDERKEY_PID
+ ORDERKEY_RCHAR
+ ORDERKEY_WCHAR
+ ORDERKEY_SYSCR
+ ORDERKEY_SYSCW
+ ORDERKEY_READS
+ ORDERKEY_CWRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
+
+int
+compare_cwrites(struct top_proc ** pp1, struct top_proc ** pp2)
+{
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_CWRITES
+ ORDERKEY_PID
+ ORDERKEY_RCHAR
+ ORDERKEY_WCHAR
+ ORDERKEY_SYSCR
+ ORDERKEY_SYSCW
+ ORDERKEY_READS
+ ORDERKEY_WRITES
+ ORDERKEY_NAME
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+}
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
diff --git a/pg_top.c b/pg_top.c
index 9a2f7b6..db11c82 100644
--- a/pg_top.c
+++ b/pg_top.c
@@ -64,12 +64,6 @@ char *copyright =
/* Size of the stdio buffer given to stdout */
#define Buffersize 2048
-/* Display modes. */
-#define MODE_PROCESSES 0
-#define MODE_TABLE_STATS 1
-#define MODE_INDEX_STATS 2
-#define MODE_IO_STATS 3
-
/* The buffer that stdio will use */
char stdoutbuf[Buffersize];
@@ -290,6 +284,7 @@ main(int argc, char *argv[])
char *order_name = NULL;
int order_index = 0;
int index_order_index = 0;
+ int io_order_index = 0;
int table_order_index = 0;
#ifndef FD_SET
@@ -794,7 +789,7 @@ Usage: %s [-ITWbcinqru] [-x x] [-s x] [-o field] [-z username]\n\
if (mode_remote == 0)
{
get_system_info(&system_info);
- (void) get_process_info(&system_info, &ps, 0, conninfo);
+ (void) get_process_info(&system_info, &ps, 0, conninfo, mode);
}
else
{
@@ -816,12 +811,20 @@ Usage: %s [-ITWbcinqru] [-x x] [-s x] [-o field] [-z username]\n\
while ((displays == -1) || (displays-- > 0))
{
+ int tmp_index = 0;
+ switch (mode) {
+ case MODE_IO_STATS:
+ tmp_index = io_order_index;
+ break;
+ default:
+ tmp_index = 0;
+ }
/* get the current stats and processes */
if (mode_remote == 0)
{
get_system_info(&system_info);
- processes = get_process_info(&system_info, &ps, order_index,
- conninfo);
+ processes = get_process_info(&system_info, &ps, tmp_index,
+ conninfo, mode);
}
else
{
@@ -1283,6 +1286,27 @@ Usage: %s [-ITWbcinqru] [-x x] [-s x] [-o field] [-z username]\n\
clear_message();
}
break;
+ case MODE_IO_STATS:
+ new_message(MT_standout,
+ "Order to sort: ");
+ if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
+ {
+ if ((i = string_index(tempbuf2, statics.order_names_io)) == -1)
+ {
+ new_message(MT_standout,
+ " %s: unrecognized sorting order", tempbuf2);
+ no_command = Yes;
+ }
+ else
+ {
+ io_order_index = i;
+ }
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
case MODE_PROCESSES:
default:
if (statics.order_names == NULL)