LCOV - differential code coverage report
Current view: top level - contrib/pg_buffercache - pg_buffercache_pages.c (source / functions) Coverage Total Hit UNC UBC GNC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 91.1 % 146 133 7 6 1 132
Current Date: 2024-04-14 14:21:10 Functions: 88.9 % 9 8 1 1 7
Baseline: 16@8cea358b128 Branches: 56.7 % 60 34 10 16 34
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 12.5 % 8 1 7 1
(240..) days: 95.7 % 138 132 6 132
Function coverage date bins:
[..60] days: 50.0 % 2 1 1 1
(240..) days: 100.0 % 7 7 7
Branch coverage date bins:
[..60] days: 0.0 % 10 0 10
(240..) days: 68.0 % 50 34 16 34

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * pg_buffercache_pages.c
                                  4                 :                :  *    display some contents of the buffer cache
                                  5                 :                :  *
                                  6                 :                :  *    contrib/pg_buffercache/pg_buffercache_pages.c
                                  7                 :                :  *-------------------------------------------------------------------------
                                  8                 :                :  */
                                  9                 :                : #include "postgres.h"
                                 10                 :                : 
                                 11                 :                : #include "access/htup_details.h"
                                 12                 :                : #include "catalog/pg_type.h"
                                 13                 :                : #include "funcapi.h"
                                 14                 :                : #include "storage/buf_internals.h"
                                 15                 :                : #include "storage/bufmgr.h"
                                 16                 :                : 
                                 17                 :                : 
                                 18                 :                : #define NUM_BUFFERCACHE_PAGES_MIN_ELEM  8
                                 19                 :                : #define NUM_BUFFERCACHE_PAGES_ELEM  9
                                 20                 :                : #define NUM_BUFFERCACHE_SUMMARY_ELEM 5
                                 21                 :                : #define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4
                                 22                 :                : 
 6529 tgl@sss.pgh.pa.us          23                 :CBC           1 : PG_MODULE_MAGIC;
                                 24                 :                : 
                                 25                 :                : /*
                                 26                 :                :  * Record structure holding the to be exposed cache data.
                                 27                 :                :  */
                                 28                 :                : typedef struct
                                 29                 :                : {
                                 30                 :                :     uint32      bufferid;
                                 31                 :                :     RelFileNumber relfilenumber;
                                 32                 :                :     Oid         reltablespace;
                                 33                 :                :     Oid         reldatabase;
                                 34                 :                :     ForkNumber  forknum;
                                 35                 :                :     BlockNumber blocknum;
                                 36                 :                :     bool        isvalid;
                                 37                 :                :     bool        isdirty;
                                 38                 :                :     uint16      usagecount;
                                 39                 :                : 
                                 40                 :                :     /*
                                 41                 :                :      * An int32 is sufficiently large, as MAX_BACKENDS prevents a buffer from
                                 42                 :                :      * being pinned by too many backends and each backend will only pin once
                                 43                 :                :      * because of bufmgr.c's PrivateRefCount infrastructure.
                                 44                 :                :      */
                                 45                 :                :     int32       pinning_backends;
                                 46                 :                : } BufferCachePagesRec;
                                 47                 :                : 
                                 48                 :                : 
                                 49                 :                : /*
                                 50                 :                :  * Function context for data persisting over repeated calls.
                                 51                 :                :  */
                                 52                 :                : typedef struct
                                 53                 :                : {
                                 54                 :                :     TupleDesc   tupdesc;
                                 55                 :                :     BufferCachePagesRec *record;
                                 56                 :                : } BufferCachePagesContext;
                                 57                 :                : 
                                 58                 :                : 
                                 59                 :                : /*
                                 60                 :                :  * Function returning data from the shared buffer cache - buffer number,
                                 61                 :                :  * relation node/tablespace/database/blocknum and dirty indicator.
                                 62                 :                :  */
 6973 neilc@samurai.com          63                 :              2 : PG_FUNCTION_INFO_V1(pg_buffercache_pages);
  549 andres@anarazel.de         64                 :              2 : PG_FUNCTION_INFO_V1(pg_buffercache_summary);
  373 tgl@sss.pgh.pa.us          65                 :              2 : PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);
    7 tmunro@postgresql.or       66                 :GNC           1 : PG_FUNCTION_INFO_V1(pg_buffercache_evict);
                                 67                 :                : 
                                 68                 :                : Datum
  564 rhaas@postgresql.org       69                 :CBC       32770 : pg_buffercache_pages(PG_FUNCTION_ARGS)
                                 70                 :                : {
                                 71                 :                :     FuncCallContext *funcctx;
                                 72                 :                :     Datum       result;
                                 73                 :                :     MemoryContext oldcontext;
                                 74                 :                :     BufferCachePagesContext *fctx;  /* User function context. */
                                 75                 :                :     TupleDesc   tupledesc;
                                 76                 :                :     TupleDesc   expected_tupledesc;
                                 77                 :                :     HeapTuple   tuple;
                                 78                 :                : 
 6973 neilc@samurai.com          79         [ +  + ]:          32770 :     if (SRF_IS_FIRSTCALL())
                                 80                 :                :     {
                                 81                 :                :         int         i;
                                 82                 :                : 
                                 83                 :              2 :         funcctx = SRF_FIRSTCALL_INIT();
                                 84                 :                : 
                                 85                 :                :         /* Switch context when allocating stuff to be used in later calls */
                                 86                 :              2 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                                 87                 :                : 
                                 88                 :                :         /* Create a user function context for cross-call persistence */
 6384 tgl@sss.pgh.pa.us          89                 :              2 :         fctx = (BufferCachePagesContext *) palloc(sizeof(BufferCachePagesContext));
                                 90                 :                : 
                                 91                 :                :         /*
                                 92                 :                :          * To smoothly support upgrades from version 1.0 of this extension
                                 93                 :                :          * transparently handle the (non-)existence of the pinning_backends
                                 94                 :                :          * column. We unfortunately have to get the result type for that... -
                                 95                 :                :          * we can't use the result type determined by the function definition
                                 96                 :                :          * without potentially crashing when somebody uses the old (or even
                                 97                 :                :          * wrong) function definition though.
                                 98                 :                :          */
 3523 andres@anarazel.de         99         [ -  + ]:              2 :         if (get_call_result_type(fcinfo, NULL, &expected_tupledesc) != TYPEFUNC_COMPOSITE)
 3523 andres@anarazel.de        100         [ #  # ]:UBC           0 :             elog(ERROR, "return type must be a row type");
                                101                 :                : 
 3523 andres@anarazel.de        102         [ +  - ]:CBC           2 :         if (expected_tupledesc->natts < NUM_BUFFERCACHE_PAGES_MIN_ELEM ||
                                103         [ -  + ]:              2 :             expected_tupledesc->natts > NUM_BUFFERCACHE_PAGES_ELEM)
 3523 andres@anarazel.de        104         [ #  # ]:UBC           0 :             elog(ERROR, "incorrect number of output arguments");
                                105                 :                : 
                                106                 :                :         /* Construct a tuple descriptor for the result rows. */
 1972 andres@anarazel.de        107                 :CBC           2 :         tupledesc = CreateTemplateTupleDesc(expected_tupledesc->natts);
 6973 neilc@samurai.com         108                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
                                109                 :                :                            INT4OID, -1, 0);
                                110                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
                                111                 :                :                            OIDOID, -1, 0);
                                112                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 3, "reltablespace",
                                113                 :                :                            OIDOID, -1, 0);
                                114                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 4, "reldatabase",
                                115                 :                :                            OIDOID, -1, 0);
 5722 heikki.linnakangas@i      116                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 5, "relforknumber",
                                117                 :                :                            INT2OID, -1, 0);
                                118                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 6, "relblocknumber",
                                119                 :                :                            INT8OID, -1, 0);
                                120                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 7, "isdirty",
                                121                 :                :                            BOOLOID, -1, 0);
                                122                 :              2 :         TupleDescInitEntry(tupledesc, (AttrNumber) 8, "usage_count",
                                123                 :                :                            INT2OID, -1, 0);
                                124                 :                : 
 3523 andres@anarazel.de        125         [ +  - ]:              2 :         if (expected_tupledesc->natts == NUM_BUFFERCACHE_PAGES_ELEM)
                                126                 :              2 :             TupleDescInitEntry(tupledesc, (AttrNumber) 9, "pinning_backends",
                                127                 :                :                                INT4OID, -1, 0);
                                128                 :                : 
 6384 tgl@sss.pgh.pa.us         129                 :              2 :         fctx->tupdesc = BlessTupleDesc(tupledesc);
                                130                 :                : 
                                131                 :                :         /* Allocate NBuffers worth of BufferCachePagesRec records. */
 2768 rhaas@postgresql.org      132                 :              2 :         fctx->record = (BufferCachePagesRec *)
                                133                 :              2 :             MemoryContextAllocHuge(CurrentMemoryContext,
                                134                 :                :                                    sizeof(BufferCachePagesRec) * NBuffers);
                                135                 :                : 
                                136                 :                :         /* Set max calls and remember the user function context. */
 6384 tgl@sss.pgh.pa.us         137                 :              2 :         funcctx->max_calls = NBuffers;
                                138                 :              2 :         funcctx->user_fctx = fctx;
                                139                 :                : 
                                140                 :                :         /* Return to original context when allocating transient memory */
 6973 neilc@samurai.com         141                 :              2 :         MemoryContextSwitchTo(oldcontext);
                                142                 :                : 
                                143                 :                :         /*
                                144                 :                :          * Scan through all the buffers, saving the relevant fields in the
                                145                 :                :          * fctx->record structure.
                                146                 :                :          *
                                147                 :                :          * We don't hold the partition locks, so we don't get a consistent
                                148                 :                :          * snapshot across all buffers, but we do grab the buffer header
                                149                 :                :          * locks, so the information of each buffer is self-consistent.
                                150                 :                :          */
 3363 andres@anarazel.de        151         [ +  + ]:          32770 :         for (i = 0; i < NBuffers; i++)
                                152                 :                :         {
                                153                 :                :             BufferDesc *bufHdr;
                                154                 :                :             uint32      buf_state;
                                155                 :                : 
                                156                 :          32768 :             bufHdr = GetBufferDescriptor(i);
                                157                 :                :             /* Lock each buffer header before inspecting. */
 2926                           158                 :          32768 :             buf_state = LockBufHdr(bufHdr);
                                159                 :                : 
 6973 neilc@samurai.com         160                 :          32768 :             fctx->record[i].bufferid = BufferDescriptorGetBuffer(bufHdr);
  599 rhaas@postgresql.org      161                 :          32768 :             fctx->record[i].relfilenumber = BufTagGetRelNumber(&bufHdr->tag);
                                162                 :          32768 :             fctx->record[i].reltablespace = bufHdr->tag.spcOid;
                                163                 :          32768 :             fctx->record[i].reldatabase = bufHdr->tag.dbOid;
                                164                 :          32768 :             fctx->record[i].forknum = BufTagGetForkNum(&bufHdr->tag);
 6973 neilc@samurai.com         165                 :          32768 :             fctx->record[i].blocknum = bufHdr->tag.blockNum;
 2926 andres@anarazel.de        166                 :          32768 :             fctx->record[i].usagecount = BUF_STATE_GET_USAGECOUNT(buf_state);
                                167                 :          32768 :             fctx->record[i].pinning_backends = BUF_STATE_GET_REFCOUNT(buf_state);
                                168                 :                : 
                                169         [ +  + ]:          32768 :             if (buf_state & BM_DIRTY)
 6973 neilc@samurai.com         170                 :           1886 :                 fctx->record[i].isdirty = true;
                                171                 :                :             else
                                172                 :          30882 :                 fctx->record[i].isdirty = false;
                                173                 :                : 
                                174                 :                :             /* Note if the buffer is valid, and has storage created */
 2926 andres@anarazel.de        175   [ +  +  +  - ]:          32768 :             if ((buf_state & BM_VALID) && (buf_state & BM_TAG_VALID))
 6973 neilc@samurai.com         176                 :           3684 :                 fctx->record[i].isvalid = true;
                                177                 :                :             else
                                178                 :          29084 :                 fctx->record[i].isvalid = false;
                                179                 :                : 
 2926 andres@anarazel.de        180                 :          32768 :             UnlockBufHdr(bufHdr, buf_state);
                                181                 :                :         }
                                182                 :                :     }
                                183                 :                : 
 6973 neilc@samurai.com         184                 :          32770 :     funcctx = SRF_PERCALL_SETUP();
                                185                 :                : 
                                186                 :                :     /* Get the saved state */
                                187                 :          32770 :     fctx = funcctx->user_fctx;
                                188                 :                : 
                                189         [ +  + ]:          32770 :     if (funcctx->call_cntr < funcctx->max_calls)
                                190                 :                :     {
 6756 bruce@momjian.us          191                 :          32768 :         uint32      i = funcctx->call_cntr;
                                192                 :                :         Datum       values[NUM_BUFFERCACHE_PAGES_ELEM];
                                193                 :                :         bool        nulls[NUM_BUFFERCACHE_PAGES_ELEM];
                                194                 :                : 
 6384 tgl@sss.pgh.pa.us         195                 :          32768 :         values[0] = Int32GetDatum(fctx->record[i].bufferid);
                                196                 :          32768 :         nulls[0] = false;
                                197                 :                : 
                                198                 :                :         /*
                                199                 :                :          * Set all fields except the bufferid to null if the buffer is unused
                                200                 :                :          * or not valid.
                                201                 :                :          */
 6973 neilc@samurai.com         202         [ +  + ]:          32768 :         if (fctx->record[i].blocknum == InvalidBlockNumber ||
 6756 bruce@momjian.us          203         [ -  + ]:           3684 :             fctx->record[i].isvalid == false)
                                204                 :                :         {
 6384 tgl@sss.pgh.pa.us         205                 :          29084 :             nulls[1] = true;
                                206                 :          29084 :             nulls[2] = true;
                                207                 :          29084 :             nulls[3] = true;
                                208                 :          29084 :             nulls[4] = true;
                                209                 :          29084 :             nulls[5] = true;
 6217 bruce@momjian.us          210                 :          29084 :             nulls[6] = true;
 5722 heikki.linnakangas@i      211                 :          29084 :             nulls[7] = true;
                                212                 :                :             /* unused for v1.0 callers, but the array is always long enough */
 3523 andres@anarazel.de        213                 :          29084 :             nulls[8] = true;
                                214                 :                :         }
                                215                 :                :         else
                                216                 :                :         {
  564 rhaas@postgresql.org      217                 :           3684 :             values[1] = ObjectIdGetDatum(fctx->record[i].relfilenumber);
 6384 tgl@sss.pgh.pa.us         218                 :           3684 :             nulls[1] = false;
                                219                 :           3684 :             values[2] = ObjectIdGetDatum(fctx->record[i].reltablespace);
                                220                 :           3684 :             nulls[2] = false;
                                221                 :           3684 :             values[3] = ObjectIdGetDatum(fctx->record[i].reldatabase);
                                222                 :           3684 :             nulls[3] = false;
 5722 heikki.linnakangas@i      223                 :           3684 :             values[4] = ObjectIdGetDatum(fctx->record[i].forknum);
 6384 tgl@sss.pgh.pa.us         224                 :           3684 :             nulls[4] = false;
 5722 heikki.linnakangas@i      225                 :           3684 :             values[5] = Int64GetDatum((int64) fctx->record[i].blocknum);
 6384 tgl@sss.pgh.pa.us         226                 :           3684 :             nulls[5] = false;
 5722 heikki.linnakangas@i      227                 :           3684 :             values[6] = BoolGetDatum(fctx->record[i].isdirty);
 6217 bruce@momjian.us          228                 :           3684 :             nulls[6] = false;
 5722 heikki.linnakangas@i      229                 :           3684 :             values[7] = Int16GetDatum(fctx->record[i].usagecount);
                                230                 :           3684 :             nulls[7] = false;
                                231                 :                :             /* unused for v1.0 callers, but the array is always long enough */
 3523 andres@anarazel.de        232                 :           3684 :             values[8] = Int32GetDatum(fctx->record[i].pinning_backends);
                                233                 :           3684 :             nulls[8] = false;
                                234                 :                :         }
                                235                 :                : 
                                236                 :                :         /* Build and return the tuple. */
 6384 tgl@sss.pgh.pa.us         237                 :          32768 :         tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
 6973 neilc@samurai.com         238                 :          32768 :         result = HeapTupleGetDatum(tuple);
                                239                 :                : 
                                240                 :          32768 :         SRF_RETURN_NEXT(funcctx, result);
                                241                 :                :     }
                                242                 :                :     else
                                243                 :              2 :         SRF_RETURN_DONE(funcctx);
                                244                 :                : }
                                245                 :                : 
                                246                 :                : Datum
  549 andres@anarazel.de        247                 :              2 : pg_buffercache_summary(PG_FUNCTION_ARGS)
                                248                 :                : {
                                249                 :                :     Datum       result;
                                250                 :                :     TupleDesc   tupledesc;
                                251                 :                :     HeapTuple   tuple;
                                252                 :                :     Datum       values[NUM_BUFFERCACHE_SUMMARY_ELEM];
                                253                 :                :     bool        nulls[NUM_BUFFERCACHE_SUMMARY_ELEM];
                                254                 :                : 
                                255                 :              2 :     int32       buffers_used = 0;
                                256                 :              2 :     int32       buffers_unused = 0;
                                257                 :              2 :     int32       buffers_dirty = 0;
                                258                 :              2 :     int32       buffers_pinned = 0;
                                259                 :              2 :     int64       usagecount_total = 0;
                                260                 :                : 
                                261         [ -  + ]:              2 :     if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE)
  549 andres@anarazel.de        262         [ #  # ]:UBC           0 :         elog(ERROR, "return type must be a row type");
                                263                 :                : 
  549 andres@anarazel.de        264         [ +  + ]:CBC       32770 :     for (int i = 0; i < NBuffers; i++)
                                265                 :                :     {
                                266                 :                :         BufferDesc *bufHdr;
                                267                 :                :         uint32      buf_state;
                                268                 :                : 
                                269                 :                :         /*
                                270                 :                :          * This function summarizes the state of all headers. Locking the
                                271                 :                :          * buffer headers wouldn't provide an improved result as the state of
                                272                 :                :          * the buffer can still change after we release the lock and it'd
                                273                 :                :          * noticeably increase the cost of the function.
                                274                 :                :          */
                                275                 :          32768 :         bufHdr = GetBufferDescriptor(i);
                                276                 :          32768 :         buf_state = pg_atomic_read_u32(&bufHdr->state);
                                277                 :                : 
                                278         [ +  + ]:          32768 :         if (buf_state & BM_VALID)
                                279                 :                :         {
                                280                 :           3684 :             buffers_used++;
                                281                 :           3684 :             usagecount_total += BUF_STATE_GET_USAGECOUNT(buf_state);
                                282                 :                : 
                                283         [ +  + ]:           3684 :             if (buf_state & BM_DIRTY)
                                284                 :           1886 :                 buffers_dirty++;
                                285                 :                :         }
                                286                 :                :         else
                                287                 :          29084 :             buffers_unused++;
                                288                 :                : 
                                289         [ -  + ]:          32768 :         if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
  549 andres@anarazel.de        290                 :UBC           0 :             buffers_pinned++;
                                291                 :                :     }
                                292                 :                : 
  549 andres@anarazel.de        293                 :CBC           2 :     memset(nulls, 0, sizeof(nulls));
                                294                 :              2 :     values[0] = Int32GetDatum(buffers_used);
                                295                 :              2 :     values[1] = Int32GetDatum(buffers_unused);
                                296                 :              2 :     values[2] = Int32GetDatum(buffers_dirty);
                                297                 :              2 :     values[3] = Int32GetDatum(buffers_pinned);
                                298                 :                : 
                                299         [ +  - ]:              2 :     if (buffers_used != 0)
                                300                 :              2 :         values[4] = Float8GetDatum((double) usagecount_total / buffers_used);
                                301                 :                :     else
  549 andres@anarazel.de        302                 :UBC           0 :         nulls[4] = true;
                                303                 :                : 
                                304                 :                :     /* Build and return the tuple. */
  549 andres@anarazel.de        305                 :CBC           2 :     tuple = heap_form_tuple(tupledesc, values, nulls);
                                306                 :              2 :     result = HeapTupleGetDatum(tuple);
                                307                 :                : 
                                308                 :              2 :     PG_RETURN_DATUM(result);
                                309                 :                : }
                                310                 :                : 
                                311                 :                : Datum
  373 tgl@sss.pgh.pa.us         312                 :              2 : pg_buffercache_usage_counts(PG_FUNCTION_ARGS)
                                313                 :                : {
                                314                 :              2 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
                                315                 :              2 :     int         usage_counts[BM_MAX_USAGE_COUNT + 1] = {0};
                                316                 :              2 :     int         dirty[BM_MAX_USAGE_COUNT + 1] = {0};
                                317                 :              2 :     int         pinned[BM_MAX_USAGE_COUNT + 1] = {0};
                                318                 :                :     Datum       values[NUM_BUFFERCACHE_USAGE_COUNTS_ELEM];
                                319                 :              2 :     bool        nulls[NUM_BUFFERCACHE_USAGE_COUNTS_ELEM] = {0};
                                320                 :                : 
                                321                 :              2 :     InitMaterializedSRF(fcinfo, 0);
                                322                 :                : 
                                323         [ +  + ]:          32770 :     for (int i = 0; i < NBuffers; i++)
                                324                 :                :     {
                                325                 :          32768 :         BufferDesc *bufHdr = GetBufferDescriptor(i);
                                326                 :          32768 :         uint32      buf_state = pg_atomic_read_u32(&bufHdr->state);
                                327                 :                :         int         usage_count;
                                328                 :                : 
                                329                 :          32768 :         usage_count = BUF_STATE_GET_USAGECOUNT(buf_state);
                                330                 :          32768 :         usage_counts[usage_count]++;
                                331                 :                : 
                                332         [ +  + ]:          32768 :         if (buf_state & BM_DIRTY)
                                333                 :           1886 :             dirty[usage_count]++;
                                334                 :                : 
                                335         [ -  + ]:          32768 :         if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
  373 tgl@sss.pgh.pa.us         336                 :UBC           0 :             pinned[usage_count]++;
                                337                 :                :     }
                                338                 :                : 
  373 tgl@sss.pgh.pa.us         339         [ +  + ]:CBC          14 :     for (int i = 0; i < BM_MAX_USAGE_COUNT + 1; i++)
                                340                 :                :     {
                                341                 :             12 :         values[0] = Int32GetDatum(i);
                                342                 :             12 :         values[1] = Int32GetDatum(usage_counts[i]);
                                343                 :             12 :         values[2] = Int32GetDatum(dirty[i]);
                                344                 :             12 :         values[3] = Int32GetDatum(pinned[i]);
                                345                 :                : 
                                346                 :             12 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
                                347                 :                :     }
                                348                 :                : 
                                349                 :              2 :     return (Datum) 0;
                                350                 :                : }
                                351                 :                : 
                                352                 :                : /*
                                353                 :                :  * Try to evict a shared buffer.
                                354                 :                :  */
                                355                 :                : Datum
    7 tmunro@postgresql.or      356                 :UNC           0 : pg_buffercache_evict(PG_FUNCTION_ARGS)
                                357                 :                : {
                                358                 :              0 :     Buffer      buf = PG_GETARG_INT32(0);
                                359                 :                : 
                                360         [ #  # ]:              0 :     if (!superuser())
                                361         [ #  # ]:              0 :         ereport(ERROR,
                                362                 :                :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                363                 :                :                  errmsg("must be superuser to use pg_buffercache_evict function")));
                                364                 :                : 
                                365   [ #  #  #  # ]:              0 :     if (buf < 1 || buf > NBuffers)
                                366         [ #  # ]:              0 :         elog(ERROR, "bad buffer ID: %d", buf);
                                367                 :                : 
                                368                 :              0 :     PG_RETURN_BOOL(EvictUnpinnedBuffer(buf));
                                369                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622