summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wong <mark@2ndQuadrant.com>2020-07-30 18:08:09 -0700
committerMark Wong <mark@2ndQuadrant.com>2020-07-30 18:08:09 -0700
commit1d0fb40ec2a2b444cd9429fb77c1dd36ff7ee369 (patch)
tree5183d80ca23fe7c0968d2e98eab807269d1cf8c1
parentf3a30cd1b356b37e44f8b2c5bb1a564a906a3dfd (diff)
m_openbsd: multiple updates
* Updated on OpenBSD 6.7 * add replication view * update activity view * Username column now reflects the Postgres role. * State column now reflects Postgres backend state. * Transaction (XTIME) and query (QTIME) execution time has been added. * Added LOCKS column showing number of locks acquired per process. * Removed column relating to priority and nice.
-rw-r--r--HISTORY.rst1
-rw-r--r--machine/m_openbsd.c228
-rw-r--r--machine/m_remote.c2
-rw-r--r--pg_top.h1
4 files changed, 175 insertions, 57 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index a85f3b0..0a6b098 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -25,6 +25,7 @@ YYYY-MM-DD v4.0.0
* Fix view of locks held by process. Separate table and index locks. Also
showing schema.
* Handle longer pids on Linux
+* Updated for OpenBSD 6.7.
2013-07-31 v3.7.0
-----------------
diff --git a/machine/m_openbsd.c b/machine/m_openbsd.c
index cf2c043..56ded8c 100644
--- a/machine/m_openbsd.c
+++ b/machine/m_openbsd.c
@@ -34,11 +34,12 @@
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/dkstat.h>
#include <sys/mount.h>
#include <sys/proc.h>
+#include <sys/sched.h>
#include <sys/swap.h>
#include <sys/sysctl.h>
+#include <sys/tree.h>
#include <stdio.h>
#include <stdlib.h>
@@ -54,7 +55,6 @@
#include "loadavg.h"
static long swapmode(long *, long *);
-static char *state_abbr(struct kinfo_proc *);
static char *format_comm(struct kinfo_proc *);
/* get_process_info passes back a handle. This is what it looks like: */
@@ -65,6 +65,39 @@ struct handle
int remaining; /* number of pointers remaining */
};
+struct pg_proc
+{
+ RB_ENTRY(pg_proc) entry;
+ pid_t pid;
+
+ char *name;
+ char *usename;
+ int pgstate;
+ unsigned long xtime;
+ unsigned long qtime;
+ unsigned int locks;
+
+ /* Replication data */
+ char *application_name;
+ char *client_addr;
+ char *repstate;
+ char *primary;
+ char *sent;
+ char *write;
+ char *flush;
+ char *replay;
+ long long sent_lag;
+ long long write_lag;
+ long long flush_lag;
+ long long replay_lag;
+};
+
+int topproccmp(struct pg_proc *, struct pg_proc *);
+
+RB_HEAD(pgproc, pg_proc) head_proc = RB_INITIALIZER(&head_proc);
+RB_PROTOTYPE(pgproc, pg_proc, entry, topproccmp)
+RB_GENERATE(pgproc, pg_proc, entry, topproccmp)
+
/* what we consider to be process size: */
#define PROCSIZE(pp) ((pp)->p_vm_tsize + (pp)->p_vm_dsize + (pp)->p_vm_ssize)
@@ -72,13 +105,13 @@ struct handle
* These definitions control the format of the per-process area
*/
static char header[] =
-" PID X PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND";
+" PID X SIZE RES STATE XTIME QTIME %CPU LOCKS COMMAND";
/* 0123456 -- field to fill in starts at header+6 */
#define UNAME_START 6
#define Proc_format \
- "%5d %-8.8s %3d %4d %5s %5s %-8s %-7.7s %6s %5.2f%% %.50s"
+ "%5d %-8.8s %5s %5s %-8s %5s %5s %5.2f %5d %.50s"
/* process state names for the "STATE" column of the display */
/*
@@ -96,12 +129,7 @@ static int64_t * *cp_old;
static int64_t * *cp_diff;
/* these are for detailing the process states */
-int process_states[8];
-char *procstatenames[] = {
- "", " starting, ", " running, ", " idle, ",
- " stopped, ", " zombie, ", " dead, ", " on processor, ",
- NULL
-};
+int process_states[6];
/* these are for detailing the cpu states */
int64_t *cpu_states;
@@ -225,9 +253,9 @@ void
get_system_info(struct system_info *si)
{
static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
- static int vmtotal_mib[] = {CTL_VM, VM_METER};
+ static int uvmexp_mib[] = {CTL_VM, VM_UVMEXP};
struct loadavg sysload;
- struct vmtotal vmtotal;
+ struct uvmexp uvmexp;
double *infoloadp;
size_t size;
int i;
@@ -241,6 +269,7 @@ get_system_info(struct system_info *si)
* is more than 1 process.
*/
if (nproc > 1)
+ {
if (ncpu > 1)
{
int cp_time_mib[] = {CTL_KERN, KERN_CPTIME2, 0};
@@ -275,6 +304,7 @@ get_system_info(struct system_info *si)
cp_old[0], cp_diff[0]);
}
}
+ }
size = sizeof(sysload);
if (sysctl(sysload_mib, 2, &sysload, &size, NULL, 0) < 0)
@@ -285,18 +315,18 @@ get_system_info(struct system_info *si)
/* get total -- systemwide main memory usage structure */
- size = sizeof(vmtotal);
- if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0)
+ size = sizeof(uvmexp);
+ if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0)
{
warn("sysctl failed");
- bzero(&vmtotal, sizeof(vmtotal));
+ bzero(&uvmexp, sizeof(uvmexp));
}
/* convert memory stats to Kbytes */
memory_stats[0] = -1;
- memory_stats[1] = pagetok(vmtotal.t_arm);
- memory_stats[2] = pagetok(vmtotal.t_rm);
+ memory_stats[1] = pagetok(uvmexp.active);
+ memory_stats[2] = pagetok(uvmexp.npages - uvmexp.free);
memory_stats[3] = -1;
- memory_stats[4] = pagetok(vmtotal.t_free);
+ memory_stats[4] = pagetok(uvmexp.free);
memory_stats[5] = -1;
if (!swapmode(&memory_stats[6], &memory_stats[7]))
@@ -315,12 +345,9 @@ static struct handle handle;
caddr_t
get_process_info(struct system_info *si, struct process_select *sel,
- int compare_index, const char *values[])
+ int compare_index, struct pg_conninfo_ctx *conninfo, int mode)
{
int show_idle,
- show_system,
- show_threads,
- show_uid,
show_cmd;
int total_procs,
active_procs;
@@ -330,8 +357,8 @@ get_process_info(struct system_info *si, struct process_select *sel,
size_t size;
int i;
- PGconn *pgconn;
PGresult *pgresult = NULL;
+ struct pg_proc *n, *p;
size = (size_t) sizeof(struct kinfo_proc);
mib[0] = CTL_KERN;
@@ -341,15 +368,22 @@ get_process_info(struct system_info *si, struct process_select *sel,
mib[5] = 1;
nproc = 0;
- pgconn = connect_to_db(values);
- if (pgconn != NULL)
+ connect_to_db(conninfo);
+ if (conninfo->connection != NULL)
{
- pgresult = pg_processes(pgconn);
+ if (mode == MODE_REPLICATION)
+ {
+ pgresult = pg_replication(conninfo->connection);
+ }
+ else
+ {
+ pgresult = pg_processes(conninfo->connection);
+ }
nproc = PQntuples(pgresult);
- pbase = (struct kinfo_proc *) realloc(pbase,
- sizeof(struct kinfo_proc *) * nproc);
+ if (nproc > onproc)
+ pbase = (struct kinfo_proc *)
+ realloc(pbase, sizeof(struct kinfo_proc) * nproc);
}
- PQfinish(pgconn);
if (nproc > onproc)
pref = (struct kinfo_proc **) realloc(pref,
@@ -364,7 +398,6 @@ get_process_info(struct system_info *si, struct process_select *sel,
/* set up flags which define what we are going to select */
show_idle = sel->idle;
- show_uid = sel->uid != (uid_t) -1;
show_cmd = sel->command != NULL;
/* count up process states and get pointers to interesting procs */
@@ -376,7 +409,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
for (pp = pbase; pp < &pbase[nproc]; pp++)
{
mib[3] = atoi(PQgetvalue(pgresult, i, 0));
- if (sysctl(mib, 6, &pbase[i++], &size, NULL, 0) != 0)
+ if (sysctl(mib, 6, &pbase[i], &size, NULL, 0) != 0)
{
/*
* It appears that when pg_top is the only process accessing the
@@ -385,7 +418,6 @@ get_process_info(struct system_info *si, struct process_select *sel,
* throws any error, assume that is the case and adjust pbase
* accordingly.
*/
- --i;
--nproc;
continue;
}
@@ -397,15 +429,14 @@ get_process_info(struct system_info *si, struct process_select *sel,
* ignored unless show_system is set.
*/
if (pp->p_stat != 0 &&
- (show_system || (pp->p_flag & P_SYSTEM) == 0) &&
- (show_threads || (pp->p_flag & P_THREAD) == 0))
+ ((pp->p_flag & P_SYSTEM) == 0) &&
+ ((pp->p_flag & P_THREAD) == 0))
{
total_procs++;
process_states[(unsigned char) pp->p_stat]++;
if (pp->p_stat != SZOMB &&
(show_idle || pp->p_pctcpu != 0 ||
pp->p_stat == SRUN) &&
- (!show_uid || pp->p_ruid == sel->uid) &&
(!show_cmd || strstr(pp->p_comm,
sel->command)))
{
@@ -413,10 +444,59 @@ get_process_info(struct system_info *si, struct process_select *sel,
active_procs++;
}
}
+
+ n = malloc(sizeof(struct pg_proc));
+ if (n == NULL)
+ {
+ fprintf(stderr, "malloc error\n");
+ if (pgresult != NULL)
+ PQclear(pgresult);
+ disconnect_from_db(conninfo);
+ exit(1);
+ }
+ memset(n, 0, sizeof(struct pg_proc));
+ n->pid = atoi(PQgetvalue(pgresult, i, 0));
+ p = RB_INSERT(pgproc, &head_proc, n);
+ if (p != NULL)
+ {
+ free(n);
+ n = p;
+ }
+
+ if (mode == MODE_REPLICATION)
+ {
+ update_str(&n->usename, PQgetvalue(pgresult, i, REP_USENAME));
+ update_str(&n->application_name,
+ PQgetvalue(pgresult, i, REP_APPLICATION_NAME));
+ update_str(&n->client_addr,
+ PQgetvalue(pgresult, i, REP_CLIENT_ADDR));
+ update_str(&n->repstate, PQgetvalue(pgresult, i, REP_STATE));
+ update_str(&n->primary,
+ PQgetvalue(pgresult, i, REP_WAL_INSERT));
+ update_str(&n->sent, PQgetvalue(pgresult, i, REP_SENT));
+ update_str(&n->write, PQgetvalue(pgresult, i, REP_WRITE));
+ update_str(&n->flush, PQgetvalue(pgresult, i, REP_FLUSH));
+ update_str(&n->replay, PQgetvalue(pgresult, i, REP_REPLAY));
+ n->sent_lag = atol(PQgetvalue(pgresult, i, REP_SENT_LAG));
+ n->write_lag = atol(PQgetvalue(pgresult, i, REP_WRITE_LAG));
+ n->flush_lag = atol(PQgetvalue(pgresult, i, REP_FLUSH_LAG));
+ n->replay_lag = atol(PQgetvalue(pgresult, i, REP_REPLAY_LAG));
+ }
+ else
+ {
+ update_str(&n->name, PQgetvalue(pgresult, i, PROC_QUERY));
+ printable(n->name);
+ update_state(&n->pgstate, PQgetvalue(pgresult, i, PROC_STATE));
+ update_str(&n->usename, PQgetvalue(pgresult, i, PROC_USENAME));
+ n->xtime = atol(PQgetvalue(pgresult, i, PROC_XSTART));
+ n->qtime = atol(PQgetvalue(pgresult, i, PROC_QSTART));
+ n->locks = atoi(PQgetvalue(pgresult, i, PROC_LOCKS));
+ }
+ ++i;
}
/* if requested, sort the "interesting" processes */
- if (compare_index != 0)
+ if (compare_index >= 0)
qsort((char *) pref, active_procs,
sizeof(struct kinfo_proc *), proc_compares[compare_index]);
/* remember active and total counts */
@@ -432,20 +512,6 @@ get_process_info(struct system_info *si, struct process_select *sel,
char fmt[MAX_COLS]; /* static area where result is built */
static char *
-state_abbr(struct kinfo_proc *pp)
-{
- static char buf[10];
-
- if (ncpu > 1 && pp->p_cpuid != KI_NOCPU)
- snprintf(buf, sizeof buf, "%s/%llu",
- state_abbrev[(unsigned char) pp->p_stat], pp->p_cpuid);
- else
- snprintf(buf, sizeof buf, "%s",
- state_abbrev[(unsigned char) pp->p_stat]);
- return buf;
-}
-
-static char *
format_comm(struct kinfo_proc *kp)
{
#define ARG_SIZE 60
@@ -481,19 +547,24 @@ format_comm(struct kinfo_proc *kp)
}
char *
-format_next_process(caddr_t handle, char *(*get_userid) (uid_t))
+format_next_process(caddr_t handle)
{
char *p_wait;
struct kinfo_proc *pp;
struct handle *hp;
int cputime;
double pct;
+ struct pg_proc n, *p = NULL;
/* find and remember the next proc structure */
hp = (struct handle *) handle;
pp = *(hp->next_proc++);
hp->remaining--;
+ memset(&n, 0, sizeof(struct pg_proc));
+ n.pid = pp->p_pid;
+ p = RB_FIND(pgproc, &head_proc, &n);
+
cputime = pp->p_rtime_sec + ((pp->p_rtime_usec + 500000) / 1000000);
/* calculate the base for cpu percentages */
@@ -506,19 +577,58 @@ format_next_process(caddr_t handle, char *(*get_userid) (uid_t))
/* format this entry */
snprintf(fmt, sizeof fmt, Proc_format,
- pp->p_pid, (*get_userid) (pp->p_ruid),
- pp->p_priority - PZERO, pp->p_nice - NZERO,
+ pp->p_pid, p->usename,
format_k(pagetok(PROCSIZE(pp))),
format_k(pagetok(pp->p_vm_rssize)),
- (pp->p_stat == SSLEEP && pp->p_slptime > maxslp) ?
- "idle" : state_abbr(pp),
- p_wait, format_time(cputime), 100.0 * pct,
+ backendstatenames[p->pgstate],
+ format_time(p->xtime),
+ format_time(p->qtime),
+ 100.0 * pct,
+ p->locks,
printable(format_comm(pp)));
/* return the result */
return (fmt);
}
+char *
+format_next_replication(caddr_t handle)
+{
+ static char fmt[MAX_COLS]; /* static area where result is built */
+ register struct kinfo_proc *pp;
+ struct handle *hp;
+ struct pg_proc n, *p = NULL;
+
+ /* find and remember the next proc structure */
+ hp = (struct handle *) handle;
+ pp = *(hp->next_proc++);
+ hp->remaining--;
+
+ memset(&n, 0, sizeof(struct pg_proc));
+ n.pid = pp->p_pid;
+ p = RB_FIND(pgproc, &head_proc, &n);
+
+ snprintf(fmt, sizeof(fmt),
+ "%5d %-8.8s %-11.11s %15s %-9.9s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s %5s %5s %5s %5s",
+ p->pid,
+ p->usename,
+ p->application_name,
+ p->client_addr,
+ p->repstate,
+ p->primary,
+ p->sent,
+ p->write,
+ p->flush,
+ p->replay,
+ format_b(p->sent_lag),
+ format_b(p->write_lag),
+ format_b(p->flush_lag),
+ format_b(p->replay_lag));
+
+ /* return the result */
+ return (fmt);
+}
+
/* comparison routine for qsort */
static unsigned char sorted_state[] =
{
@@ -750,3 +860,9 @@ swapmode(long *used, long *total)
free(swdev);
return 1;
}
+
+int
+topproccmp(struct pg_proc *e1, struct pg_proc *e2)
+{
+ return (e1->pid < e2->pid ? -1 : e1->pid > e2->pid);
+}
diff --git a/machine/m_remote.c b/machine/m_remote.c
index 0369ba6..19b2ddd 100644
--- a/machine/m_remote.c
+++ b/machine/m_remote.c
@@ -3,7 +3,7 @@
*/
#include <stdlib.h>
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/tree.h>
#endif /* __FreeBSD__*/
#ifdef __linux__
diff --git a/pg_top.h b/pg_top.h
index 95e17d7..b3af7ec 100644
--- a/pg_top.h
+++ b/pg_top.h
@@ -10,6 +10,7 @@
#define _PG_TOP_H_
#include "machine.h"
+#include "os.h"
/* Log base 2 of 1024 is 10 (2^10 == 1024) */
#define LOG1024 10