pg_buffercache tidyup - Mailing list pgsql-patches

From Mark Kirkwood
Subject pg_buffercache tidyup
Date
Msg-id 453B0FFA.1050509@paradise.net.nz
Whole thread Raw
Responses Re: pg_buffercache tidyup  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
This is probably terrible timing, but I noticed Tom had done some nice
tidying up on pg_freespacemap to eliminate the clumsy conversion to and
from strings. This patch does a similar thing for pg_buffercache.

I did wonder about not showing buffers that are invalid or not in use
(currently displays all attributes bar the id as NULL). Comments?

Cheers

Mark

Index: contrib/pg_buffercache/pg_buffercache_pages.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v
retrieving revision 1.10
diff -c -r1.10 pg_buffercache_pages.c
*** contrib/pg_buffercache/pg_buffercache_pages.c    19 Oct 2006 18:32:46 -0000    1.10
--- contrib/pg_buffercache/pg_buffercache_pages.c    22 Oct 2006 06:27:52 -0000
***************
*** 8,13 ****
--- 8,14 ----
   */
  #include "postgres.h"
  #include "funcapi.h"
+ #include "access/heapam.h"
  #include "catalog/pg_type.h"
  #include "storage/buf_internals.h"
  #include "storage/bufmgr.h"
***************
*** 44,52 ****
  typedef struct
  {

!     AttInMetadata *attinmeta;
      BufferCachePagesRec *record;
-     char       *values[NUM_BUFFERCACHE_PAGES_ELEM];

  }    BufferCachePagesContext;

--- 45,52 ----
  typedef struct
  {

!     TupleDesc    tupdesc;
      BufferCachePagesRec *record;

  }    BufferCachePagesContext;

***************
*** 77,83 ****
          /* Switch context when allocating stuff to be used in later calls */
          oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

!         /* Construct a tuple to return. */
          tupledesc = CreateTemplateTupleDesc(NUM_BUFFERCACHE_PAGES_ELEM, false);
          TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
                             INT4OID, -1, 0);
--- 77,87 ----
          /* Switch context when allocating stuff to be used in later calls */
          oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

!
!         /* Create a user function context for cross-call persistence */
!         fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
!
!         /* Construct a tuple to return, and save its descriptor. */
          tupledesc = CreateTemplateTupleDesc(NUM_BUFFERCACHE_PAGES_ELEM, false);
          TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
                             INT4OID, -1, 0);
***************
*** 92,118 ****
          TupleDescInitEntry(tupledesc, (AttrNumber) 6, "isdirty",
                             BOOLOID, -1, 0);

!         /* Generate attribute metadata needed later to produce tuples */
!         funcctx->attinmeta = TupleDescGetAttInMetadata(tupledesc);
!
!         /*
!          * Create a function context for cross-call persistence and initialize
!          * the buffer counters.
!          */
!         fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
!         funcctx->max_calls = NBuffers;
!         funcctx->user_fctx = fctx;

          /* Allocate NBuffers worth of BufferCachePagesRec records. */
          fctx->record = (BufferCachePagesRec *) palloc(sizeof(BufferCachePagesRec) * NBuffers);

!         /* allocate the strings for tuple formation */
!         fctx->values[0] = (char *) palloc(3 * sizeof(uint32) + 1);
!         fctx->values[1] = (char *) palloc(3 * sizeof(uint32) + 1);
!         fctx->values[2] = (char *) palloc(3 * sizeof(uint32) + 1);
!         fctx->values[3] = (char *) palloc(3 * sizeof(uint32) + 1);
!         fctx->values[4] = (char *) palloc(3 * sizeof(uint32) + 1);
!         fctx->values[5] = (char *) palloc(2);

          /* Return to original context when allocating transient memory */
          MemoryContextSwitchTo(oldcontext);
--- 96,109 ----
          TupleDescInitEntry(tupledesc, (AttrNumber) 6, "isdirty",
                             BOOLOID, -1, 0);

!         fctx->tupdesc = BlessTupleDesc(tupledesc);

          /* Allocate NBuffers worth of BufferCachePagesRec records. */
          fctx->record = (BufferCachePagesRec *) palloc(sizeof(BufferCachePagesRec) * NBuffers);

!         /* Set max calls and remember the user function context. */
!         funcctx->max_calls = NBuffers;
!         funcctx->user_fctx = fctx;

          /* Return to original context when allocating transient memory */
          MemoryContextSwitchTo(oldcontext);
***************
*** 167,184 ****
      if (funcctx->call_cntr < funcctx->max_calls)
      {
          uint32        i = funcctx->call_cntr;
!         char       *values[NUM_BUFFERCACHE_PAGES_ELEM];
!         int            j;
!
!         /*
!          * Use a temporary values array, initially pointing to fctx->values,
!          * so it can be reassigned w/o losing the storage for subsequent
!          * calls.
!          */
!         for (j = 0; j < NUM_BUFFERCACHE_PAGES_ELEM; j++)
!         {
!             values[j] = fctx->values[j];
!         }


          /*
--- 158,165 ----
      if (funcctx->call_cntr < funcctx->max_calls)
      {
          uint32        i = funcctx->call_cntr;
!         Datum        values[NUM_BUFFERCACHE_PAGES_ELEM];
!         bool        nulls[NUM_BUFFERCACHE_PAGES_ELEM];


          /*
***************
*** 189,224 ****
              fctx->record[i].isvalid == false)
          {

!             sprintf(values[0], "%u", fctx->record[i].bufferid);
!             values[1] = NULL;
!             values[2] = NULL;
!             values[3] = NULL;
!             values[4] = NULL;
!             values[5] = NULL;

          }
          else
          {

!             sprintf(values[0], "%u", fctx->record[i].bufferid);
!             sprintf(values[1], "%u", fctx->record[i].relfilenode);
!             sprintf(values[2], "%u", fctx->record[i].reltablespace);
!             sprintf(values[3], "%u", fctx->record[i].reldatabase);
!             sprintf(values[4], "%u", fctx->record[i].blocknum);
              if (fctx->record[i].isdirty)
              {
!                 strcpy(values[5], "t");
              }
              else
              {
!                 strcpy(values[5], "f");
              }

          }


          /* Build and return the tuple. */
!         tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
          result = HeapTupleGetDatum(tuple);


--- 170,212 ----
              fctx->record[i].isvalid == false)
          {

!             values[0] = Int32GetDatum(fctx->record[i].bufferid);
!             nulls[0] = false;
!             nulls[1] = true;
!             nulls[2] = true;
!             nulls[3] = true;
!             nulls[4] = true;
!             nulls[5] = true;

          }
          else
          {

!             values[0] = Int32GetDatum(fctx->record[i].bufferid);
!             nulls[0] = false;
!             values[1] = ObjectIdGetDatum(fctx->record[i].relfilenode);
!             nulls[1] = false;
!             values[2] = ObjectIdGetDatum(fctx->record[i].reltablespace);
!             nulls[2] = false;
!             values[3] = ObjectIdGetDatum(fctx->record[i].reldatabase);
!             nulls[3] = false;
!             values[4] = Int64GetDatum((int64) fctx->record[i].blocknum);
!             nulls[4] = false;
              if (fctx->record[i].isdirty)
              {
!                 values[5] = BoolGetDatum(true);
              }
              else
              {
!                 values[5] = BoolGetDatum(false);
              }
+             nulls[5] = false;

          }


          /* Build and return the tuple. */
!         tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
          result = HeapTupleGetDatum(tuple);



pgsql-patches by date:

Previous
From: Tom Lane
Date:
Subject: Re: Updates for vcbuild
Next
From: "Magnus Hagander"
Date:
Subject: Re: Updates for vcbuild