prepare-xact-desc_v2.patch
application/octet-stream
Filename: prepare-xact-desc_v2.patch
Type: application/octet-stream
Part: 0
Message:
Re: pg_waldump and PREPARE
Patch
Format: context
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/access/rmgrdesc/xactdesc.c | 52 | 0 |
| src/backend/access/transam/twophase.c | 1 | 0 |
| src/include/access/twophase.h | 0 | 0 |
| src/include/access/xact.h | 19 | 0 |
*** a/src/backend/access/rmgrdesc/xactdesc.c
--- b/src/backend/access/rmgrdesc/xactdesc.c
***************
*** 209,214 **** ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
--- 209,249 ----
}
}
+ /*
+ * ParsePrepareRecord
+ */
+ void
+ ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *parsed)
+ {
+ char *bufptr;
+
+ bufptr = (char *) xlrec + MAXALIGN(sizeof(xl_xact_prepare));
+
+ 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->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->xnodes = (RelFileNode *) bufptr;
+ bufptr += MAXALIGN(xlrec->ncommitrels * sizeof(RelFileNode));
+
+ parsed->abortnodes = (RelFileNode *) bufptr;
+ bufptr += MAXALIGN(xlrec->nabortrels * sizeof(RelFileNode));
+
+ parsed->msgs = (SharedInvalidationMessage *) bufptr;
+ bufptr += MAXALIGN(xlrec->ninvalmsgs * sizeof(SharedInvalidationMessage));
+ }
+
static void
xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId origin_id)
{
***************
*** 293,298 **** xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec)
--- 328,344 ----
}
}
+ static void
+ xact_desc_prepare(StringInfo buf, uint8 info, xl_xact_prepare *xlrec)
+ {
+ xl_xact_parsed_prepare parsed;
+
+ ParsePrepareRecord(info, xlrec, &parsed);
+
+ appendStringInfo(buf, "gid %s: ", parsed.twophase_gid);
+ appendStringInfoString(buf, timestamptz_to_str(parsed.xact_time));
+ }
+
static void
xact_desc_assignment(StringInfo buf, xl_xact_assignment *xlrec)
{
***************
*** 323,328 **** xact_desc(StringInfo buf, XLogReaderState *record)
--- 369,380 ----
xact_desc_abort(buf, XLogRecGetInfo(record), xlrec);
}
+ else if (info == XLOG_XACT_PREPARE)
+ {
+ xl_xact_prepare *xlrec = (xl_xact_prepare *) rec;
+
+ xact_desc_prepare(buf, XLogRecGetInfo(record), xlrec);
+ }
else if (info == XLOG_XACT_ASSIGNMENT)
{
xl_xact_assignment *xlrec = (xl_xact_assignment *) rec;
*** a/src/backend/access/transam/twophase.c
--- b/src/backend/access/transam/twophase.c
***************
*** 911,933 **** TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
*/
#define TWOPHASE_MAGIC 0x57F94534 /* format identifier */
! typedef struct TwoPhaseFileHeader
! {
! uint32 magic; /* format identifier */
! uint32 total_len; /* actual file length */
! TransactionId xid; /* original transaction XID */
! Oid database; /* OID of database it was in */
! TimestampTz prepared_at; /* time of preparation */
! Oid owner; /* user running the transaction */
! int32 nsubxacts; /* number of following subxact XIDs */
! int32 ncommitrels; /* number of delete-on-commit rels */
! int32 nabortrels; /* number of delete-on-abort rels */
! int32 ninvalmsgs; /* number of cache invalidation messages */
! bool initfileinval; /* does relcache init file need invalidation? */
! uint16 gidlen; /* length of the GID - GID follows the header */
! XLogRecPtr origin_lsn; /* lsn of this record at origin node */
! TimestampTz origin_timestamp; /* time of prepare at origin node */
! } TwoPhaseFileHeader;
/*
* Header for each record in a state file
--- 911,917 ----
*/
#define TWOPHASE_MAGIC 0x57F94534 /* format identifier */
! typedef xl_xact_prepare TwoPhaseFileHeader;
/*
* Header for each record in a state file
***************
*** 1332,1375 **** ReadTwoPhaseFile(TransactionId xid, bool missing_ok)
return buf;
}
- /*
- * ParsePrepareRecord
- */
- void
- ParsePrepareRecord(uint8 info, char *xlrec, xl_xact_parsed_prepare *parsed)
- {
- TwoPhaseFileHeader *hdr;
- char *bufptr;
-
- hdr = (TwoPhaseFileHeader *) xlrec;
- bufptr = xlrec + MAXALIGN(sizeof(TwoPhaseFileHeader));
-
- parsed->origin_lsn = hdr->origin_lsn;
- parsed->origin_timestamp = hdr->origin_timestamp;
- parsed->twophase_xid = hdr->xid;
- parsed->dbId = hdr->database;
- parsed->nsubxacts = hdr->nsubxacts;
- parsed->nrels = hdr->ncommitrels;
- parsed->nabortrels = hdr->nabortrels;
- parsed->nmsgs = hdr->ninvalmsgs;
-
- strncpy(parsed->twophase_gid, bufptr, hdr->gidlen);
- bufptr += MAXALIGN(hdr->gidlen);
-
- parsed->subxacts = (TransactionId *) bufptr;
- bufptr += MAXALIGN(hdr->nsubxacts * sizeof(TransactionId));
-
- parsed->xnodes = (RelFileNode *) bufptr;
- bufptr += MAXALIGN(hdr->ncommitrels * sizeof(RelFileNode));
-
- parsed->abortnodes = (RelFileNode *) bufptr;
- bufptr += MAXALIGN(hdr->nabortrels * sizeof(RelFileNode));
-
- parsed->msgs = (SharedInvalidationMessage *) bufptr;
- bufptr += MAXALIGN(hdr->ninvalmsgs * sizeof(SharedInvalidationMessage));
- }
-
-
/*
* Reads 2PC data from xlog. During checkpoint this data will be moved to
--- 1316,1321 ----
*** a/src/include/access/twophase.h
--- b/src/include/access/twophase.h
***************
*** 47,54 **** extern bool StandbyTransactionIdIsPrepared(TransactionId xid);
extern TransactionId PrescanPreparedTransactions(TransactionId **xids_p,
int *nxids_p);
- extern void ParsePrepareRecord(uint8 info, char *xlrec,
- xl_xact_parsed_prepare *parsed);
extern void StandbyRecoverPreparedTransactions(void);
extern void RecoverPreparedTransactions(void);
--- 47,52 ----
*** a/src/include/access/xact.h
--- b/src/include/access/xact.h
***************
*** 292,297 **** typedef struct xl_xact_abort
--- 292,315 ----
} xl_xact_abort;
#define MinSizeOfXactAbort sizeof(xl_xact_abort)
+ typedef struct xl_xact_prepare
+ {
+ uint32 magic; /* format identifier */
+ uint32 total_len; /* actual file length */
+ TransactionId xid; /* original transaction XID */
+ Oid database; /* OID of database it was in */
+ TimestampTz prepared_at; /* time of preparation */
+ Oid owner; /* user running the transaction */
+ int32 nsubxacts; /* number of following subxact XIDs */
+ int32 ncommitrels; /* number of delete-on-commit rels */
+ int32 nabortrels; /* number of delete-on-abort rels */
+ int32 ninvalmsgs; /* number of cache invalidation messages */
+ bool initfileinval; /* does relcache init file need invalidation? */
+ uint16 gidlen; /* length of the GID - GID follows the header */
+ XLogRecPtr origin_lsn; /* lsn of this record at origin node */
+ TimestampTz origin_timestamp; /* time of prepare at origin node */
+ } xl_xact_prepare;
+
/*
* Commit/Abort records in the above form are a bit verbose to parse, so
* there's a deconstructed versions generated by ParseCommit/AbortRecord() for
***************
*** 435,440 **** extern const char *xact_identify(uint8 info);
--- 453,459 ----
/* also in xactdesc.c, so they can be shared between front/backend code */
extern void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed);
extern void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed);
+ extern void ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *parsed);
extern void EnterParallelMode(void);
extern void ExitParallelMode(void);