diff options
author | Mark Wong <markwkm@gmail.com> | 2009-03-03 20:09:51 -0800 |
---|---|---|
committer | Mark Wong <markwkm@gmail.com> | 2009-03-03 20:09:51 -0800 |
commit | 843fddfd2484dc9353c50432cccc1e4a77015794 (patch) | |
tree | a75df6d9ccf99ff4feee8970f4a6ce37f890db84 | |
parent | 26f15d8dd5193af6ff23c5b8a55a8b1865b6484c (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.c | 14 | ||||
-rw-r--r-- | help.h | 1 | ||||
-rw-r--r-- | machine.h | 9 | ||||
-rw-r--r-- | machine/m_linux.c | 251 | ||||
-rw-r--r-- | pg_top.c | 42 |
5 files changed, 301 insertions, 16 deletions
@@ -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 "); @@ -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\ @@ -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 @@ -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) |