LCOV - code coverage report
Current view: top level - src/backend/access/rmgrdesc - xactdesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 0 147 0.0 %
Date: 2017-09-29 15:12:54 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * xactdesc.c
       4             :  *    rmgr descriptor routines for access/transam/xact.c
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/access/rmgrdesc/xactdesc.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/transam.h"
      18             : #include "access/xact.h"
      19             : #include "catalog/catalog.h"
      20             : #include "storage/sinval.h"
      21             : #include "storage/standbydefs.h"
      22             : #include "utils/timestamp.h"
      23             : 
      24             : /*
      25             :  * Parse the WAL format of an xact commit and abort records into an easier to
      26             :  * understand format.
      27             :  *
      28             :  * This routines are in xactdesc.c because they're accessed in backend (when
      29             :  * replaying WAL) and frontend (pg_waldump) code. This file is the only xact
      30             :  * specific one shared between both. They're complicated enough that
      31             :  * duplication would be bothersome.
      32             :  */
      33             : 
      34             : void
      35           0 : ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
      36             : {
      37           0 :     char       *data = ((char *) xlrec) + MinSizeOfXactCommit;
      38             : 
      39           0 :     memset(parsed, 0, sizeof(*parsed));
      40             : 
      41           0 :     parsed->xinfo = 0;           /* default, if no XLOG_XACT_HAS_INFO is
      42             :                                  * present */
      43             : 
      44           0 :     parsed->xact_time = xlrec->xact_time;
      45             : 
      46           0 :     if (info & XLOG_XACT_HAS_INFO)
      47             :     {
      48           0 :         xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
      49             : 
      50           0 :         parsed->xinfo = xl_xinfo->xinfo;
      51             : 
      52           0 :         data += sizeof(xl_xact_xinfo);
      53             :     }
      54             : 
      55           0 :     if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
      56             :     {
      57           0 :         xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;
      58             : 
      59           0 :         parsed->dbId = xl_dbinfo->dbId;
      60           0 :         parsed->tsId = xl_dbinfo->tsId;
      61             : 
      62           0 :         data += sizeof(xl_xact_dbinfo);
      63             :     }
      64             : 
      65           0 :     if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
      66             :     {
      67           0 :         xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
      68             : 
      69           0 :         parsed->nsubxacts = xl_subxacts->nsubxacts;
      70           0 :         parsed->subxacts = xl_subxacts->subxacts;
      71             : 
      72           0 :         data += MinSizeOfXactSubxacts;
      73           0 :         data += parsed->nsubxacts * sizeof(TransactionId);
      74             :     }
      75             : 
      76           0 :     if (parsed->xinfo & XACT_XINFO_HAS_RELFILENODES)
      77             :     {
      78           0 :         xl_xact_relfilenodes *xl_relfilenodes = (xl_xact_relfilenodes *) data;
      79             : 
      80           0 :         parsed->nrels = xl_relfilenodes->nrels;
      81           0 :         parsed->xnodes = xl_relfilenodes->xnodes;
      82             : 
      83           0 :         data += MinSizeOfXactRelfilenodes;
      84           0 :         data += xl_relfilenodes->nrels * sizeof(RelFileNode);
      85             :     }
      86             : 
      87           0 :     if (parsed->xinfo & XACT_XINFO_HAS_INVALS)
      88             :     {
      89           0 :         xl_xact_invals *xl_invals = (xl_xact_invals *) data;
      90             : 
      91           0 :         parsed->nmsgs = xl_invals->nmsgs;
      92           0 :         parsed->msgs = xl_invals->msgs;
      93             : 
      94           0 :         data += MinSizeOfXactInvals;
      95           0 :         data += xl_invals->nmsgs * sizeof(SharedInvalidationMessage);
      96             :     }
      97             : 
      98           0 :     if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
      99             :     {
     100           0 :         xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
     101             : 
     102           0 :         parsed->twophase_xid = xl_twophase->xid;
     103             : 
     104           0 :         data += sizeof(xl_xact_twophase);
     105             :     }
     106             : 
     107           0 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
     108             :     {
     109             :         xl_xact_origin xl_origin;
     110             : 
     111             :         /* we're only guaranteed 4 byte alignment, so copy onto stack */
     112           0 :         memcpy(&xl_origin, data, sizeof(xl_origin));
     113             : 
     114           0 :         parsed->origin_lsn = xl_origin.origin_lsn;
     115           0 :         parsed->origin_timestamp = xl_origin.origin_timestamp;
     116             : 
     117           0 :         data += sizeof(xl_xact_origin);
     118             :     }
     119           0 : }
     120             : 
     121             : void
     122           0 : ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
     123             : {
     124           0 :     char       *data = ((char *) xlrec) + MinSizeOfXactAbort;
     125             : 
     126           0 :     memset(parsed, 0, sizeof(*parsed));
     127             : 
     128           0 :     parsed->xinfo = 0;           /* default, if no XLOG_XACT_HAS_INFO is
     129             :                                  * present */
     130             : 
     131           0 :     parsed->xact_time = xlrec->xact_time;
     132             : 
     133           0 :     if (info & XLOG_XACT_HAS_INFO)
     134             :     {
     135           0 :         xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
     136             : 
     137           0 :         parsed->xinfo = xl_xinfo->xinfo;
     138             : 
     139           0 :         data += sizeof(xl_xact_xinfo);
     140             :     }
     141             : 
     142           0 :     if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
     143             :     {
     144           0 :         xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
     145             : 
     146           0 :         parsed->nsubxacts = xl_subxacts->nsubxacts;
     147           0 :         parsed->subxacts = xl_subxacts->subxacts;
     148             : 
     149           0 :         data += MinSizeOfXactSubxacts;
     150           0 :         data += parsed->nsubxacts * sizeof(TransactionId);
     151             :     }
     152             : 
     153           0 :     if (parsed->xinfo & XACT_XINFO_HAS_RELFILENODES)
     154             :     {
     155           0 :         xl_xact_relfilenodes *xl_relfilenodes = (xl_xact_relfilenodes *) data;
     156             : 
     157           0 :         parsed->nrels = xl_relfilenodes->nrels;
     158           0 :         parsed->xnodes = xl_relfilenodes->xnodes;
     159             : 
     160           0 :         data += MinSizeOfXactRelfilenodes;
     161           0 :         data += xl_relfilenodes->nrels * sizeof(RelFileNode);
     162             :     }
     163             : 
     164           0 :     if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
     165             :     {
     166           0 :         xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
     167             : 
     168           0 :         parsed->twophase_xid = xl_twophase->xid;
     169             : 
     170           0 :         data += sizeof(xl_xact_twophase);
     171             :     }
     172           0 : }
     173             : 
     174             : static void
     175           0 : xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId origin_id)
     176             : {
     177             :     xl_xact_parsed_commit parsed;
     178             :     int         i;
     179             : 
     180           0 :     ParseCommitRecord(info, xlrec, &parsed);
     181             : 
     182             :     /* If this is a prepared xact, show the xid of the original xact */
     183           0 :     if (TransactionIdIsValid(parsed.twophase_xid))
     184           0 :         appendStringInfo(buf, "%u: ", parsed.twophase_xid);
     185             : 
     186           0 :     appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
     187             : 
     188           0 :     if (parsed.nrels > 0)
     189             :     {
     190           0 :         appendStringInfoString(buf, "; rels:");
     191           0 :         for (i = 0; i < parsed.nrels; i++)
     192             :         {
     193           0 :             char       *path = relpathperm(parsed.xnodes[i], MAIN_FORKNUM);
     194             : 
     195           0 :             appendStringInfo(buf, " %s", path);
     196           0 :             pfree(path);
     197             :         }
     198             :     }
     199           0 :     if (parsed.nsubxacts > 0)
     200             :     {
     201           0 :         appendStringInfoString(buf, "; subxacts:");
     202           0 :         for (i = 0; i < parsed.nsubxacts; i++)
     203           0 :             appendStringInfo(buf, " %u", parsed.subxacts[i]);
     204             :     }
     205           0 :     if (parsed.nmsgs > 0)
     206             :     {
     207           0 :         standby_desc_invalidations(
     208             :                                    buf, parsed.nmsgs, parsed.msgs, parsed.dbId, parsed.tsId,
     209           0 :                                    XactCompletionRelcacheInitFileInval(parsed.xinfo));
     210             :     }
     211             : 
     212           0 :     if (XactCompletionForceSyncCommit(parsed.xinfo))
     213           0 :         appendStringInfoString(buf, "; sync");
     214             : 
     215           0 :     if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
     216             :     {
     217           0 :         appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
     218             :                          origin_id,
     219           0 :                          (uint32) (parsed.origin_lsn >> 32),
     220           0 :                          (uint32) parsed.origin_lsn,
     221             :                          timestamptz_to_str(parsed.origin_timestamp));
     222             :     }
     223           0 : }
     224             : 
     225             : static void
     226           0 : xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec)
     227             : {
     228             :     xl_xact_parsed_abort parsed;
     229             :     int         i;
     230             : 
     231           0 :     ParseAbortRecord(info, xlrec, &parsed);
     232             : 
     233             :     /* If this is a prepared xact, show the xid of the original xact */
     234           0 :     if (TransactionIdIsValid(parsed.twophase_xid))
     235           0 :         appendStringInfo(buf, "%u: ", parsed.twophase_xid);
     236             : 
     237           0 :     appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
     238           0 :     if (parsed.nrels > 0)
     239             :     {
     240           0 :         appendStringInfoString(buf, "; rels:");
     241           0 :         for (i = 0; i < parsed.nrels; i++)
     242             :         {
     243           0 :             char       *path = relpathperm(parsed.xnodes[i], MAIN_FORKNUM);
     244             : 
     245           0 :             appendStringInfo(buf, " %s", path);
     246           0 :             pfree(path);
     247             :         }
     248             :     }
     249             : 
     250           0 :     if (parsed.nsubxacts > 0)
     251             :     {
     252           0 :         appendStringInfoString(buf, "; subxacts:");
     253           0 :         for (i = 0; i < parsed.nsubxacts; i++)
     254           0 :             appendStringInfo(buf, " %u", parsed.subxacts[i]);
     255             :     }
     256           0 : }
     257             : 
     258             : static void
     259           0 : xact_desc_assignment(StringInfo buf, xl_xact_assignment *xlrec)
     260             : {
     261             :     int         i;
     262             : 
     263           0 :     appendStringInfoString(buf, "subxacts:");
     264             : 
     265           0 :     for (i = 0; i < xlrec->nsubxacts; i++)
     266           0 :         appendStringInfo(buf, " %u", xlrec->xsub[i]);
     267           0 : }
     268             : 
     269             : void
     270           0 : xact_desc(StringInfo buf, XLogReaderState *record)
     271             : {
     272           0 :     char       *rec = XLogRecGetData(record);
     273           0 :     uint8       info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
     274             : 
     275           0 :     if (info == XLOG_XACT_COMMIT || info == XLOG_XACT_COMMIT_PREPARED)
     276           0 :     {
     277           0 :         xl_xact_commit *xlrec = (xl_xact_commit *) rec;
     278             : 
     279           0 :         xact_desc_commit(buf, XLogRecGetInfo(record), xlrec,
     280           0 :                          XLogRecGetOrigin(record));
     281             :     }
     282           0 :     else if (info == XLOG_XACT_ABORT || info == XLOG_XACT_ABORT_PREPARED)
     283           0 :     {
     284           0 :         xl_xact_abort *xlrec = (xl_xact_abort *) rec;
     285             : 
     286           0 :         xact_desc_abort(buf, XLogRecGetInfo(record), xlrec);
     287             :     }
     288           0 :     else if (info == XLOG_XACT_ASSIGNMENT)
     289             :     {
     290           0 :         xl_xact_assignment *xlrec = (xl_xact_assignment *) rec;
     291             : 
     292             :         /*
     293             :          * Note that we ignore the WAL record's xid, since we're more
     294             :          * interested in the top-level xid that issued the record and which
     295             :          * xids are being reported here.
     296             :          */
     297           0 :         appendStringInfo(buf, "xtop %u: ", xlrec->xtop);
     298           0 :         xact_desc_assignment(buf, xlrec);
     299             :     }
     300           0 : }
     301             : 
     302             : const char *
     303           0 : xact_identify(uint8 info)
     304             : {
     305           0 :     const char *id = NULL;
     306             : 
     307           0 :     switch (info & XLOG_XACT_OPMASK)
     308             :     {
     309             :         case XLOG_XACT_COMMIT:
     310           0 :             id = "COMMIT";
     311           0 :             break;
     312             :         case XLOG_XACT_PREPARE:
     313           0 :             id = "PREPARE";
     314           0 :             break;
     315             :         case XLOG_XACT_ABORT:
     316           0 :             id = "ABORT";
     317           0 :             break;
     318             :         case XLOG_XACT_COMMIT_PREPARED:
     319           0 :             id = "COMMIT_PREPARED";
     320           0 :             break;
     321             :         case XLOG_XACT_ABORT_PREPARED:
     322           0 :             id = "ABORT_PREPARED";
     323           0 :             break;
     324             :         case XLOG_XACT_ASSIGNMENT:
     325           0 :             id = "ASSIGNMENT";
     326           0 :             break;
     327             :     }
     328             : 
     329           0 :     return id;
     330             : }

Generated by: LCOV version 1.11