diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 8a22836406..c4fd9eff87 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -126,6 +126,9 @@ int max_prepared_xacts = 0; * * typedef struct GlobalTransactionData *GlobalTransaction appears in * twophase.h + * + * Note that the max value of GIDSIZE must fit in the uint16 gidlen, + * specified in TwoPhaseFileHeader. */ #define GIDSIZE 200 @@ -851,7 +854,7 @@ TwoPhaseGetDummyProc(TransactionId xid) /* * Header for a 2PC state file */ -#define TWOPHASE_MAGIC 0x57F94532 /* format identifier */ +#define TWOPHASE_MAGIC 0x57F94533 /* format identifier */ typedef struct TwoPhaseFileHeader { @@ -866,7 +869,7 @@ typedef struct TwoPhaseFileHeader int32 nabortrels; /* number of delete-on-abort rels */ int32 ninvalmsgs; /* number of cache invalidation messages */ bool initfileinval; /* does relcache init file need invalidation? */ - char gid[GIDSIZE]; /* GID for transaction */ + uint16 gidlen; /* length of the GID - GID follows the header */ } TwoPhaseFileHeader; /* @@ -977,9 +980,10 @@ StartPrepare(GlobalTransaction gxact) hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels); hdr.ninvalmsgs = xactGetCommittedInvalidationMessages(&invalmsgs, &hdr.initfileinval); - StrNCpy(hdr.gid, gxact->gid, GIDSIZE); + hdr.gidlen = strlen(gxact->gid) + 1; /* Include '\0' */ save_state_data(&hdr, sizeof(TwoPhaseFileHeader)); + save_state_data(gxact->gid, hdr.gidlen); /* * Add the additional info about subxacts, deletable files and cache @@ -1360,6 +1364,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit) hdr = (TwoPhaseFileHeader *) buf; Assert(TransactionIdEquals(hdr->xid, xid)); bufptr = buf + MAXALIGN(sizeof(TwoPhaseFileHeader)); + bufptr += MAXALIGN(hdr->gidlen); children = (TransactionId *) bufptr; bufptr += MAXALIGN(hdr->nsubxacts * sizeof(TransactionId)); commitrels = (RelFileNode *) bufptr; @@ -1915,6 +1920,7 @@ RecoverPreparedTransactions(void) TwoPhaseFileHeader *hdr; TransactionId *subxids; GlobalTransaction gxact; + const char *gid; int i; xid = (TransactionId) strtoul(clde->d_name, NULL, 16); @@ -1947,6 +1953,8 @@ RecoverPreparedTransactions(void) hdr = (TwoPhaseFileHeader *) buf; Assert(TransactionIdEquals(hdr->xid, xid)); bufptr = buf + MAXALIGN(sizeof(TwoPhaseFileHeader)); + gid = (const char *) bufptr; + bufptr += MAXALIGN(hdr->gidlen); subxids = (TransactionId *) bufptr; bufptr += MAXALIGN(hdr->nsubxacts * sizeof(TransactionId)); bufptr += MAXALIGN(hdr->ncommitrels * sizeof(RelFileNode)); @@ -1975,7 +1983,7 @@ RecoverPreparedTransactions(void) /* * Recreate its GXACT and dummy PGPROC */ - gxact = MarkAsPreparing(xid, hdr->gid, + gxact = MarkAsPreparing(xid, gid, hdr->prepared_at, hdr->owner, hdr->database); gxact->ondisk = true;