LCOV - code coverage report
Current view: top level - src/bin/pg_waldump - gindesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 49 130 37.7 %
Date: 2025-10-10 18:17:38 Functions: 2 3 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * gindesc.c
       4             :  *    rmgr descriptor routines for access/transam/gin/ginxlog.c
       5             :  *
       6             :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/access/rmgrdesc/gindesc.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/ginxlog.h"
      18             : #include "lib/stringinfo.h"
      19             : 
      20             : static void
      21           0 : desc_recompress_leaf(StringInfo buf, ginxlogRecompressDataLeaf *insertData)
      22             : {
      23             :     int         i;
      24           0 :     char       *walbuf = ((char *) insertData) + sizeof(ginxlogRecompressDataLeaf);
      25             : 
      26           0 :     appendStringInfo(buf, " %d segments:", (int) insertData->nactions);
      27             : 
      28           0 :     for (i = 0; i < insertData->nactions; i++)
      29             :     {
      30           0 :         uint8       a_segno = *((uint8 *) (walbuf++));
      31           0 :         uint8       a_action = *((uint8 *) (walbuf++));
      32           0 :         uint16      nitems = 0;
      33           0 :         int         newsegsize = 0;
      34             : 
      35           0 :         if (a_action == GIN_SEGMENT_INSERT ||
      36             :             a_action == GIN_SEGMENT_REPLACE)
      37             :         {
      38           0 :             newsegsize = SizeOfGinPostingList((GinPostingList *) walbuf);
      39           0 :             walbuf += SHORTALIGN(newsegsize);
      40             :         }
      41             : 
      42           0 :         if (a_action == GIN_SEGMENT_ADDITEMS)
      43             :         {
      44           0 :             memcpy(&nitems, walbuf, sizeof(uint16));
      45           0 :             walbuf += sizeof(uint16);
      46           0 :             walbuf += nitems * sizeof(ItemPointerData);
      47             :         }
      48             : 
      49           0 :         switch (a_action)
      50             :         {
      51           0 :             case GIN_SEGMENT_ADDITEMS:
      52           0 :                 appendStringInfo(buf, " %d (add %d items)", a_segno, nitems);
      53           0 :                 break;
      54           0 :             case GIN_SEGMENT_DELETE:
      55           0 :                 appendStringInfo(buf, " %d (delete)", a_segno);
      56           0 :                 break;
      57           0 :             case GIN_SEGMENT_INSERT:
      58           0 :                 appendStringInfo(buf, " %d (insert)", a_segno);
      59           0 :                 break;
      60           0 :             case GIN_SEGMENT_REPLACE:
      61           0 :                 appendStringInfo(buf, " %d (replace)", a_segno);
      62           0 :                 break;
      63           0 :             default:
      64           0 :                 appendStringInfo(buf, " %d unknown action %d ???", a_segno, a_action);
      65             :                 /* cannot decode unrecognized actions further */
      66           0 :                 return;
      67             :         }
      68             :     }
      69             : }
      70             : 
      71             : void
      72        6192 : gin_desc(StringInfo buf, XLogReaderState *record)
      73             : {
      74        6192 :     char       *rec = XLogRecGetData(record);
      75        6192 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
      76             : 
      77        6192 :     switch (info)
      78             :     {
      79           0 :         case XLOG_GIN_CREATE_PTREE:
      80             :             /* no further information */
      81           0 :             break;
      82          72 :         case XLOG_GIN_INSERT:
      83             :             {
      84          72 :                 ginxlogInsert *xlrec = (ginxlogInsert *) rec;
      85             : 
      86         144 :                 appendStringInfo(buf, "isdata: %c isleaf: %c",
      87          72 :                                  (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
      88          72 :                                  (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
      89          72 :                 if (!(xlrec->flags & GIN_INSERT_ISLEAF))
      90             :                 {
      91           0 :                     char       *payload = rec + sizeof(ginxlogInsert);
      92             :                     BlockNumber leftChildBlkno;
      93             :                     BlockNumber rightChildBlkno;
      94             : 
      95           0 :                     leftChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
      96           0 :                     payload += sizeof(BlockIdData);
      97           0 :                     rightChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
      98           0 :                     payload += sizeof(BlockNumber);
      99           0 :                     appendStringInfo(buf, " children: %u/%u",
     100             :                                      leftChildBlkno, rightChildBlkno);
     101             :                 }
     102          72 :                 if (!XLogRecHasBlockImage(record, 0))
     103             :                 {
     104          72 :                     char       *payload = XLogRecGetBlockData(record, 0, NULL);
     105             : 
     106          72 :                     if (!(xlrec->flags & GIN_INSERT_ISDATA))
     107          72 :                         appendStringInfo(buf, " isdelete: %c",
     108          72 :                                          (((ginxlogInsertEntry *) payload)->isDelete) ? 'T' : 'F');
     109           0 :                     else if (xlrec->flags & GIN_INSERT_ISLEAF)
     110           0 :                         desc_recompress_leaf(buf, (ginxlogRecompressDataLeaf *) payload);
     111             :                     else
     112             :                     {
     113           0 :                         ginxlogInsertDataInternal *insertData =
     114             :                             (ginxlogInsertDataInternal *) payload;
     115             : 
     116           0 :                         appendStringInfo(buf, " pitem: %u-%u/%u",
     117           0 :                                          PostingItemGetBlockNumber(&insertData->newitem),
     118           0 :                                          ItemPointerGetBlockNumber(&insertData->newitem.key),
     119           0 :                                          ItemPointerGetOffsetNumber(&insertData->newitem.key));
     120             :                     }
     121             :                 }
     122             :             }
     123          72 :             break;
     124           0 :         case XLOG_GIN_SPLIT:
     125             :             {
     126           0 :                 ginxlogSplit *xlrec = (ginxlogSplit *) rec;
     127             : 
     128           0 :                 appendStringInfo(buf, "isrootsplit: %c",
     129           0 :                                  (((ginxlogSplit *) rec)->flags & GIN_SPLIT_ROOT) ? 'T' : 'F');
     130           0 :                 appendStringInfo(buf, " isdata: %c isleaf: %c",
     131           0 :                                  (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
     132           0 :                                  (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
     133           0 :                 if (xlrec->leftChildBlkno != InvalidBlockNumber)
     134           0 :                     appendStringInfo(buf, " children: %u/%u",
     135             :                                      xlrec->leftChildBlkno, xlrec->rightChildBlkno);
     136             :             }
     137           0 :             break;
     138           0 :         case XLOG_GIN_VACUUM_PAGE:
     139             :             /* no further information */
     140           0 :             break;
     141           0 :         case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
     142             :             {
     143           0 :                 if (!XLogRecHasBlockImage(record, 0))
     144             :                 {
     145             :                     ginxlogVacuumDataLeafPage *xlrec =
     146           0 :                         (ginxlogVacuumDataLeafPage *) XLogRecGetBlockData(record, 0, NULL);
     147             : 
     148           0 :                     desc_recompress_leaf(buf, &xlrec->data);
     149             :                 }
     150             :             }
     151           0 :             break;
     152           0 :         case XLOG_GIN_DELETE_PAGE:
     153             :             /* no further information */
     154           0 :             break;
     155        6012 :         case XLOG_GIN_UPDATE_META_PAGE:
     156             :             {
     157        6012 :                 ginxlogUpdateMeta *xlrec = (ginxlogUpdateMeta *) rec;
     158             : 
     159        6012 :                 appendStringInfo(buf, "ntuples: %d", xlrec->ntuples);
     160        6012 :                 if (xlrec->prevTail != InvalidBlockNumber)
     161          84 :                     appendStringInfo(buf, " prevTail: %u",
     162             :                                      xlrec->prevTail);
     163        6012 :                 if (xlrec->newRightlink != InvalidBlockNumber)
     164          84 :                     appendStringInfo(buf, " newRightLink: %u",
     165             :                                      xlrec->newRightlink);
     166             :             }
     167        6012 :             break;
     168          96 :         case XLOG_GIN_INSERT_LISTPAGE:
     169             :             {
     170          96 :                 ginxlogInsertListPage *xlrec = (ginxlogInsertListPage *) rec;
     171             : 
     172          96 :                 appendStringInfo(buf, "ntuples: %d", xlrec->ntuples);
     173          96 :                 if (xlrec->rightlink != InvalidBlockNumber)
     174           0 :                     appendStringInfo(buf, " rightlink: %u",
     175             :                                      xlrec->rightlink);
     176             :             }
     177          96 :             break;
     178          12 :         case XLOG_GIN_DELETE_LISTPAGE:
     179          12 :             appendStringInfo(buf, "ndeleted: %d",
     180             :                              ((ginxlogDeleteListPages *) rec)->ndeleted);
     181          12 :             break;
     182             :     }
     183        6192 : }
     184             : 
     185             : const char *
     186        6200 : gin_identify(uint8 info)
     187             : {
     188        6200 :     const char *id = NULL;
     189             : 
     190        6200 :     switch (info & ~XLR_INFO_MASK)
     191             :     {
     192           0 :         case XLOG_GIN_CREATE_PTREE:
     193           0 :             id = "CREATE_PTREE";
     194           0 :             break;
     195          74 :         case XLOG_GIN_INSERT:
     196          74 :             id = "INSERT";
     197          74 :             break;
     198           0 :         case XLOG_GIN_SPLIT:
     199           0 :             id = "SPLIT";
     200           0 :             break;
     201           0 :         case XLOG_GIN_VACUUM_PAGE:
     202           0 :             id = "VACUUM_PAGE";
     203           0 :             break;
     204           0 :         case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
     205           0 :             id = "VACUUM_DATA_LEAF_PAGE";
     206           0 :             break;
     207           0 :         case XLOG_GIN_DELETE_PAGE:
     208           0 :             id = "DELETE_PAGE";
     209           0 :             break;
     210        6014 :         case XLOG_GIN_UPDATE_META_PAGE:
     211        6014 :             id = "UPDATE_META_PAGE";
     212        6014 :             break;
     213          98 :         case XLOG_GIN_INSERT_LISTPAGE:
     214          98 :             id = "INSERT_LISTPAGE";
     215          98 :             break;
     216          14 :         case XLOG_GIN_DELETE_LISTPAGE:
     217          14 :             id = "DELETE_LISTPAGE";
     218          14 :             break;
     219             :     }
     220             : 
     221        6200 :     return id;
     222             : }

Generated by: LCOV version 1.16