LCOV - code coverage report
Current view: top level - src/backend/access/rmgrdesc - xlogdesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 89 136 65.4 %
Date: 2024-07-18 16:11:39 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * xlogdesc.c
       4             :  *    rmgr descriptor routines for access/transam/xlog.c
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/access/rmgrdesc/xlogdesc.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/transam.h"
      18             : #include "access/xlog.h"
      19             : #include "access/xlog_internal.h"
      20             : #include "catalog/pg_control.h"
      21             : #include "utils/guc.h"
      22             : #include "utils/timestamp.h"
      23             : 
      24             : /*
      25             :  * GUC support
      26             :  */
      27             : const struct config_enum_entry wal_level_options[] = {
      28             :     {"minimal", WAL_LEVEL_MINIMAL, false},
      29             :     {"replica", WAL_LEVEL_REPLICA, false},
      30             :     {"archive", WAL_LEVEL_REPLICA, true}, /* deprecated */
      31             :     {"hot_standby", WAL_LEVEL_REPLICA, true}, /* deprecated */
      32             :     {"logical", WAL_LEVEL_LOGICAL, false},
      33             :     {NULL, 0, false}
      34             : };
      35             : 
      36             : void
      37          96 : xlog_desc(StringInfo buf, XLogReaderState *record)
      38             : {
      39          96 :     char       *rec = XLogRecGetData(record);
      40          96 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
      41             : 
      42          96 :     if (info == XLOG_CHECKPOINT_SHUTDOWN ||
      43             :         info == XLOG_CHECKPOINT_ONLINE)
      44           4 :     {
      45           4 :         CheckPoint *checkpoint = (CheckPoint *) rec;
      46             : 
      47           8 :         appendStringInfo(buf, "redo %X/%X; "
      48             :                          "tli %u; prev tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
      49             :                          "oldest xid %u in DB %u; oldest multi %u in DB %u; "
      50             :                          "oldest/newest commit timestamp xid: %u/%u; "
      51             :                          "oldest running xid %u; %s",
      52           4 :                          LSN_FORMAT_ARGS(checkpoint->redo),
      53             :                          checkpoint->ThisTimeLineID,
      54             :                          checkpoint->PrevTimeLineID,
      55           4 :                          checkpoint->fullPageWrites ? "true" : "false",
      56           4 :                          EpochFromFullTransactionId(checkpoint->nextXid),
      57           4 :                          XidFromFullTransactionId(checkpoint->nextXid),
      58             :                          checkpoint->nextOid,
      59             :                          checkpoint->nextMulti,
      60             :                          checkpoint->nextMultiOffset,
      61             :                          checkpoint->oldestXid,
      62             :                          checkpoint->oldestXidDB,
      63             :                          checkpoint->oldestMulti,
      64             :                          checkpoint->oldestMultiDB,
      65             :                          checkpoint->oldestCommitTsXid,
      66             :                          checkpoint->newestCommitTsXid,
      67             :                          checkpoint->oldestActiveXid,
      68             :                          (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
      69             :     }
      70          92 :     else if (info == XLOG_NEXTOID)
      71             :     {
      72             :         Oid         nextOid;
      73             : 
      74           2 :         memcpy(&nextOid, rec, sizeof(Oid));
      75           2 :         appendStringInfo(buf, "%u", nextOid);
      76             :     }
      77          90 :     else if (info == XLOG_RESTORE_POINT)
      78             :     {
      79           0 :         xl_restore_point *xlrec = (xl_restore_point *) rec;
      80             : 
      81           0 :         appendStringInfoString(buf, xlrec->rp_name);
      82             :     }
      83          90 :     else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
      84             :     {
      85             :         /* no further information to print */
      86             :     }
      87          22 :     else if (info == XLOG_BACKUP_END)
      88             :     {
      89             :         XLogRecPtr  startpoint;
      90             : 
      91           4 :         memcpy(&startpoint, rec, sizeof(XLogRecPtr));
      92           4 :         appendStringInfo(buf, "%X/%X", LSN_FORMAT_ARGS(startpoint));
      93             :     }
      94          18 :     else if (info == XLOG_PARAMETER_CHANGE)
      95             :     {
      96             :         xl_parameter_change xlrec;
      97             :         const char *wal_level_str;
      98             :         const struct config_enum_entry *entry;
      99             : 
     100          12 :         memcpy(&xlrec, rec, sizeof(xl_parameter_change));
     101             : 
     102             :         /* Find a string representation for wal_level */
     103          12 :         wal_level_str = "?";
     104          20 :         for (entry = wal_level_options; entry->name; entry++)
     105             :         {
     106          20 :             if (entry->val == xlrec.wal_level)
     107             :             {
     108          12 :                 wal_level_str = entry->name;
     109          12 :                 break;
     110             :             }
     111             :         }
     112             : 
     113          24 :         appendStringInfo(buf, "max_connections=%d max_worker_processes=%d "
     114             :                          "max_wal_senders=%d max_prepared_xacts=%d "
     115             :                          "max_locks_per_xact=%d wal_level=%s "
     116             :                          "wal_log_hints=%s track_commit_timestamp=%s",
     117             :                          xlrec.MaxConnections,
     118             :                          xlrec.max_worker_processes,
     119             :                          xlrec.max_wal_senders,
     120             :                          xlrec.max_prepared_xacts,
     121             :                          xlrec.max_locks_per_xact,
     122             :                          wal_level_str,
     123          12 :                          xlrec.wal_log_hints ? "on" : "off",
     124          12 :                          xlrec.track_commit_timestamp ? "on" : "off");
     125             :     }
     126           6 :     else if (info == XLOG_FPW_CHANGE)
     127             :     {
     128             :         bool        fpw;
     129             : 
     130           0 :         memcpy(&fpw, rec, sizeof(bool));
     131           0 :         appendStringInfoString(buf, fpw ? "true" : "false");
     132             :     }
     133           6 :     else if (info == XLOG_END_OF_RECOVERY)
     134             :     {
     135             :         xl_end_of_recovery xlrec;
     136             : 
     137           0 :         memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
     138           0 :         appendStringInfo(buf, "tli %u; prev tli %u; time %s",
     139             :                          xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
     140             :                          timestamptz_to_str(xlrec.end_time));
     141             :     }
     142           6 :     else if (info == XLOG_OVERWRITE_CONTRECORD)
     143             :     {
     144             :         xl_overwrite_contrecord xlrec;
     145             : 
     146           2 :         memcpy(&xlrec, rec, sizeof(xl_overwrite_contrecord));
     147           2 :         appendStringInfo(buf, "lsn %X/%X; time %s",
     148           2 :                          LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
     149             :                          timestamptz_to_str(xlrec.overwrite_time));
     150             :     }
     151             :     else if (info == XLOG_CHECKPOINT_REDO)
     152             :     {
     153             :         /* No details to write out */
     154             :     }
     155          96 : }
     156             : 
     157             : const char *
     158          96 : xlog_identify(uint8 info)
     159             : {
     160          96 :     const char *id = NULL;
     161             : 
     162          96 :     switch (info & ~XLR_INFO_MASK)
     163             :     {
     164           4 :         case XLOG_CHECKPOINT_SHUTDOWN:
     165           4 :             id = "CHECKPOINT_SHUTDOWN";
     166           4 :             break;
     167           0 :         case XLOG_CHECKPOINT_ONLINE:
     168           0 :             id = "CHECKPOINT_ONLINE";
     169           0 :             break;
     170           0 :         case XLOG_NOOP:
     171           0 :             id = "NOOP";
     172           0 :             break;
     173           2 :         case XLOG_NEXTOID:
     174           2 :             id = "NEXTOID";
     175           2 :             break;
     176           2 :         case XLOG_SWITCH:
     177           2 :             id = "SWITCH";
     178           2 :             break;
     179           4 :         case XLOG_BACKUP_END:
     180           4 :             id = "BACKUP_END";
     181           4 :             break;
     182          12 :         case XLOG_PARAMETER_CHANGE:
     183          12 :             id = "PARAMETER_CHANGE";
     184          12 :             break;
     185           0 :         case XLOG_RESTORE_POINT:
     186           0 :             id = "RESTORE_POINT";
     187           0 :             break;
     188           0 :         case XLOG_FPW_CHANGE:
     189           0 :             id = "FPW_CHANGE";
     190           0 :             break;
     191           0 :         case XLOG_END_OF_RECOVERY:
     192           0 :             id = "END_OF_RECOVERY";
     193           0 :             break;
     194           2 :         case XLOG_OVERWRITE_CONTRECORD:
     195           2 :             id = "OVERWRITE_CONTRECORD";
     196           2 :             break;
     197          48 :         case XLOG_FPI:
     198          48 :             id = "FPI";
     199          48 :             break;
     200          20 :         case XLOG_FPI_FOR_HINT:
     201          20 :             id = "FPI_FOR_HINT";
     202          20 :             break;
     203           2 :         case XLOG_CHECKPOINT_REDO:
     204           2 :             id = "CHECKPOINT_REDO";
     205           2 :             break;
     206             :     }
     207             : 
     208          96 :     return id;
     209             : }
     210             : 
     211             : /*
     212             :  * Returns a string giving information about all the blocks in an
     213             :  * XLogRecord.
     214             :  */
     215             : void
     216       68628 : XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
     217             :                        bool detailed_format, StringInfo buf,
     218             :                        uint32 *fpi_len)
     219             : {
     220             :     int         block_id;
     221             : 
     222             :     Assert(record != NULL);
     223             : 
     224       68628 :     if (detailed_format && pretty)
     225           0 :         appendStringInfoChar(buf, '\n');
     226             : 
     227      141286 :     for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
     228             :     {
     229             :         RelFileLocator rlocator;
     230             :         ForkNumber  forknum;
     231             :         BlockNumber blk;
     232             : 
     233       72658 :         if (!XLogRecGetBlockTagExtended(record, block_id,
     234             :                                         &rlocator, &forknum, &blk, NULL))
     235           6 :             continue;
     236             : 
     237       72652 :         if (detailed_format)
     238             :         {
     239             :             /* Get block references in detailed format. */
     240             : 
     241       72652 :             if (pretty)
     242           0 :                 appendStringInfoChar(buf, '\t');
     243       72652 :             else if (block_id > 0)
     244        4024 :                 appendStringInfoChar(buf, ' ');
     245             : 
     246       72652 :             appendStringInfo(buf,
     247             :                              "blkref #%d: rel %u/%u/%u fork %s blk %u",
     248             :                              block_id,
     249             :                              rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
     250             :                              forkNames[forknum],
     251             :                              blk);
     252             : 
     253       72652 :             if (XLogRecHasBlockImage(record, block_id))
     254             :             {
     255       10516 :                 uint8       bimg_info = XLogRecGetBlock(record, block_id)->bimg_info;
     256             : 
     257             :                 /* Calculate the amount of FPI data in the record. */
     258       10516 :                 if (fpi_len)
     259       10516 :                     *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len;
     260             : 
     261       10516 :                 if (BKPIMAGE_COMPRESSED(bimg_info))
     262             :                 {
     263             :                     const char *method;
     264             : 
     265           0 :                     if ((bimg_info & BKPIMAGE_COMPRESS_PGLZ) != 0)
     266           0 :                         method = "pglz";
     267           0 :                     else if ((bimg_info & BKPIMAGE_COMPRESS_LZ4) != 0)
     268           0 :                         method = "lz4";
     269           0 :                     else if ((bimg_info & BKPIMAGE_COMPRESS_ZSTD) != 0)
     270           0 :                         method = "zstd";
     271             :                     else
     272           0 :                         method = "unknown";
     273             : 
     274           0 :                     appendStringInfo(buf,
     275             :                                      " (FPW%s); hole: offset: %u, length: %u, "
     276             :                                      "compression saved: %u, method: %s",
     277           0 :                                      XLogRecBlockImageApply(record, block_id) ?
     278             :                                      "" : " for WAL verification",
     279           0 :                                      XLogRecGetBlock(record, block_id)->hole_offset,
     280           0 :                                      XLogRecGetBlock(record, block_id)->hole_length,
     281             :                                      BLCKSZ -
     282           0 :                                      XLogRecGetBlock(record, block_id)->hole_length -
     283           0 :                                      XLogRecGetBlock(record, block_id)->bimg_len,
     284             :                                      method);
     285             :                 }
     286             :                 else
     287             :                 {
     288       10516 :                     appendStringInfo(buf,
     289             :                                      " (FPW%s); hole: offset: %u, length: %u",
     290       10516 :                                      XLogRecBlockImageApply(record, block_id) ?
     291             :                                      "" : " for WAL verification",
     292       10516 :                                      XLogRecGetBlock(record, block_id)->hole_offset,
     293       10516 :                                      XLogRecGetBlock(record, block_id)->hole_length);
     294             :                 }
     295             :             }
     296             : 
     297       72652 :             if (pretty)
     298           0 :                 appendStringInfoChar(buf, '\n');
     299             :         }
     300             :         else
     301             :         {
     302             :             /* Get block references in short format. */
     303             : 
     304           0 :             if (forknum != MAIN_FORKNUM)
     305             :             {
     306           0 :                 appendStringInfo(buf,
     307             :                                  ", blkref #%d: rel %u/%u/%u fork %s blk %u",
     308             :                                  block_id,
     309             :                                  rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
     310             :                                  forkNames[forknum],
     311             :                                  blk);
     312             :             }
     313             :             else
     314             :             {
     315           0 :                 appendStringInfo(buf,
     316             :                                  ", blkref #%d: rel %u/%u/%u blk %u",
     317             :                                  block_id,
     318             :                                  rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
     319             :                                  blk);
     320             :             }
     321             : 
     322           0 :             if (XLogRecHasBlockImage(record, block_id))
     323             :             {
     324             :                 /* Calculate the amount of FPI data in the record. */
     325           0 :                 if (fpi_len)
     326           0 :                     *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len;
     327             : 
     328           0 :                 if (XLogRecBlockImageApply(record, block_id))
     329           0 :                     appendStringInfoString(buf, " FPW");
     330             :                 else
     331           0 :                     appendStringInfoString(buf, " FPW for WAL verification");
     332             :             }
     333             :         }
     334             :     }
     335             : 
     336       68628 :     if (!detailed_format && pretty)
     337           0 :         appendStringInfoChar(buf, '\n');
     338       68628 : }

Generated by: LCOV version 1.14