Changed the C stored function to return data for all procpid's in the
authorMark Wong <markwkm@gmail.com>
Wed, 21 May 2008 03:35:24 +0000 (20:35 -0700)
committerMark Wong <markwkm@gmail.com>
Wed, 21 May 2008 03:35:24 +0000 (20:35 -0700)
pg_stat_activity table.  Now you can join with other tables.  For example:

SELECT *
FROM pg_stat_activity, pg_proctab()
WHERE procpid = pid;

README
pg_proctab.c
pg_proctab.sql.in

diff --git a/README b/README
index e97c184b3d0a9123402606c7464a0d552565b1a7..c04b45f247ceaa2b064f266cd9ee0fce4b88ae31 100644 (file)
--- a/README
+++ b/README
@@ -6,10 +6,14 @@ make
 make install
 psql -f pg_proctab.sql
 
-Example
--------
+Examples
+--------
 SELECT procpid
 FROM pg_stat_activity;
 
 SELECT *
-FROM pg_proctab(12345);
+FROM pg_proctab();
+
+SELECT *
+FROM pg_stat_activity, pg_proctab()
+WHERE procpid = pid;
index a4f17269bb1fcb12c5b4b922794bec7df8eda140..a13cc920d320a246a5a3f704248dcdf5ad3bc8e0 100644 (file)
@@ -12,6 +12,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/param.h>
+#include <executor/spi.h>
 
 #if 0
 #include <linux/proc_fs.h>
@@ -28,6 +29,10 @@ PG_MODULE_MAGIC;
 #define INTEGER_LEN 10
 #define BIGINT_LEN 20
 
+#define GET_PIDS \
+               "SELECT procpid " \
+               "FROM pg_stat_activity"
+
 #define GET_NEXT_VALUE(p, q, value, length, msg) \
                if ((q = strchr(p, ' ')) == NULL) \
                { \
@@ -46,8 +51,6 @@ PG_FUNCTION_INFO_V1(pg_proctab);
 
 Datum pg_proctab(PG_FUNCTION_ARGS)
 {
-       int32 pid = PG_GETARG_INT32(0);
-
        FuncCallContext *funcctx;
        int call_cntr;
        int max_calls;
@@ -57,7 +60,7 @@ Datum pg_proctab(PG_FUNCTION_ARGS)
        struct statfs sb;
        int fd;
        int len;
-       char buffer[512];
+       char buffer[4096];
        char *p;
        char *q;
 
@@ -68,53 +71,13 @@ Datum pg_proctab(PG_FUNCTION_ARGS)
                        i_rss, i_signal, i_blocked, i_sigignore, i_sigcatch,
                        i_wchan, i_exit_signal, i_processor, i_rt_priority, i_policy,
                        i_delayacct_blkio_ticks};
-       char **values = NULL;
 
        /* stuff done only on the first call of the function */
        if (SRF_IS_FIRSTCALL())
        {
                MemoryContext oldcontext;
 
-               values = (char **) palloc(34 * sizeof(char *));
-               values[i_pid] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_comm] = (char *) palloc(1024 * sizeof(char));
-               values[i_state] = (char *) palloc(2 * sizeof(char));
-               values[i_ppid] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_pgrp] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_session] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_tty_nr] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_tpgid] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_flags] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_minflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_cminflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_majflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_cmajflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_utime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_stime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_cutime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_cstime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_priority] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_nice] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_num_threads] =
-                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_itrealvalue] =
-                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_starttime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_vsize] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_rss] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_signal] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_blocked] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_sigignore] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_sigcatch] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_wchan] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_exit_signal] =
-                               (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_processor] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
-               values[i_rt_priority] =
-                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_policy] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
-               values[i_delayacct_blkio_ticks] =
-                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               int ret;
 
                /* create a function context for cross-call persistence */
                funcctx = SRF_FIRSTCALL_INIT();
@@ -122,9 +85,6 @@ Datum pg_proctab(PG_FUNCTION_ARGS)
                /* switch to memory context appropriate for multiple function calls */
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-               /* total number of tuples to be returned */
-               funcctx->max_calls = 1;
-
                /* Build a tuple descriptor for our result type */
                if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
                        ereport(ERROR,
@@ -139,6 +99,43 @@ Datum pg_proctab(PG_FUNCTION_ARGS)
                attinmeta = TupleDescGetAttInMetadata(tupdesc);
                funcctx->attinmeta = attinmeta;
 
+               /* Get pid of all client connections. */
+
+               SPI_connect();
+
+               ret = SPI_exec(GET_PIDS, 0);
+               if (ret == SPI_OK_SELECT)
+               {
+                       int32 *ppid;
+
+                       int i;
+                       TupleDesc tupdesc;
+                       SPITupleTable *tuptable;
+                       HeapTuple tuple;
+
+                       /* total number of tuples to be returned */
+                       funcctx->max_calls = SPI_processed;
+                       funcctx->user_fctx = palloc(sizeof(int32) * funcctx->max_calls);
+                       ppid = (int32 *) funcctx->user_fctx;
+
+                       tupdesc = SPI_tuptable->tupdesc;
+                       tuptable = SPI_tuptable;
+
+                       for (i = 0; i < funcctx->max_calls; i++)
+                       {
+                               tuple = tuptable->vals[i];
+                               ppid[i] = atoi(SPI_getvalue(tuple, tupdesc, 1));
+                       }
+               }
+               else
+               {
+                       /* total number of tuples to be returned */
+                       funcctx->max_calls = 0;
+                       elog(WARNING, "unable to get procpids from pg_stat_activity");
+               }
+
+               SPI_finish();
+
                MemoryContextSwitchTo(oldcontext);
        }
 
@@ -153,8 +150,13 @@ Datum pg_proctab(PG_FUNCTION_ARGS)
        {
                HeapTuple tuple;
                Datum result;
+
+               int32 *ppid;
+               int32 pid;
                int length;
 
+               char **values = NULL;
+
                /* Check if /proc is mounted. */
                if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC)
                {
@@ -165,6 +167,9 @@ Datum pg_proctab(PG_FUNCTION_ARGS)
 
                /* Read the stat info for the pid. */
 
+               ppid = (int32 *) funcctx->user_fctx;
+               pid = ppid[call_cntr];
+
                /*
                 * Sanity check, make sure we read the pid information that we're
                 * asking for.
@@ -180,6 +185,47 @@ Datum pg_proctab(PG_FUNCTION_ARGS)
                close(fd);
                buffer[len] = '\0';
 
+               values = (char **) palloc(34 * sizeof(char *));
+               values[i_pid] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_comm] = (char *) palloc(1024 * sizeof(char));
+               values[i_state] = (char *) palloc(2 * sizeof(char));
+               values[i_ppid] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_pgrp] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_session] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_tty_nr] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_tpgid] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_flags] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_minflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_cminflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_majflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_cmajflt] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_utime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_stime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_cutime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_cstime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_priority] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_nice] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_num_threads] =
+                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_itrealvalue] =
+                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_starttime] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_vsize] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_rss] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_signal] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_blocked] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_sigignore] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_sigcatch] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_wchan] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_exit_signal] =
+                               (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_processor] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
+               values[i_rt_priority] =
+                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_policy] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+               values[i_delayacct_blkio_ticks] =
+                               (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
+
                p = buffer;
 
                /* pid */
index 93dced815beb18e5aba714f2a37d2a6ae0eb6e6e..59bb0c3fa31c6d3b747ec31019c153b711fbc94d 100644 (file)
@@ -1,6 +1,6 @@
 -- Copyright (C) 2008 Mark Wong
 CREATE OR REPLACE FUNCTION pg_proctab(
-               INOUT pid INTEGER,
+               OUT pid INTEGER,
                OUT comm VARCHAR,
                OUT state CHAR,
                OUT ppid INTEGER,