Reduce size of two phase file header
authorSimon Riggs <[email protected]>
Thu, 10 Mar 2016 12:51:46 +0000 (12:51 +0000)
committerSimon Riggs <[email protected]>
Thu, 10 Mar 2016 12:51:46 +0000 (12:51 +0000)
Previously 2PC header was fixed at 200 bytes, which in most cases wasted
WAL space for a workload using 2PC heavily.

Pavan Deolasee, reviewed by Petr Jelinek

src/backend/access/transam/twophase.c

index 8a22836406afd02c61ba190841b60e6b7e9758f3..c4fd9eff87033ad7b95757c69744af5a44ca82e9 100644 (file)
@@ -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;