LCOV - code coverage report
Current view: top level - src/backend/backup - walsummaryfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 14 64 21.9 %
Date: 2024-11-21 08:14:44 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          76 :     foreach(lc, wslist)
      47             :     {
      48          68 :         WalSummaryFile *ws = (WalSummaryFile *) lfirst(lc);
      49             :         HeapTuple   tuple;
      50             : 
      51          68 :         CHECK_FOR_INTERRUPTS();
      52             : 
      53          68 :         values[0] = Int64GetDatum((int64) ws->tli);
      54          68 :         values[1] = LSNGetDatum(ws->start_lsn);
      55          68 :         values[2] = LSNGetDatum(ws->end_lsn);
      56             : 
      57          68 :         tuple = heap_form_tuple(rsi->setDesc, values, nulls);
      58          68 :         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             :         /*
     122             :          * If the limit block is not InvalidBlockNumber, emit an extra row
     123             :          * with that block number and limit_block = true.
     124             :          *
     125             :          * There is no point in doing this when the limit_block is
     126             :          * InvalidBlockNumber, because no block with that number or any higher
     127             :          * number can ever exist.
     128             :          */
     129           0 :         if (BlockNumberIsValid(limit_block))
     130             :         {
     131           0 :             values[4] = Int64GetDatum((int64) limit_block);
     132           0 :             values[5] = BoolGetDatum(true);
     133             : 
     134           0 :             tuple = heap_form_tuple(rsi->setDesc, values, nulls);
     135           0 :             tuplestore_puttuple(rsi->setResult, tuple);
     136             :         }
     137             : 
     138             :         /* Loop over blocks within the current relation fork. */
     139             :         while (1)
     140           0 :         {
     141             :             unsigned    nblocks;
     142             :             unsigned    i;
     143             : 
     144           0 :             CHECK_FOR_INTERRUPTS();
     145             : 
     146           0 :             nblocks = BlockRefTableReaderGetBlocks(reader, blocks,
     147             :                                                    MAX_BLOCKS_PER_CALL);
     148           0 :             if (nblocks == 0)
     149           0 :                 break;
     150             : 
     151             :             /*
     152             :              * For each block that we specifically know to have been modified,
     153             :              * emit a row with that block number and limit_block = false.
     154             :              */
     155           0 :             values[5] = BoolGetDatum(false);
     156           0 :             for (i = 0; i < nblocks; ++i)
     157             :             {
     158           0 :                 values[4] = Int64GetDatum((int64) blocks[i]);
     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