On 28/03/18 19:47, Simon Riggs wrote:
Store 2PC GID in commit/abort WAL recs for logical decoding
This forgot to update the comments in xl_xact_commit and xl_xact_abort, for the new fields.
+ + if (parsed->xinfo & XACT_XINFO_HAS_GID) + { + int gidlen; + strcpy(parsed->twophase_gid, data); + gidlen = strlen(parsed->twophase_gid) + 1; + data += MAXALIGN(gidlen); + } + } + + if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN) + { + xl_xact_origin xl_origin; + + /* we're only guaranteed 4 byte alignment, 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); }
There seems to be some confusion on the padding here. Firstly, what's the point of zero-padding the GID length to the next MAXALIGN boundary, which would be 8 bytes on 64-bit systems, if the start is only guaranteed 4-byte alignment, per the comment at the memcpy() above. Secondly, if we're memcpying the fields that follow anyway, why bother with any alignment padding at all?
I propose the attached. - Heikki
diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c index 3b3c95f810..2e4ea62e62 100644 --- a/src/backend/access/rmgrdesc/xactdesc.c +++ b/src/backend/access/rmgrdesc/xactdesc.c @@ -105,10 +105,8 @@ ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *pars if (parsed->xinfo & XACT_XINFO_HAS_GID) { - int gidlen; strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid)); - gidlen = strlen(data) + 1; - data += MAXALIGN(gidlen); + data += strlen(data) + 1; } } @@ -116,7 +114,7 @@ ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *pars { xl_xact_origin xl_origin; - /* we're only guaranteed 4 byte alignment, so copy onto stack */ + /* we're not guaranteed any alignment, so copy onto stack */ memcpy(&xl_origin, data, sizeof(xl_origin)); parsed->origin_lsn = xl_origin.origin_lsn; @@ -189,10 +187,8 @@ ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed) if (parsed->xinfo & XACT_XINFO_HAS_GID) { - int gidlen; strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid)); - gidlen = strlen(data) + 1; - data += MAXALIGN(gidlen); + data += strlen(data) + 1; } } @@ -200,7 +196,7 @@ ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed) { xl_xact_origin xl_origin; - /* we're only guaranteed 4 byte alignment, so copy onto stack */ + /* we're not guaranteed any alignment, so copy onto stack */ memcpy(&xl_origin, data, sizeof(xl_origin)); parsed->origin_lsn = xl_origin.origin_lsn; diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index d6e4b7980f..5c05d545c4 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -1129,9 +1129,11 @@ EndPrepare(GlobalTransaction gxact) gxact->prepare_end_lsn = XLogInsert(RM_XACT_ID, XLOG_XACT_PREPARE); if (replorigin) + { /* Move LSNs forward for this replication origin */ replorigin_session_advance(replorigin_session_origin_lsn, gxact->prepare_end_lsn); + } XLogFlush(gxact->prepare_end_lsn); diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index b88d4ccf74..1dcf825625 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -5248,7 +5248,6 @@ XactLogCommitRecord(TimestampTz commit_time, xl_xact_origin xl_origin; uint8 info; - int gidlen = 0; Assert(CritSectionCount > 0); @@ -5314,10 +5313,7 @@ XactLogCommitRecord(TimestampTz commit_time, Assert(twophase_gid != NULL); if (XLogLogicalInfoActive()) - { xl_xinfo.xinfo |= XACT_XINFO_HAS_GID; - gidlen = strlen(twophase_gid) + 1; /* include '\0' */ - } } /* dump transaction origin information */ @@ -5371,12 +5367,7 @@ XactLogCommitRecord(TimestampTz commit_time, { XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID) - { - static const char zeroes[MAXIMUM_ALIGNOF] = { 0 }; - XLogRegisterData((char*) twophase_gid, gidlen); - if (MAXALIGN(gidlen) != gidlen) - XLogRegisterData((char*) zeroes, MAXALIGN(gidlen) - gidlen); - } + XLogRegisterData((char *) twophase_gid, strlen(twophase_gid)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN) @@ -5410,7 +5401,6 @@ XactLogAbortRecord(TimestampTz abort_time, xl_xact_origin xl_origin; uint8 info; - int gidlen = 0; Assert(CritSectionCount > 0); @@ -5449,10 +5439,7 @@ XactLogAbortRecord(TimestampTz abort_time, Assert(twophase_gid != NULL); if (XLogLogicalInfoActive()) - { xl_xinfo.xinfo |= XACT_XINFO_HAS_GID; - gidlen = strlen(twophase_gid) + 1; /* include '\0' */ - } } if (TransactionIdIsValid(twophase_xid) && XLogLogicalInfoActive()) @@ -5488,7 +5475,6 @@ XactLogAbortRecord(TimestampTz abort_time, if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO) XLogRegisterData((char *) (&xl_dbinfo), sizeof(xl_dbinfo)); - if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS) { XLogRegisterData((char *) (&xl_subxacts), @@ -5509,14 +5495,14 @@ XactLogAbortRecord(TimestampTz abort_time, { XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID) - { - static const char zeroes[MAXIMUM_ALIGNOF] = { 0 }; - XLogRegisterData((char*) twophase_gid, gidlen); - if (MAXALIGN(gidlen) != gidlen) - XLogRegisterData((char*) zeroes, MAXALIGN(gidlen) - gidlen); - } + XLogRegisterData((char *) twophase_gid, strlen(twophase_gid) + 1); } + /* + * NOTE: twophase_gid is variable-length, so no alignment is guaranteed + * after this point. + */ + if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN) XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin)); diff --git a/src/include/access/xact.h b/src/include/access/xact.h index a46396f2d9..3661b8d090 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -269,6 +269,7 @@ typedef struct xl_xact_commit /* xl_xact_relfilenodes follows if XINFO_HAS_RELFILENODES */ /* xl_xact_invals follows if XINFO_HAS_INVALS */ /* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */ + /* twophase_gid follows if XINFO_HAS_GID. As a null-terminated string. */ /* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */ } xl_xact_commit; #define MinSizeOfXactCommit (offsetof(xl_xact_commit, xact_time) + sizeof(TimestampTz)) @@ -278,11 +279,13 @@ typedef struct xl_xact_abort TimestampTz xact_time; /* time of abort */ /* xl_xact_xinfo follows if XLOG_XACT_HAS_INFO */ - /* No db_info required */ + /* xl_xact_dbinfo follows if XINFO_HAS_DBINFO */ /* xl_xact_subxacts follows if HAS_SUBXACT */ /* xl_xact_relfilenodes follows if HAS_RELFILENODES */ /* No invalidation messages needed. */ /* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */ + /* twophase_gid follows if XINFO_HAS_GID. As a null-terminated string. */ + /* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */ } xl_xact_abort; #define MinSizeOfXactAbort sizeof(xl_xact_abort)