xloginsert-bkp-refactor-1.patch
text/x-diff
Filename: xloginsert-bkp-refactor-1.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 87 | 0 |
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 690,695 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
--- 690,698 ----
uint32 freespace;
int curridx;
XLogRecData *rdt;
+ XLogRecData *rdt_cur;
+ XLogRecData *rdt_bkp_first;
+ XLogRecData *rdt_bkp_last;
Buffer dtbuf[XLR_MAX_BKP_BLOCKS];
bool dtbuf_bkp[XLR_MAX_BKP_BLOCKS];
BkpBlock dtbuf_xlg[XLR_MAX_BKP_BLOCKS];
***************
*** 704,709 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
--- 707,713 ----
bool updrqst;
bool doPageWrites;
bool isLogSwitch = (rmid == RM_XLOG_ID && info == XLOG_SWITCH);
+ uint8 info_final;
/* cross-check on whether we should be here or not */
if (!XLogInsertAllowed())
***************
*** 727,738 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
}
/*
! * Here we scan the rdata chain, determine which buffers must be backed
! * up, and compute the CRC values for the data. Note that the record
! * header isn't added into the CRC initially since we don't know the final
! * length or info bits quite yet. Thus, the CRC will represent the CRC of
! * the whole record in the order "rdata, then backup blocks, then record
! * header".
*
* We may have to loop back to here if a race condition is detected below.
* We could prevent the race by doing all this work while holding the
--- 731,738 ----
}
/*
! * Here we scan the rdata chain to determine which buffers must be backed
! * up.
*
* We may have to loop back to here if a race condition is detected below.
* We could prevent the race by doing all this work while holding the
***************
*** 746,751 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
--- 746,752 ----
* over the chain later.
*/
begin:;
+ info_final = info;
for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
{
dtbuf[i] = InvalidBuffer;
***************
*** 760,766 **** begin:;
*/
doPageWrites = fullPageWrites || Insert->forcePageWrites;
- INIT_CRC32(rdata_crc);
len = 0;
for (rdt = rdata;;)
{
--- 761,766 ----
***************
*** 768,774 **** begin:;
{
/* Simple data, just include it */
len += rdt->len;
- COMP_CRC32(rdata_crc, rdt->data, rdt->len);
}
else
{
--- 768,773 ----
***************
*** 779,790 **** begin:;
{
/* Buffer already referenced by earlier chain item */
if (dtbuf_bkp[i])
rdt->data = NULL;
else if (rdt->data)
- {
len += rdt->len;
- COMP_CRC32(rdata_crc, rdt->data, rdt->len);
- }
break;
}
if (dtbuf[i] == InvalidBuffer)
--- 778,789 ----
{
/* Buffer already referenced by earlier chain item */
if (dtbuf_bkp[i])
+ {
rdt->data = NULL;
+ rdt->len = 0;
+ }
else if (rdt->data)
len += rdt->len;
break;
}
if (dtbuf[i] == InvalidBuffer)
***************
*** 796,807 **** begin:;
{
dtbuf_bkp[i] = true;
rdt->data = NULL;
}
else if (rdt->data)
- {
len += rdt->len;
- COMP_CRC32(rdata_crc, rdt->data, rdt->len);
- }
break;
}
}
--- 795,804 ----
{
dtbuf_bkp[i] = true;
rdt->data = NULL;
+ rdt->len = 0;
}
else if (rdt->data)
len += rdt->len;
break;
}
}
***************
*** 816,854 **** begin:;
}
/*
! * Now add the backup block headers and data into the CRC
*/
for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
{
! if (dtbuf_bkp[i])
{
! BkpBlock *bkpb = &(dtbuf_xlg[i]);
! char *page;
!
! COMP_CRC32(rdata_crc,
! (char *) bkpb,
! sizeof(BkpBlock));
! page = (char *) BufferGetBlock(dtbuf[i]);
! if (bkpb->hole_length == 0)
! {
! COMP_CRC32(rdata_crc,
! page,
! BLCKSZ);
! }
! else
! {
! /* must skip the hole */
! COMP_CRC32(rdata_crc,
! page,
! bkpb->hole_offset);
! COMP_CRC32(rdata_crc,
! page + (bkpb->hole_offset + bkpb->hole_length),
! BLCKSZ - (bkpb->hole_offset + bkpb->hole_length));
! }
}
}
/*
* NOTE: We disallow len == 0 because it provides a useful bit of extra
* error checking in ReadRecord. This means that all callers of
* XLogInsert must supply at least some not-in-a-buffer data. However, we
--- 813,898 ----
}
/*
! * Make additional rdata chain entries for the backup blocks, so that we
! * don't need to special-case them in the write loop. They are kept in
! * a separate rdata chain until we have the lock, and know that we won't
! * need to restart from scratch anymore. The real rdata chain is kept
! * unmodified until then.
! *
! * At the exit of this loop, write_len includes the backup block data.
! *
! * Also set the appropriate info bits to show which buffers were backed
! * up. The i'th XLR_SET_BKP_BLOCK bit corresponds to the i'th distinct
! * buffer value (ignoring InvalidBuffer) appearing in the rdata chain.
*/
+ write_len = len;
+ rdt_bkp_first = rdt_bkp_last = NULL;
for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
{
! BkpBlock *bkpb;
! char *page;
!
! if (!dtbuf_bkp[i])
! continue;
!
! info_final |= XLR_SET_BKP_BLOCK(i);
!
! bkpb = &(dtbuf_xlg[i]);
! page = (char *) BufferGetBlock(dtbuf[i]);
!
! if (rdt_bkp_first == NULL)
! rdt_bkp_first = &(dtbuf_rdt1[i]);
! else
! rdt_bkp_last->next = &(dtbuf_rdt1[i]);
!
! rdt_bkp_last = &(dtbuf_rdt1[i]);
!
! rdt_bkp_last->data = (char *) bkpb;
! rdt_bkp_last->len = sizeof(BkpBlock);
! write_len += sizeof(BkpBlock);
!
! rdt_bkp_last->next = &(dtbuf_rdt2[i]);
! rdt_bkp_last = rdt_bkp_last->next;
!
! if (bkpb->hole_length == 0)
{
! rdt_bkp_last->data = page;
! rdt_bkp_last->len = BLCKSZ;
! write_len += BLCKSZ;
! rdt_bkp_last->next = NULL;
! }
! else
! {
! /* must skip the hole */
! rdt_bkp_last->data = page;
! rdt_bkp_last->len = bkpb->hole_offset;
! write_len += bkpb->hole_offset;
!
! rdt_bkp_last->next = &(dtbuf_rdt3[i]);
! rdt_bkp_last = rdt_bkp_last->next;
!
! rdt_bkp_last->data = page + (bkpb->hole_offset + bkpb->hole_length);
! rdt_bkp_last->len = BLCKSZ - (bkpb->hole_offset + bkpb->hole_length);
! write_len += rdt_bkp_last->len;
! rdt_bkp_last->next = NULL;
}
}
/*
+ * Calculate CRC of the data, including all the backup blocks
+ *
+ * Note that the record header isn't added into the CRC initially since
+ * we don't know the prev-link yet. Thus, the CRC will represent the CRC
+ * of the whole record in the order "rdata, then backup blocks, then
+ * record header".
+ */
+ INIT_CRC32(rdata_crc);
+ for (rdt_cur = rdt; rdt_cur != NULL; rdt_cur = rdt_cur->next)
+ COMP_CRC32(rdata_crc, rdt_cur->data, rdt_cur->len);
+ for (rdt_cur = rdt_bkp_first; rdt_cur != NULL; rdt_cur = rdt_cur->next)
+ COMP_CRC32(rdata_crc, rdt_cur->data, rdt_cur->len);
+
+ /*
* NOTE: We disallow len == 0 because it provides a useful bit of extra
* error checking in ReadRecord. This means that all callers of
* XLogInsert must supply at least some not-in-a-buffer data. However, we
***************
*** 913,974 **** begin:;
}
/*
! * Make additional rdata chain entries for the backup blocks, so that we
! * don't need to special-case them in the write loop. Note that we have
! * now irrevocably changed the input rdata chain. At the exit of this
! * loop, write_len includes the backup block data.
! *
! * Also set the appropriate info bits to show which buffers were backed
! * up. The i'th XLR_SET_BKP_BLOCK bit corresponds to the i'th distinct
! * buffer value (ignoring InvalidBuffer) appearing in the rdata chain.
*/
! write_len = len;
! for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
! {
! BkpBlock *bkpb;
! char *page;
!
! if (!dtbuf_bkp[i])
! continue;
!
! info |= XLR_SET_BKP_BLOCK(i);
!
! bkpb = &(dtbuf_xlg[i]);
! page = (char *) BufferGetBlock(dtbuf[i]);
!
! rdt->next = &(dtbuf_rdt1[i]);
! rdt = rdt->next;
!
! rdt->data = (char *) bkpb;
! rdt->len = sizeof(BkpBlock);
! write_len += sizeof(BkpBlock);
!
! rdt->next = &(dtbuf_rdt2[i]);
! rdt = rdt->next;
!
! if (bkpb->hole_length == 0)
! {
! rdt->data = page;
! rdt->len = BLCKSZ;
! write_len += BLCKSZ;
! rdt->next = NULL;
! }
! else
! {
! /* must skip the hole */
! rdt->data = page;
! rdt->len = bkpb->hole_offset;
! write_len += bkpb->hole_offset;
!
! rdt->next = &(dtbuf_rdt3[i]);
! rdt = rdt->next;
!
! rdt->data = page + (bkpb->hole_offset + bkpb->hole_length);
! rdt->len = BLCKSZ - (bkpb->hole_offset + bkpb->hole_length);
! write_len += rdt->len;
! rdt->next = NULL;
! }
! }
/*
* If there isn't enough space on the current XLOG page for a record
--- 957,966 ----
}
/*
! * We can now link the backup block rdata entries into the chain. This
! * changes the rdata chain irrevocably.
*/
! rdt->next = rdt_bkp_first;
/*
* If there isn't enough space on the current XLOG page for a record
***************
*** 1031,1037 **** begin:;
record->xl_xid = GetCurrentTransactionIdIfAny();
record->xl_tot_len = SizeOfXLogRecord + write_len;
record->xl_len = len; /* doesn't include backup blocks */
! record->xl_info = info;
record->xl_rmid = rmid;
/* Now we can finish computing the record's CRC */
--- 1023,1029 ----
record->xl_xid = GetCurrentTransactionIdIfAny();
record->xl_tot_len = SizeOfXLogRecord + write_len;
record->xl_len = len; /* doesn't include backup blocks */
! record->xl_info = info_final;
record->xl_rmid = rmid;
/* Now we can finish computing the record's CRC */