LCOV - code coverage report
Current view: top level - src/backend/backup - walsummaryfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 14 64 21.9 %
Date: 2024-05-05 08:10:59 Functions: 1 3 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * walsummaryfuncs.c
       4             :  *    SQL-callable functions for accessing WAL summary data.
       5             :  *
       6             :  * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group
       7             :  *
       8             :  * src/backend/backup/walsummaryfuncs.c
       9             :  *
      10             :  *-------------------------------------------------------------------------
      11             :  */
      12             : 
      13             : #include "postgres.h"
      14             : 
      15             : #include "backup/walsummary.h"
      16             : #include "common/blkreftable.h"
      17             : #include "funcapi.h"
      18             : #include "miscadmin.h"
      19             : #include "postmaster/walsummarizer.h"
      20             : #include "utils/fmgrprotos.h"
      21             : #include "utils/pg_lsn.h"
      22             : 
      23             : #define NUM_WS_ATTS         3
      24             : #define NUM_SUMMARY_ATTS    6
      25             : #define NUM_STATE_ATTS      4
      26             : #define MAX_BLOCKS_PER_CALL 256
      27             : 
      28             : /*
      29             :  * List the WAL summary files available in pg_wal/summaries.
      30             :  */
      31             : Datum
      32           8 : pg_available_wal_summaries(PG_FUNCTION_ARGS)
      33             : {
      34             :     ReturnSetInfo *rsi;
      35             :     List       *wslist;
      36             :     ListCell   *lc;
      37             :     Datum       values[NUM_WS_ATTS];
      38             :     bool        nulls[NUM_WS_ATTS];
      39             : 
      40           8 :     InitMaterializedSRF(fcinfo, 0);
      41           8 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
      42             : 
      43           8 :     memset(nulls, 0, sizeof(nulls));
      44             : 
      45           8 :     wslist = GetWalSummaries(0, InvalidXLogRecPtr, InvalidXLogRecPtr);
      46          68 :     foreach(lc, wslist)
      47             :     {
      48          60 :         WalSummaryFile *ws = (WalSummaryFile *) lfirst(lc);
      49             :         HeapTuple   tuple;
      50             : 
      51          60 :         CHECK_FOR_INTERRUPTS();
      52             : 
      53          60 :         values[0] = Int64GetDatum((int64) ws->tli);
      54          60 :         values[1] = LSNGetDatum(ws->start_lsn);
      55          60 :         values[2] = LSNGetDatum(ws->end_lsn);
      56             : 
      57          60 :         tuple = heap_form_tuple(rsi->setDesc, values, nulls);
      58          60 :         tuplestore_puttuple(rsi->setResult, tuple);
      59             :     }
      60             : 
      61           8 :     return (Datum) 0;
      62             : }
      63             : 
      64             : /*
      65             :  * List the contents of a WAL summary file identified by TLI, start LSN,
      66             :  * and end LSN.
      67             :  */
      68             : Datum
      69           0 : pg_wal_summary_contents(PG_FUNCTION_ARGS)
      70             : {
      71             :     ReturnSetInfo *rsi;
      72             :     Datum       values[NUM_SUMMARY_ATTS];
      73             :     bool        nulls[NUM_SUMMARY_ATTS];
      74             :     WalSummaryFile ws;
      75             :     WalSummaryIO io;
      76             :     BlockRefTableReader *reader;
      77             :     int64       raw_tli;
      78             :     RelFileLocator rlocator;
      79             :     ForkNumber  forknum;
      80             :     BlockNumber limit_block;
      81             : 
      82           0 :     InitMaterializedSRF(fcinfo, 0);
      83           0 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
      84           0 :     memset(nulls, 0, sizeof(nulls));
      85             : 
      86             :     /*
      87             :      * Since the timeline could at least in theory be more than 2^31, and
      88             :      * since we don't have unsigned types at the SQL level, it is passed as a
      89             :      * 64-bit integer. Test whether it's out of range.
      90             :      */
      91           0 :     raw_tli = PG_GETARG_INT64(0);
      92           0 :     if (raw_tli < 1 || raw_tli > PG_INT32_MAX)
      93           0 :         ereport(ERROR,
      94             :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      95             :                 errmsg("invalid timeline %lld", (long long) raw_tli));
      96             : 
      97             :     /* Prepare to read the specified WAL summary file. */
      98           0 :     ws.tli = (TimeLineID) raw_tli;
      99           0 :     ws.start_lsn = PG_GETARG_LSN(1);
     100           0 :     ws.end_lsn = PG_GETARG_LSN(2);
     101           0 :     io.filepos = 0;
     102           0 :     io.file = OpenWalSummaryFile(&ws, false);
     103           0 :     reader = CreateBlockRefTableReader(ReadWalSummary, &io,
     104             :                                        FilePathName(io.file),
     105             :                                        ReportWalSummaryError, NULL);
     106             : 
     107             :     /* Loop over relation forks. */
     108           0 :     while (BlockRefTableReaderNextRelation(reader, &rlocator, &forknum,
     109             :                                            &limit_block))
     110             :     {
     111             :         BlockNumber blocks[MAX_BLOCKS_PER_CALL];
     112             :         HeapTuple   tuple;
     113             : 
     114           0 :         CHECK_FOR_INTERRUPTS();
     115             : 
     116           0 :         values[0] = ObjectIdGetDatum(rlocator.relNumber);
     117           0 :         values[1] = ObjectIdGetDatum(rlocator.spcOid);
     118           0 :         values[2] = ObjectIdGetDatum(rlocator.dbOid);
     119           0 :         values[3] = Int16GetDatum((int16) forknum);
     120             : 
     121             :         /* Loop over blocks within the current relation fork. */
     122             :         while (1)
     123           0 :         {
     124             :             unsigned    nblocks;
     125             :             unsigned    i;
     126             : 
     127           0 :             CHECK_FOR_INTERRUPTS();
     128             : 
     129           0 :             nblocks = BlockRefTableReaderGetBlocks(reader, blocks,
     130             :                                                    MAX_BLOCKS_PER_CALL);
     131           0 :             if (nblocks == 0)
     132           0 :                 break;
     133             : 
     134             :             /*
     135             :              * For each block that we specifically know to have been modified,
     136             :              * emit a row with that block number and limit_block = false.
     137             :              */
     138           0 :             values[5] = BoolGetDatum(false);
     139           0 :             for (i = 0; i < nblocks; ++i)
     140             :             {
     141           0 :                 values[4] = Int64GetDatum((int64) blocks[i]);
     142             : 
     143           0 :                 tuple = heap_form_tuple(rsi->setDesc, values, nulls);
     144           0 :                 tuplestore_puttuple(rsi->setResult, tuple);
     145             :             }
     146             : 
     147             :             /*
     148             :              * If the limit block is not InvalidBlockNumber, emit an extra row
     149             :              * with that block number and limit_block = true.
     150             :              *
     151             :              * There is no point in doing this when the limit_block is
     152             :              * InvalidBlockNumber, because no block with that number or any
     153             :              * higher number can ever exist.
     154             :              */
     155           0 :             if (BlockNumberIsValid(limit_block))
     156             :             {
     157           0 :                 values[4] = Int64GetDatum((int64) limit_block);
     158           0 :                 values[5] = BoolGetDatum(true);
     159             : 
     160           0 :                 tuple = heap_form_tuple(rsi->setDesc, values, nulls);
     161           0 :                 tuplestore_puttuple(rsi->setResult, tuple);
     162             :             }
     163             :         }
     164             :     }
     165             : 
     166             :     /* Cleanup */
     167           0 :     DestroyBlockRefTableReader(reader);
     168           0 :     FileClose(io.file);
     169             : 
     170           0 :     return (Datum) 0;
     171             : }
     172             : 
     173             : /*
     174             :  * Returns information about the state of the WAL summarizer process.
     175             :  */
     176             : Datum
     177           0 : pg_get_wal_summarizer_state(PG_FUNCTION_ARGS)
     178             : {
     179             :     Datum       values[NUM_STATE_ATTS];
     180             :     bool        nulls[NUM_STATE_ATTS];
     181             :     TimeLineID  summarized_tli;
     182             :     XLogRecPtr  summarized_lsn;
     183             :     XLogRecPtr  pending_lsn;
     184             :     int         summarizer_pid;
     185             :     TupleDesc   tupdesc;
     186             :     HeapTuple   htup;
     187             : 
     188           0 :     GetWalSummarizerState(&summarized_tli, &summarized_lsn, &pending_lsn,
     189             :                           &summarizer_pid);
     190             : 
     191           0 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
     192           0 :         elog(ERROR, "return type must be a row type");
     193             : 
     194           0 :     memset(nulls, 0, sizeof(nulls));
     195             : 
     196           0 :     values[0] = Int64GetDatum((int64) summarized_tli);
     197           0 :     values[1] = LSNGetDatum(summarized_lsn);
     198           0 :     values[2] = LSNGetDatum(pending_lsn);
     199             : 
     200           0 :     if (summarizer_pid < 0)
     201           0 :         nulls[3] = true;
     202             :     else
     203           0 :         values[3] = Int32GetDatum(summarizer_pid);
     204             : 
     205           0 :     htup = heap_form_tuple(tupdesc, values, nulls);
     206             : 
     207           0 :     PG_RETURN_DATUM(HeapTupleGetDatum(htup));
     208             : }

Generated by: LCOV version 1.14