From db400ce9532536da36812dbf0456e756a0ea4724 Mon Sep 17 00:00:00 2001 From: "Andrey V. Lepikhov" Date: Tue, 31 Jul 2018 07:22:17 +0500 Subject: [PATCH 1/4] Relation-into-WAL-function --- src/backend/access/transam/generic_xlog.c | 62 +++++++++++++++++++++++ src/include/access/generic_xlog.h | 3 ++ 2 files changed, 65 insertions(+) diff --git a/src/backend/access/transam/generic_xlog.c b/src/backend/access/transam/generic_xlog.c index ce023548ae..8397b58ee7 100644 --- a/src/backend/access/transam/generic_xlog.c +++ b/src/backend/access/transam/generic_xlog.c @@ -80,6 +80,7 @@ static void computeRegionDelta(PageData *pageData, static void computeDelta(PageData *pageData, Page curpage, Page targetpage); static void applyPageRedo(Page page, const char *delta, Size deltaSize); +static void standard_page_layout_check(Buffer buf); /* * Write next fragment into pageData's delta. @@ -545,3 +546,64 @@ generic_mask(char *page, BlockNumber blkno) mask_unused_space(page); } + +/* + * Check page layout. + * Caller must lock the buffer + */ +static void +standard_page_layout_check(Buffer buf) +{ + PageHeader ph = (PageHeader) BufferGetPage(buf); + + Assert((ph->pd_lower >= SizeOfPageHeaderData) && + (ph->pd_lower <= ph->pd_upper) && + (ph->pd_upper <= ph->pd_special) && + (ph->pd_special <= BLCKSZ) && + (ph->pd_special == MAXALIGN(ph->pd_special))); +} + +/* + * Function to write generic xlog for every existing block of a relation. + * Caller is responsible for locking the relation exclusively. + */ +void +generic_log_relation(Relation rel) +{ + BlockNumber blkno; + BlockNumber nblocks; + + nblocks = RelationGetNumberOfBlocks(rel); + + elog(DEBUG2, "generic_log_relation '%s', nblocks %u BEGIN.", + RelationGetRelationName(rel), nblocks); + + for (blkno = 0; blkno < nblocks; ) + { + GenericXLogState *state; + Buffer buffer[MAX_GENERIC_XLOG_PAGES]; + int counter, + blocks_pack; + + CHECK_FOR_INTERRUPTS(); + + blocks_pack = ((nblocks-blkno) < MAX_GENERIC_XLOG_PAGES) ? + (nblocks-blkno) : MAX_GENERIC_XLOG_PAGES; + + state = GenericXLogStart(rel); + + for (counter = 0 ; counter < blocks_pack; counter++) + { + buffer[counter] = ReadBuffer(rel, blkno++); + standard_page_layout_check(buffer[counter]); + LockBuffer(buffer[counter], BUFFER_LOCK_EXCLUSIVE); + GenericXLogRegisterBuffer(state, buffer[counter], GENERIC_XLOG_FULL_IMAGE); + } + + GenericXLogFinish(state); + + for (counter = 0 ; counter < blocks_pack; counter++) + UnlockReleaseBuffer(buffer[counter]); + } + elog(DEBUG2, "generic_log_relation '%s' END.", RelationGetRelationName(rel)); +} diff --git a/src/include/access/generic_xlog.h b/src/include/access/generic_xlog.h index b23e1f684b..1f4b3b7030 100644 --- a/src/include/access/generic_xlog.h +++ b/src/include/access/generic_xlog.h @@ -42,4 +42,7 @@ extern const char *generic_identify(uint8 info); extern void generic_desc(StringInfo buf, XLogReaderState *record); extern void generic_mask(char *pagedata, BlockNumber blkno); +/* other utils */ +extern void generic_log_relation(Relation rel); + #endif /* GENERIC_XLOG_H */ -- 2.17.1