LCOV - code coverage report
Current view: top level - src/backend/access/rmgrdesc - heapdesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 145 221 65.6 %
Date: 2023-12-05 08:11:01 Functions: 5 7 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * heapdesc.c
       4             :  *    rmgr descriptor routines for access/heap/heapam.c
       5             :  *
       6             :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/access/rmgrdesc/heapdesc.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/heapam_xlog.h"
      18             : #include "access/rmgrdesc_utils.h"
      19             : 
      20             : /*
      21             :  * NOTE: "keyname" argument cannot have trailing spaces or punctuation
      22             :  * characters
      23             :  */
      24             : static void
      25          96 : infobits_desc(StringInfo buf, uint8 infobits, const char *keyname)
      26             : {
      27          96 :     appendStringInfo(buf, "%s: [", keyname);
      28             : 
      29             :     Assert(buf->data[buf->len - 1] != ' ');
      30             : 
      31          96 :     if (infobits & XLHL_XMAX_IS_MULTI)
      32           0 :         appendStringInfoString(buf, "IS_MULTI, ");
      33          96 :     if (infobits & XLHL_XMAX_LOCK_ONLY)
      34          12 :         appendStringInfoString(buf, "LOCK_ONLY, ");
      35          96 :     if (infobits & XLHL_XMAX_EXCL_LOCK)
      36          12 :         appendStringInfoString(buf, "EXCL_LOCK, ");
      37          96 :     if (infobits & XLHL_XMAX_KEYSHR_LOCK)
      38           0 :         appendStringInfoString(buf, "KEYSHR_LOCK, ");
      39          96 :     if (infobits & XLHL_KEYS_UPDATED)
      40          40 :         appendStringInfoString(buf, "KEYS_UPDATED, ");
      41             : 
      42          96 :     if (buf->data[buf->len - 1] == ' ')
      43             :     {
      44             :         /* Truncate-away final unneeded ", "  */
      45             :         Assert(buf->data[buf->len - 2] == ',');
      46          52 :         buf->len -= 2;
      47          52 :         buf->data[buf->len] = '\0';
      48             :     }
      49             : 
      50          96 :     appendStringInfoChar(buf, ']');
      51          96 : }
      52             : 
      53             : static void
      54           0 : truncate_flags_desc(StringInfo buf, uint8 flags)
      55             : {
      56           0 :     appendStringInfoString(buf, "flags: [");
      57             : 
      58           0 :     if (flags & XLH_TRUNCATE_CASCADE)
      59           0 :         appendStringInfoString(buf, "CASCADE, ");
      60           0 :     if (flags & XLH_TRUNCATE_RESTART_SEQS)
      61           0 :         appendStringInfoString(buf, "RESTART_SEQS, ");
      62             : 
      63           0 :     if (buf->data[buf->len - 1] == ' ')
      64             :     {
      65             :         /* Truncate-away final unneeded ", "  */
      66             :         Assert(buf->data[buf->len - 2] == ',');
      67           0 :         buf->len -= 2;
      68           0 :         buf->data[buf->len] = '\0';
      69             :     }
      70             : 
      71           0 :     appendStringInfoChar(buf, ']');
      72           0 : }
      73             : 
      74             : static void
      75           0 : plan_elem_desc(StringInfo buf, void *plan, void *data)
      76             : {
      77           0 :     xl_heap_freeze_plan *new_plan = (xl_heap_freeze_plan *) plan;
      78           0 :     OffsetNumber **offsets = data;
      79             : 
      80           0 :     appendStringInfo(buf, "{ xmax: %u, infomask: %u, infomask2: %u, ntuples: %u",
      81             :                      new_plan->xmax,
      82           0 :                      new_plan->t_infomask, new_plan->t_infomask2,
      83           0 :                      new_plan->ntuples);
      84             : 
      85           0 :     appendStringInfoString(buf, ", offsets:");
      86           0 :     array_desc(buf, *offsets, sizeof(OffsetNumber), new_plan->ntuples,
      87             :                &offset_elem_desc, NULL);
      88             : 
      89           0 :     *offsets += new_plan->ntuples;
      90             : 
      91           0 :     appendStringInfoString(buf, " }");
      92           0 : }
      93             : 
      94             : void
      95       61898 : heap_desc(StringInfo buf, XLogReaderState *record)
      96             : {
      97       61898 :     char       *rec = XLogRecGetData(record);
      98       61898 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
      99             : 
     100       61898 :     info &= XLOG_HEAP_OPMASK;
     101       61898 :     if (info == XLOG_HEAP_INSERT)
     102             :     {
     103       61798 :         xl_heap_insert *xlrec = (xl_heap_insert *) rec;
     104             : 
     105       61798 :         appendStringInfo(buf, "off: %u, flags: 0x%02X",
     106       61798 :                          xlrec->offnum,
     107       61798 :                          xlrec->flags);
     108             :     }
     109         100 :     else if (info == XLOG_HEAP_DELETE)
     110             :     {
     111          40 :         xl_heap_delete *xlrec = (xl_heap_delete *) rec;
     112             : 
     113          40 :         appendStringInfo(buf, "xmax: %u, off: %u, ",
     114          40 :                          xlrec->xmax, xlrec->offnum);
     115          40 :         infobits_desc(buf, xlrec->infobits_set, "infobits");
     116          40 :         appendStringInfo(buf, ", flags: 0x%02X", xlrec->flags);
     117             :     }
     118          60 :     else if (info == XLOG_HEAP_UPDATE)
     119             :     {
     120          12 :         xl_heap_update *xlrec = (xl_heap_update *) rec;
     121             : 
     122          12 :         appendStringInfo(buf, "old_xmax: %u, old_off: %u, ",
     123          12 :                          xlrec->old_xmax, xlrec->old_offnum);
     124          12 :         infobits_desc(buf, xlrec->old_infobits_set, "old_infobits");
     125          12 :         appendStringInfo(buf, ", flags: 0x%02X, new_xmax: %u, new_off: %u",
     126          12 :                          xlrec->flags, xlrec->new_xmax, xlrec->new_offnum);
     127             :     }
     128          48 :     else if (info == XLOG_HEAP_HOT_UPDATE)
     129             :     {
     130          32 :         xl_heap_update *xlrec = (xl_heap_update *) rec;
     131             : 
     132          32 :         appendStringInfo(buf, "old_xmax: %u, old_off: %u, ",
     133          32 :                          xlrec->old_xmax, xlrec->old_offnum);
     134          32 :         infobits_desc(buf, xlrec->old_infobits_set, "old_infobits");
     135          32 :         appendStringInfo(buf, ", flags: 0x%02X, new_xmax: %u, new_off: %u",
     136          32 :                          xlrec->flags, xlrec->new_xmax, xlrec->new_offnum);
     137             :     }
     138          16 :     else if (info == XLOG_HEAP_TRUNCATE)
     139             :     {
     140           0 :         xl_heap_truncate *xlrec = (xl_heap_truncate *) rec;
     141             : 
     142           0 :         truncate_flags_desc(buf, xlrec->flags);
     143           0 :         appendStringInfo(buf, ", nrelids: %u", xlrec->nrelids);
     144           0 :         appendStringInfoString(buf, ", relids:");
     145           0 :         array_desc(buf, xlrec->relids, sizeof(Oid), xlrec->nrelids,
     146             :                    &oid_elem_desc, NULL);
     147             :     }
     148          16 :     else if (info == XLOG_HEAP_CONFIRM)
     149             :     {
     150           0 :         xl_heap_confirm *xlrec = (xl_heap_confirm *) rec;
     151             : 
     152           0 :         appendStringInfo(buf, "off: %u", xlrec->offnum);
     153             :     }
     154          16 :     else if (info == XLOG_HEAP_LOCK)
     155             :     {
     156          12 :         xl_heap_lock *xlrec = (xl_heap_lock *) rec;
     157             : 
     158          12 :         appendStringInfo(buf, "xmax: %u, off: %u, ",
     159          12 :                          xlrec->xmax, xlrec->offnum);
     160          12 :         infobits_desc(buf, xlrec->infobits_set, "infobits");
     161          12 :         appendStringInfo(buf, ", flags: 0x%02X", xlrec->flags);
     162             :     }
     163           4 :     else if (info == XLOG_HEAP_INPLACE)
     164             :     {
     165           4 :         xl_heap_inplace *xlrec = (xl_heap_inplace *) rec;
     166             : 
     167           4 :         appendStringInfo(buf, "off: %u", xlrec->offnum);
     168             :     }
     169       61898 : }
     170             : 
     171             : void
     172         128 : heap2_desc(StringInfo buf, XLogReaderState *record)
     173             : {
     174         128 :     char       *rec = XLogRecGetData(record);
     175         128 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
     176             : 
     177         128 :     info &= XLOG_HEAP_OPMASK;
     178         128 :     if (info == XLOG_HEAP2_PRUNE)
     179             :     {
     180          80 :         xl_heap_prune *xlrec = (xl_heap_prune *) rec;
     181             : 
     182          80 :         appendStringInfo(buf, "snapshotConflictHorizon: %u, nredirected: %u, ndead: %u",
     183             :                          xlrec->snapshotConflictHorizon,
     184          80 :                          xlrec->nredirected,
     185          80 :                          xlrec->ndead);
     186             : 
     187          80 :         if (XLogRecHasBlockData(record, 0))
     188             :         {
     189             :             OffsetNumber *end;
     190             :             OffsetNumber *redirected;
     191             :             OffsetNumber *nowdead;
     192             :             OffsetNumber *nowunused;
     193             :             int         nredirected;
     194             :             int         nunused;
     195             :             Size        datalen;
     196             : 
     197          80 :             redirected = (OffsetNumber *) XLogRecGetBlockData(record, 0,
     198             :                                                               &datalen);
     199             : 
     200          80 :             nredirected = xlrec->nredirected;
     201          80 :             end = (OffsetNumber *) ((char *) redirected + datalen);
     202          80 :             nowdead = redirected + (nredirected * 2);
     203          80 :             nowunused = nowdead + xlrec->ndead;
     204          80 :             nunused = (end - nowunused);
     205             :             Assert(nunused >= 0);
     206             : 
     207          80 :             appendStringInfo(buf, ", nunused: %d", nunused);
     208             : 
     209          80 :             appendStringInfoString(buf, ", redirected:");
     210          80 :             array_desc(buf, redirected, sizeof(OffsetNumber) * 2,
     211             :                        nredirected, &redirect_elem_desc, NULL);
     212          80 :             appendStringInfoString(buf, ", dead:");
     213          80 :             array_desc(buf, nowdead, sizeof(OffsetNumber), xlrec->ndead,
     214             :                        &offset_elem_desc, NULL);
     215          80 :             appendStringInfoString(buf, ", unused:");
     216          80 :             array_desc(buf, nowunused, sizeof(OffsetNumber), nunused,
     217             :                        &offset_elem_desc, NULL);
     218             :         }
     219             :     }
     220          48 :     else if (info == XLOG_HEAP2_VACUUM)
     221             :     {
     222           4 :         xl_heap_vacuum *xlrec = (xl_heap_vacuum *) rec;
     223             : 
     224           4 :         appendStringInfo(buf, "nunused: %u", xlrec->nunused);
     225             : 
     226           4 :         if (XLogRecHasBlockData(record, 0))
     227             :         {
     228             :             OffsetNumber *nowunused;
     229             : 
     230           4 :             nowunused = (OffsetNumber *) XLogRecGetBlockData(record, 0, NULL);
     231             : 
     232           4 :             appendStringInfoString(buf, ", unused:");
     233           4 :             array_desc(buf, nowunused, sizeof(OffsetNumber), xlrec->nunused,
     234             :                        &offset_elem_desc, NULL);
     235             :         }
     236             :     }
     237          44 :     else if (info == XLOG_HEAP2_FREEZE_PAGE)
     238             :     {
     239           0 :         xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec;
     240             : 
     241           0 :         appendStringInfo(buf, "snapshotConflictHorizon: %u, nplans: %u",
     242           0 :                          xlrec->snapshotConflictHorizon, xlrec->nplans);
     243             : 
     244           0 :         if (XLogRecHasBlockData(record, 0))
     245             :         {
     246             :             xl_heap_freeze_plan *plans;
     247             :             OffsetNumber *offsets;
     248             : 
     249           0 :             plans = (xl_heap_freeze_plan *) XLogRecGetBlockData(record, 0, NULL);
     250           0 :             offsets = (OffsetNumber *) ((char *) plans +
     251           0 :                                         (xlrec->nplans *
     252             :                                          sizeof(xl_heap_freeze_plan)));
     253           0 :             appendStringInfoString(buf, ", plans:");
     254           0 :             array_desc(buf, plans, sizeof(xl_heap_freeze_plan), xlrec->nplans,
     255             :                        &plan_elem_desc, &offsets);
     256             :         }
     257             :     }
     258          44 :     else if (info == XLOG_HEAP2_VISIBLE)
     259             :     {
     260           4 :         xl_heap_visible *xlrec = (xl_heap_visible *) rec;
     261             : 
     262           4 :         appendStringInfo(buf, "snapshotConflictHorizon: %u, flags: 0x%02X",
     263           4 :                          xlrec->snapshotConflictHorizon, xlrec->flags);
     264             :     }
     265          40 :     else if (info == XLOG_HEAP2_MULTI_INSERT)
     266             :     {
     267          40 :         xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec;
     268          40 :         bool        isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0;
     269             : 
     270          40 :         appendStringInfo(buf, "ntuples: %d, flags: 0x%02X", xlrec->ntuples,
     271          40 :                          xlrec->flags);
     272             : 
     273          40 :         if (XLogRecHasBlockData(record, 0) && !isinit)
     274             :         {
     275          34 :             appendStringInfoString(buf, ", offsets:");
     276          34 :             array_desc(buf, xlrec->offsets, sizeof(OffsetNumber),
     277          34 :                        xlrec->ntuples, &offset_elem_desc, NULL);
     278             :         }
     279             :     }
     280           0 :     else if (info == XLOG_HEAP2_LOCK_UPDATED)
     281             :     {
     282           0 :         xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec;
     283             : 
     284           0 :         appendStringInfo(buf, "xmax: %u, off: %u, ",
     285           0 :                          xlrec->xmax, xlrec->offnum);
     286           0 :         infobits_desc(buf, xlrec->infobits_set, "infobits");
     287           0 :         appendStringInfo(buf, ", flags: 0x%02X", xlrec->flags);
     288             :     }
     289           0 :     else if (info == XLOG_HEAP2_NEW_CID)
     290             :     {
     291           0 :         xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec;
     292             : 
     293           0 :         appendStringInfo(buf, "rel: %u/%u/%u, tid: %u/%u",
     294             :                          xlrec->target_locator.spcOid,
     295             :                          xlrec->target_locator.dbOid,
     296             :                          xlrec->target_locator.relNumber,
     297           0 :                          ItemPointerGetBlockNumber(&(xlrec->target_tid)),
     298           0 :                          ItemPointerGetOffsetNumber(&(xlrec->target_tid)));
     299           0 :         appendStringInfo(buf, ", cmin: %u, cmax: %u, combo: %u",
     300             :                          xlrec->cmin, xlrec->cmax, xlrec->combocid);
     301             :     }
     302         128 : }
     303             : 
     304             : const char *
     305       61898 : heap_identify(uint8 info)
     306             : {
     307       61898 :     const char *id = NULL;
     308             : 
     309       61898 :     switch (info & ~XLR_INFO_MASK)
     310             :     {
     311       58976 :         case XLOG_HEAP_INSERT:
     312       58976 :             id = "INSERT";
     313       58976 :             break;
     314        2822 :         case XLOG_HEAP_INSERT | XLOG_HEAP_INIT_PAGE:
     315        2822 :             id = "INSERT+INIT";
     316        2822 :             break;
     317          40 :         case XLOG_HEAP_DELETE:
     318          40 :             id = "DELETE";
     319          40 :             break;
     320          10 :         case XLOG_HEAP_UPDATE:
     321          10 :             id = "UPDATE";
     322          10 :             break;
     323           2 :         case XLOG_HEAP_UPDATE | XLOG_HEAP_INIT_PAGE:
     324           2 :             id = "UPDATE+INIT";
     325           2 :             break;
     326          32 :         case XLOG_HEAP_HOT_UPDATE:
     327          32 :             id = "HOT_UPDATE";
     328          32 :             break;
     329           0 :         case XLOG_HEAP_HOT_UPDATE | XLOG_HEAP_INIT_PAGE:
     330           0 :             id = "HOT_UPDATE+INIT";
     331           0 :             break;
     332           0 :         case XLOG_HEAP_TRUNCATE:
     333           0 :             id = "TRUNCATE";
     334           0 :             break;
     335           0 :         case XLOG_HEAP_CONFIRM:
     336           0 :             id = "HEAP_CONFIRM";
     337           0 :             break;
     338          12 :         case XLOG_HEAP_LOCK:
     339          12 :             id = "LOCK";
     340          12 :             break;
     341           4 :         case XLOG_HEAP_INPLACE:
     342           4 :             id = "INPLACE";
     343           4 :             break;
     344             :     }
     345             : 
     346       61898 :     return id;
     347             : }
     348             : 
     349             : const char *
     350         128 : heap2_identify(uint8 info)
     351             : {
     352         128 :     const char *id = NULL;
     353             : 
     354         128 :     switch (info & ~XLR_INFO_MASK)
     355             :     {
     356          80 :         case XLOG_HEAP2_PRUNE:
     357          80 :             id = "PRUNE";
     358          80 :             break;
     359           4 :         case XLOG_HEAP2_VACUUM:
     360           4 :             id = "VACUUM";
     361           4 :             break;
     362           0 :         case XLOG_HEAP2_FREEZE_PAGE:
     363           0 :             id = "FREEZE_PAGE";
     364           0 :             break;
     365           4 :         case XLOG_HEAP2_VISIBLE:
     366           4 :             id = "VISIBLE";
     367           4 :             break;
     368          40 :         case XLOG_HEAP2_MULTI_INSERT:
     369          40 :             id = "MULTI_INSERT";
     370          40 :             break;
     371           0 :         case XLOG_HEAP2_MULTI_INSERT | XLOG_HEAP_INIT_PAGE:
     372           0 :             id = "MULTI_INSERT+INIT";
     373           0 :             break;
     374           0 :         case XLOG_HEAP2_LOCK_UPDATED:
     375           0 :             id = "LOCK_UPDATED";
     376           0 :             break;
     377           0 :         case XLOG_HEAP2_NEW_CID:
     378           0 :             id = "NEW_CID";
     379           0 :             break;
     380           0 :         case XLOG_HEAP2_REWRITE:
     381           0 :             id = "REWRITE";
     382           0 :             break;
     383             :     }
     384             : 
     385         128 :     return id;
     386             : }

Generated by: LCOV version 1.14