Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  xactdesc.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * xactdesc.c
 *   rmgr descriptor routines for access/transam/xact.c
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *   src/backend/access/rmgrdesc/xactdesc.c
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "access/transam.h"
#include "access/xact.h"
#include "replication/origin.h"
#include "storage/sinval.h"
#include "storage/standbydefs.h"
#include "utils/timestamp.h"

/*
 * Parse the WAL format of an xact commit and abort records into an easier to
 * understand format.
 *
 * These routines are in xactdesc.c because they're accessed in backend (when
 * replaying WAL) and frontend (pg_waldump) code. This file is the only xact
 * specific one shared between both. They're complicated enough that
 * duplication would be bothersome.
 */


void
ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
{
 char    *data = ((char *) xlrec) + MinSizeOfXactCommit;

 memset(parsed, 0sizeof(*parsed));

 parsed->xinfo = 0;   /* default, if no XLOG_XACT_HAS_INFO is
 * present */


 parsed->xact_time = xlrec->xact_time;

 if (info & XLOG_XACT_HAS_INFO)
 {
  xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;

  parsed->xinfo = xl_xinfo->xinfo;

  data += sizeof(xl_xact_xinfo);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
 {
  xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;

  parsed->dbId = xl_dbinfo->dbId;
  parsed->tsId = xl_dbinfo->tsId;

  data += sizeof(xl_xact_dbinfo);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
 {
  xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;

  parsed->nsubxacts = xl_subxacts->nsubxacts;
  parsed->subxacts = xl_subxacts->subxacts;

  data += MinSizeOfXactSubxacts;
  data += parsed->nsubxacts * sizeof(TransactionId);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
 {
  xl_xact_relfilelocators *xl_rellocators = (xl_xact_relfilelocators *) data;

  parsed->nrels = xl_rellocators->nrels;
  parsed->xlocators = xl_rellocators->xlocators;

  data += MinSizeOfXactRelfileLocators;
  data += xl_rellocators->nrels * sizeof(RelFileLocator);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
 {
  xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;

  parsed->nstats = xl_drops->nitems;
  parsed->stats = xl_drops->items;

  data += MinSizeOfXactStatsItems;
  data += xl_drops->nitems * sizeof(xl_xact_stats_item);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_INVALS)
 {
  xl_xact_invals *xl_invals = (xl_xact_invals *) data;

  parsed->nmsgs = xl_invals->nmsgs;
  parsed->msgs = xl_invals->msgs;

  data += MinSizeOfXactInvals;
  data += xl_invals->nmsgs * sizeof(SharedInvalidationMessage);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
 {
  xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;

  parsed->twophase_xid = xl_twophase->xid;

  data += sizeof(xl_xact_twophase);

  if (parsed->xinfo & XACT_XINFO_HAS_GID)
  {
   strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
   data += strlen(data) + 1;
  }
 }

 /* Note: no alignment is guaranteed after this point */

 if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
 {
  xl_xact_origin xl_origin;

  /* no alignment is guaranteed, so copy onto stack */
  memcpy(&xl_origin, data, sizeof(xl_origin));

  parsed->origin_lsn = xl_origin.origin_lsn;
  parsed->origin_timestamp = xl_origin.origin_timestamp;

  data += sizeof(xl_xact_origin);
 }
}

void
ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
{
 char    *data = ((char *) xlrec) + MinSizeOfXactAbort;

 memset(parsed, 0sizeof(*parsed));

 parsed->xinfo = 0;   /* default, if no XLOG_XACT_HAS_INFO is
 * present */


 parsed->xact_time = xlrec->xact_time;

 if (info & XLOG_XACT_HAS_INFO)
 {
  xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;

  parsed->xinfo = xl_xinfo->xinfo;

  data += sizeof(xl_xact_xinfo);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
 {
  xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;

  parsed->dbId = xl_dbinfo->dbId;
  parsed->tsId = xl_dbinfo->tsId;

  data += sizeof(xl_xact_dbinfo);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
 {
  xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;

  parsed->nsubxacts = xl_subxacts->nsubxacts;
  parsed->subxacts = xl_subxacts->subxacts;

  data += MinSizeOfXactSubxacts;
  data += parsed->nsubxacts * sizeof(TransactionId);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
 {
  xl_xact_relfilelocators *xl_rellocator = (xl_xact_relfilelocators *) data;

  parsed->nrels = xl_rellocator->nrels;
  parsed->xlocators = xl_rellocator->xlocators;

  data += MinSizeOfXactRelfileLocators;
  data += xl_rellocator->nrels * sizeof(RelFileLocator);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
 {
  xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;

  parsed->nstats = xl_drops->nitems;
  parsed->stats = xl_drops->items;

  data += MinSizeOfXactStatsItems;
  data += xl_drops->nitems * sizeof(xl_xact_stats_item);
 }

 if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
 {
  xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;

  parsed->twophase_xid = xl_twophase->xid;

  data += sizeof(xl_xact_twophase);

  if (parsed->xinfo & XACT_XINFO_HAS_GID)
  {
   strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
   data += strlen(data) + 1;
  }
 }

 /* Note: no alignment is guaranteed after this point */

 if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
 {
  xl_xact_origin xl_origin;

  /* no alignment is guaranteed, so copy onto stack */
  memcpy(&xl_origin, data, sizeof(xl_origin));

  parsed->origin_lsn = xl_origin.origin_lsn;
  parsed->origin_timestamp = xl_origin.origin_timestamp;

  data += sizeof(xl_xact_origin);
 }
}

/*
 * ParsePrepareRecord
 */

void
ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *parsed)
{
 char    *bufptr;

 bufptr = ((char *) xlrec) + MAXALIGN(sizeof(xl_xact_prepare));

 memset(parsed, 0sizeof(*parsed));

 parsed->xact_time = xlrec->prepared_at;
 parsed->origin_lsn = xlrec->origin_lsn;
 parsed->origin_timestamp = xlrec->origin_timestamp;
 parsed->twophase_xid = xlrec->xid;
 parsed->dbId = xlrec->database;
 parsed->nsubxacts = xlrec->nsubxacts;
 parsed->nrels = xlrec->ncommitrels;
 parsed->nabortrels = xlrec->nabortrels;
 parsed->nstats = xlrec->ncommitstats;
 parsed->nabortstats = xlrec->nabortstats;
 parsed->nmsgs = xlrec->ninvalmsgs;

 strncpy(parsed->twophase_gid, bufptr, xlrec->gidlen);
 bufptr += MAXALIGN(xlrec->gidlen);

 parsed->subxacts = (TransactionId *) bufptr;
 bufptr += MAXALIGN(xlrec->nsubxacts * sizeof(TransactionId));

 parsed->xlocators = (RelFileLocator *) bufptr;
 bufptr += MAXALIGN(xlrec->ncommitrels * sizeof(RelFileLocator));

 parsed->abortlocators = (RelFileLocator *) bufptr;
 bufptr += MAXALIGN(xlrec->nabortrels * sizeof(RelFileLocator));

 parsed->stats = (xl_xact_stats_item *) bufptr;
 bufptr += MAXALIGN(xlrec->ncommitstats * sizeof(xl_xact_stats_item));

 parsed->abortstats = (xl_xact_stats_item *) bufptr;
 bufptr += MAXALIGN(xlrec->nabortstats * sizeof(xl_xact_stats_item));

 parsed->msgs = (SharedInvalidationMessage *) bufptr;
 bufptr += MAXALIGN(xlrec->ninvalmsgs * sizeof(SharedInvalidationMessage));
}

static void
xact_desc_relations(StringInfo buf, char *label, int nrels,
     RelFileLocator *xlocators)
{
 int   i;

 if (nrels > 0)
 {
  appendStringInfo(buf, "; %s:", label);
  for (i = 0; i < nrels; i++)
  {
   appendStringInfo(buf, " %s",
        relpathperm(xlocators[i], MAIN_FORKNUM).str);
  }
 }
}

static void
xact_desc_subxacts(StringInfo buf, int nsubxacts, TransactionId *subxacts)
{
 int   i;

 if (nsubxacts > 0)
 {
  appendStringInfoString(buf, "; subxacts:");
  for (i = 0; i < nsubxacts; i++)
   appendStringInfo(buf, " %u", subxacts[i]);
 }
}

static void
xact_desc_stats(StringInfo buf, const char *label,
    int ndropped, xl_xact_stats_item *dropped_stats)
{
 int   i;

 if (ndropped > 0)
 {
  appendStringInfo(buf, "; %sdropped stats:", label);
  for (i = 0; i < ndropped; i++)
  {
   uint64  objid =
    ((uint64) dropped_stats[i].objid_hi) << 32 | dropped_stats[i].objid_lo;

   appendStringInfo(buf, " %d/%u/%" PRIu64,
        dropped_stats[i].kind,
        dropped_stats[i].dboid,
        objid);
  }
 }
}

static void
xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId origin_id)
{
 xl_xact_parsed_commit parsed;

 ParseCommitRecord(info, xlrec, &parsed);

 /* If this is a prepared xact, show the xid of the original xact */
 if (TransactionIdIsValid(parsed.twophase_xid))
  appendStringInfo(buf, "%u: ", parsed.twophase_xid);

 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));

 xact_desc_relations(buf, "rels", parsed.nrels, parsed.xlocators);
 xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
 xact_desc_stats(buf, "", parsed.nstats, parsed.stats);

 standby_desc_invalidations(buf, parsed.nmsgs, parsed.msgs, parsed.dbId,
          parsed.tsId,
          XactCompletionRelcacheInitFileInval(parsed.xinfo));

 if (XactCompletionApplyFeedback(parsed.xinfo))
  appendStringInfoString(buf, "; apply_feedback");

 if (XactCompletionForceSyncCommit(parsed.xinfo))
  appendStringInfoString(buf, "; sync");

 if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
 {
  appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
       origin_id,
       LSN_FORMAT_ARGS(parsed.origin_lsn),
       timestamptz_to_str(parsed.origin_timestamp));
 }
}

static void
xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec, RepOriginId origin_id)
{
 xl_xact_parsed_abort parsed;

 ParseAbortRecord(info, xlrec, &parsed);

 /* If this is a prepared xact, show the xid of the original xact */
 if (TransactionIdIsValid(parsed.twophase_xid))
  appendStringInfo(buf, "%u: ", parsed.twophase_xid);

 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));

 xact_desc_relations(buf, "rels", parsed.nrels, parsed.xlocators);
 xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);

 if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
 {
  appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
       origin_id,
       LSN_FORMAT_ARGS(parsed.origin_lsn),
       timestamptz_to_str(parsed.origin_timestamp));
 }

 xact_desc_stats(buf, "", parsed.nstats, parsed.stats);
}

static void
xact_desc_prepare(StringInfo buf, uint8 info, xl_xact_prepare *xlrec, RepOriginId origin_id)
{
 xl_xact_parsed_prepare parsed;

 ParsePrepareRecord(info, xlrec, &parsed);

 appendStringInfo(buf, "gid %s: ", parsed.twophase_gid);
 appendStringInfoString(buf, timestamptz_to_str(parsed.xact_time));

 xact_desc_relations(buf, "rels(commit)", parsed.nrels, parsed.xlocators);
 xact_desc_relations(buf, "rels(abort)", parsed.nabortrels,
      parsed.abortlocators);
 xact_desc_stats(buf, "commit ", parsed.nstats, parsed.stats);
 xact_desc_stats(buf, "abort ", parsed.nabortstats, parsed.abortstats);
 xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);

 standby_desc_invalidations(buf, parsed.nmsgs, parsed.msgs, parsed.dbId,
          parsed.tsId, xlrec->initfileinval);

 /*
  * Check if the replication origin has been set in this record in the same
  * way as PrepareRedoAdd().
 */

 if (origin_id != InvalidRepOriginId)
  appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
       origin_id,
       LSN_FORMAT_ARGS(parsed.origin_lsn),
       timestamptz_to_str(parsed.origin_timestamp));
}

static void
xact_desc_assignment(StringInfo buf, xl_xact_assignment *xlrec)
{
 int   i;

 appendStringInfoString(buf, "subxacts:");

 for (i = 0; i < xlrec->nsubxacts; i++)
  appendStringInfo(buf, " %u", xlrec->xsub[i]);
}

void
xact_desc(StringInfo buf, XLogReaderState *record)
{
 char    *rec = XLogRecGetData(record);
 uint8  info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;

 if (info == XLOG_XACT_COMMIT || info == XLOG_XACT_COMMIT_PREPARED)
 {
  xl_xact_commit *xlrec = (xl_xact_commit *) rec;

  xact_desc_commit(buf, XLogRecGetInfo(record), xlrec,
       XLogRecGetOrigin(record));
 }
 else if (info == XLOG_XACT_ABORT || info == XLOG_XACT_ABORT_PREPARED)
 {
  xl_xact_abort *xlrec = (xl_xact_abort *) rec;

  xact_desc_abort(buf, XLogRecGetInfo(record), xlrec,
      XLogRecGetOrigin(record));
 }
 else if (info == XLOG_XACT_PREPARE)
 {
  xl_xact_prepare *xlrec = (xl_xact_prepare *) rec;

  xact_desc_prepare(buf, XLogRecGetInfo(record), xlrec,
        XLogRecGetOrigin(record));
 }
 else if (info == XLOG_XACT_ASSIGNMENT)
 {
  xl_xact_assignment *xlrec = (xl_xact_assignment *) rec;

  /*
   * Note that we ignore the WAL record's xid, since we're more
   * interested in the top-level xid that issued the record and which
   * xids are being reported here.
 */

  appendStringInfo(buf, "xtop %u: ", xlrec->xtop);
  xact_desc_assignment(buf, xlrec);
 }
 else if (info == XLOG_XACT_INVALIDATIONS)
 {
  xl_xact_invals *xlrec = (xl_xact_invals *) rec;

  standby_desc_invalidations(buf, xlrec->nmsgs, xlrec->msgs, InvalidOid,
           InvalidOid, false);
 }
}

const char *
xact_identify(uint8 info)
{
 const char *id = NULL;

 switch (info & XLOG_XACT_OPMASK)
 {
  case XLOG_XACT_COMMIT:
   id = "COMMIT";
   break;
  case XLOG_XACT_PREPARE:
   id = "PREPARE";
   break;
  case XLOG_XACT_ABORT:
   id = "ABORT";
   break;
  case XLOG_XACT_COMMIT_PREPARED:
   id = "COMMIT_PREPARED";
   break;
  case XLOG_XACT_ABORT_PREPARED:
   id = "ABORT_PREPARED";
   break;
  case XLOG_XACT_ASSIGNMENT:
   id = "ASSIGNMENT";
   break;
  case XLOG_XACT_INVALIDATIONS:
   id = "INVALIDATION";
   break;
 }

 return id;
}

Messung V0.5 in Prozent
C=92 H=92 G=91

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002