diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index bc82e2df9e8..64e2562630c 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -418,8 +418,10 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo) log_newpage_range(index, MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index), true); - SetLastWrittenLSNForBlockRange(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index)); - SetLastWrittenLSNForRelation(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); + if (set_lwlsn_block_range_hook) + set_lwlsn_block_range_hook(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index)); + if (set_lwlsn_relation_hook) + set_lwlsn_relation_hook(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); } smgr_end_unlogged_build(index->rd_smgr); diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c index 91ebf84fe2d..4d1d7e19b1f 100644 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@ -340,10 +340,12 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo) log_newpage_range(index, MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index), true); - SetLastWrittenLSNForBlockRange(XactLastRecEnd, + if (set_lwlsn_block_range_hook) + set_lwlsn_block_range_hook(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index)); - SetLastWrittenLSNForRelation(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); + if (set_lwlsn_relation_hook) + set_lwlsn_relation_hook(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); } smgr_end_unlogged_build(index->rd_smgr); @@ -464,9 +466,11 @@ gist_indexsortbuild(GISTBuildState *state) { XLogRecPtr lsn = GetRedoRecPtr(); - SetLastWrittenLSNForBlock(lsn, state->indexrel->rd_smgr->smgr_rlocator.locator, - MAIN_FORKNUM, GIST_ROOT_BLKNO); - SetLastWrittenLSNForRelation(lsn, state->indexrel->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); + if (set_lwlsn_block_hook) + set_lwlsn_block_hook(lsn, state->indexrel->rd_smgr->smgr_rlocator.locator, + MAIN_FORKNUM, GIST_ROOT_BLKNO); + if (set_lwlsn_relation_hook) + set_lwlsn_relation_hook(lsn, state->indexrel->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); } pfree(levelstate); diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c index f3652531867..814f34a3241 100644 --- a/src/backend/access/spgist/spginsert.c +++ b/src/backend/access/spgist/spginsert.c @@ -142,9 +142,11 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo) log_newpage_range(index, MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index), true); - SetLastWrittenLSNForBlockRange(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, - MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index)); - SetLastWrittenLSNForRelation(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); + if (set_lwlsn_block_range_hook) + set_lwlsn_block_range_hook(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, + MAIN_FORKNUM, 0, RelationGetNumberOfBlocks(index)); + if (set_lwlsn_relation_hook) + set_lwlsn_relation_hook(XactLastRecEnd, index->rd_smgr->smgr_rlocator.locator, MAIN_FORKNUM); } smgr_end_unlogged_build(index->rd_smgr); diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 6356b23df33..86287161a21 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -138,7 +138,6 @@ int max_slot_wal_keep_size_mb = -1; int wal_decode_buffer_size = 512 * 1024; bool track_wal_io_timing = false; uint64 predefined_sysidentifier; -int lastWrittenLsnCacheSize; #ifdef WAL_DEBUG bool XLOG_DEBUG = false; @@ -148,6 +147,15 @@ int wal_segment_size = DEFAULT_XLOG_SEG_SIZE; /* NEON: Hook to allow the neon extension to restore running-xacts from CLOG at replica startup */ restore_running_xacts_callback_t restore_running_xacts_callback; + +/* NEON: Hooks to facilitate the last written LSN cache */ +set_lwlsn_block_hook_type set_lwlsn_block_hook = NULL; +set_lwlsn_block_range_hook_type set_lwlsn_block_range_hook = NULL; +set_lwlsn_block_v_hook_type set_lwlsn_block_v_hook = NULL; +set_lwlsn_db_hook_type set_lwlsn_db_hook = NULL; +set_lwlsn_relation_hook_type set_lwlsn_relation_hook = NULL; +set_max_lwlsn_hook_type set_max_lwlsn_hook = NULL; + /* * Number of WAL insertion locks to use. A higher value allows more insertions * to happen concurrently, but adds some CPU overhead to flushing the WAL, @@ -207,24 +215,8 @@ const struct config_enum_entry archive_mode_options[] = { {NULL, 0, false} }; -typedef struct LastWrittenLsnCacheEntry -{ - BufferTag key; - XLogRecPtr lsn; - /* double linked list for LRU replacement algorithm */ - dlist_node lru_node; -} LastWrittenLsnCacheEntry; -/* - * Cache of last written LSN for each relation page. - * Also to provide request LSN for smgrnblocks, smgrexists there is pseudokey=InvalidBlockId which stores LSN of last - * relation metadata update. - * Size of the cache is limited by GUC variable lastWrittenLsnCacheSize ("lsn_cache_size"), - * pages are replaced using LRU algorithm, based on L2-list. - * Access to this cache is protected by 'LastWrittenLsnLock'. - */ -static HTAB *lastWrittenLsnCache; /* * Statistics for current checkpoint are collected in this global struct. @@ -575,16 +567,7 @@ typedef struct XLogCtlData */ XLogRecPtr lastFpwDisableRecPtr; - /* - * Maximal last written LSN for pages not present in lastWrittenLsnCache - */ - XLogRecPtr maxLastWrittenLsn; - /* - * Double linked list to implement LRU replacement policy for last written LSN cache. - * Access to this list as well as to last written LSN cache is protected by 'LastWrittenLsnLock'. - */ - dlist_head lastWrittenLsnLRU; /* neon: copy of startup's RedoStartLSN for walproposer's use */ XLogRecPtr RedoStartLSN; @@ -764,12 +747,6 @@ static void WALInsertLockAcquireExclusive(void); static void WALInsertLockRelease(void); static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt); -static XLogRecPtr SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, - RelFileLocator rlocator, - ForkNumber forknum, - BlockNumber from, - BlockNumber n_blocks); - /* * Insert an XLOG record represented by an already-constructed chain of data * chunks. This is a low-level routine; to construct the WAL record header @@ -4896,8 +4873,8 @@ GetActiveWalLevelOnStandby(void) return ControlFile->wal_level; } -static Size -XLOGCtlShmemSize(void) +Size +XLOGShmemSize(void) { Size size; @@ -4946,16 +4923,6 @@ XLOGCtlShmemSize(void) return size; } -/* - * Initialization of shared memory for XLOG - */ -Size -XLOGShmemSize(void) -{ - return XLOGCtlShmemSize() + - hash_estimate_size(lastWrittenLsnCacheSize, sizeof(LastWrittenLsnCacheEntry)); -} - void XLOGShmemInit(void) { @@ -4983,18 +4950,7 @@ XLOGShmemInit(void) XLogCtl = (XLogCtlData *) - ShmemInitStruct("XLOG Ctl", XLOGCtlShmemSize(), &foundXLog); - - if (lastWrittenLsnCacheSize > 0) - { - static HASHCTL info; - info.keysize = sizeof(BufferTag); - info.entrysize = sizeof(LastWrittenLsnCacheEntry); - lastWrittenLsnCache = ShmemInitHash("last_written_lsn_cache", - lastWrittenLsnCacheSize, lastWrittenLsnCacheSize, - &info, - HASH_ELEM | HASH_BLOBS); - } + ShmemInitStruct("XLOG Ctl", XLOGShmemSize(), &foundXLog); localControlFile = ControlFile; ControlFile = (ControlFileData *) @@ -5829,13 +5785,8 @@ StartupXLOG(void) RedoRecPtr = XLogCtl->RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo; doPageWrites = lastFullPageWrites; - /* - * Setup last written lsn cache, max written LSN. - * Starting from here, we could be modifying pages through REDO, which requires - * the existance of maxLwLsn + LwLsn LRU. - */ - XLogCtl->maxLastWrittenLsn = RedoRecPtr; - dlist_init(&XLogCtl->lastWrittenLsnLRU); + if (set_max_lwlsn_hook) + set_max_lwlsn_hook(RedoRecPtr); /* REDO */ if (InRecovery) @@ -6682,343 +6633,6 @@ GetInsertRecPtr(void) return recptr; } -/* - * GetLastWrittenLSN -- Returns maximal LSN of written page. - * It returns an upper bound for the last written LSN of a given page, - * either from a cached last written LSN or a global maximum last written LSN. - * If rnode is InvalidOid then we calculate maximum among all cached LSN and maxLastWrittenLsn. - * If cache is large enough, iterating through all hash items may be rather expensive. - * But GetLastWrittenLSN(InvalidOid) is used only by neon_dbsize which is not performance critical. - */ -XLogRecPtr -GetLastWrittenLSN(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno) -{ - XLogRecPtr lsn; - LastWrittenLsnCacheEntry* entry; - - Assert(lastWrittenLsnCacheSize != 0); - - LWLockAcquire(LastWrittenLsnLock, LW_SHARED); - - /* Maximal last written LSN among all non-cached pages */ - lsn = XLogCtl->maxLastWrittenLsn; - - if (rlocator.relNumber != InvalidOid) - { - BufferTag key; - key.spcOid = rlocator.spcOid; - key.dbOid = rlocator.dbOid; - key.relNumber = rlocator.relNumber; - key.forkNum = forknum; - key.blockNum = blkno; - entry = hash_search(lastWrittenLsnCache, &key, HASH_FIND, NULL); - if (entry != NULL) - lsn = entry->lsn; - else - { - LWLockRelease(LastWrittenLsnLock); - LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); - /* - * In case of statements CREATE TABLE AS SELECT... or INSERT FROM SELECT... we are fetching data from source table - * and storing it in destination table. It cause problems with prefetch last-written-lsn is known for the pages of - * source table (which for example happens after compute restart). In this case we get get global value of - * last-written-lsn which is changed frequently as far as we are writing pages of destination table. - * As a result request-lsn for the prefetch and request-let when this page is actually needed are different - * and we got exported prefetch request. So it actually disarms prefetch. - * To prevent that, we re-insert the page with the latest LSN, so that it's - * less likely the LSN for this page will get evicted from the LwLsnCache - * before the page is read. - */ - lsn = SetLastWrittenLSNForBlockRangeInternal(lsn, rlocator, forknum, blkno, 1); - } - } - else - { - HASH_SEQ_STATUS seq; - /* Find maximum of all cached LSNs */ - hash_seq_init(&seq, lastWrittenLsnCache); - while ((entry = (LastWrittenLsnCacheEntry *) hash_seq_search(&seq)) != NULL) - { - if (entry->lsn > lsn) - lsn = entry->lsn; - } - } - LWLockRelease(LastWrittenLsnLock); - - return lsn; -} - -/* - * GetLastWrittenLSN -- Returns maximal LSN of written page. - * It returns an upper bound for the last written LSN of a given page, - * either from a cached last written LSN or a global maximum last written LSN. - * If rnode is InvalidOid then we calculate maximum among all cached LSN and maxLastWrittenLsn. - * If cache is large enough, iterating through all hash items may be rather expensive. - * But GetLastWrittenLSN(InvalidOid) is used only by neon_dbsize which is not performance critical. - */ -void -GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, - BlockNumber blkno, int nblocks, XLogRecPtr *lsns) -{ - LastWrittenLsnCacheEntry* entry; - XLogRecPtr lsn; - - Assert(lastWrittenLsnCacheSize != 0); - Assert(nblocks > 0); - Assert(PointerIsValid(lsns)); - - LWLockAcquire(LastWrittenLsnLock, LW_SHARED); - - if (relfilenode.relNumber != InvalidOid) - { - BufferTag key; - bool missed_keys = false; - - key.spcOid = relfilenode.spcOid; - key.dbOid = relfilenode.dbOid; - key.relNumber = relfilenode.relNumber; - key.forkNum = forknum; - - for (int i = 0; i < nblocks; i++) - { - /* Maximal last written LSN among all non-cached pages */ - key.blockNum = blkno + i; - - entry = hash_search(lastWrittenLsnCache, &key, HASH_FIND, NULL); - if (entry != NULL) - { - lsns[i] = entry->lsn; - } - else - { - /* Mark this block's LSN as missing - we'll update the LwLSN for missing blocks in bulk later */ - lsns[i] = InvalidXLogRecPtr; - missed_keys = true; - } - } - - /* - * If we had any missing LwLSN entries, we add the missing ones now. - * By doing the insertions in one batch, we decrease lock contention. - */ - if (missed_keys) - { - LWLockRelease(LastWrittenLsnLock); - LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); - - lsn = XLogCtl->maxLastWrittenLsn; - - for (int i = 0; i < nblocks; i++) - { - if (lsns[i] == InvalidXLogRecPtr) - { - lsns[i] = lsn; - SetLastWrittenLSNForBlockRangeInternal(lsn, relfilenode, forknum, blkno + i, 1); - } - } - } - } - else - { - HASH_SEQ_STATUS seq; - lsn = XLogCtl->maxLastWrittenLsn; - /* Find maximum of all cached LSNs */ - hash_seq_init(&seq, lastWrittenLsnCache); - while ((entry = (LastWrittenLsnCacheEntry *) hash_seq_search(&seq)) != NULL) - { - if (entry->lsn > lsn) - lsn = entry->lsn; - } - - for (int i = 0; i < nblocks; i++) - lsns[i] = lsn; - } - LWLockRelease(LastWrittenLsnLock); -} - -/* - * Guts for SetLastWrittenLSNForBlockRange. - * Caller must ensure LastWrittenLsnLock is held in exclusive mode. - */ -static XLogRecPtr -SetLastWrittenLSNForBlockRangeInternal(XLogRecPtr lsn, - RelFileLocator rlocator, - ForkNumber forknum, - BlockNumber from, - BlockNumber n_blocks) -{ - if (rlocator.relNumber == InvalidOid) - { - if (lsn > XLogCtl->maxLastWrittenLsn) - XLogCtl->maxLastWrittenLsn = lsn; - else - lsn = XLogCtl->maxLastWrittenLsn; - } - else - { - LastWrittenLsnCacheEntry* entry; - BufferTag key; - bool found; - BlockNumber i; - - key.spcOid = rlocator.spcOid; - key.dbOid = rlocator.dbOid; - key.relNumber = rlocator.relNumber; - key.forkNum = forknum; - for (i = 0; i < n_blocks; i++) - { - key.blockNum = from + i; - entry = hash_search(lastWrittenLsnCache, &key, HASH_ENTER, &found); - if (found) - { - if (lsn > entry->lsn) - entry->lsn = lsn; - else - lsn = entry->lsn; - /* Unlink from LRU list */ - dlist_delete(&entry->lru_node); - } - else - { - entry->lsn = lsn; - if (hash_get_num_entries(lastWrittenLsnCache) > lastWrittenLsnCacheSize) - { - /* Replace least recently used entry */ - LastWrittenLsnCacheEntry* victim = dlist_container(LastWrittenLsnCacheEntry, lru_node, dlist_pop_head_node(&XLogCtl->lastWrittenLsnLRU)); - /* Adjust max LSN for not cached relations/chunks if needed */ - if (victim->lsn > XLogCtl->maxLastWrittenLsn) - XLogCtl->maxLastWrittenLsn = victim->lsn; - - hash_search(lastWrittenLsnCache, victim, HASH_REMOVE, NULL); - } - } - /* Link to the end of LRU list */ - dlist_push_tail(&XLogCtl->lastWrittenLsnLRU, &entry->lru_node); - } - } - return lsn; -} - -/* - * SetLastWrittenLSNForBlockRange -- Set maximal LSN of written page range. - * We maintain cache of last written LSNs with limited size and LRU replacement - * policy. Keeping last written LSN for each page allows to use old LSN when - * requesting pages of unchanged or appended relations. Also it is critical for - * efficient work of prefetch in case massive update operations (like vacuum or remove). - * - * rlocator.relNumber can be InvalidOid, in this case maxLastWrittenLsn is updated. - * SetLastWrittenLsn with dummy rlocator is used by createdb and dbase_redo functions. - */ -XLogRecPtr -SetLastWrittenLSNForBlockRange(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks) -{ - if (lsn == InvalidXLogRecPtr || n_blocks == 0 || lastWrittenLsnCacheSize == 0) - return lsn; - - LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); - lsn = SetLastWrittenLSNForBlockRangeInternal(lsn, rlocator, forknum, from, n_blocks); - LWLockRelease(LastWrittenLsnLock); - - return lsn; -} - -/* - * SetLastWrittenLSNForBlockv -- Set maximal LSN of pages to their respective - * LSNs. - * - * We maintain cache of last written LSNs with limited size and LRU replacement - * policy. Keeping last written LSN for each page allows to use old LSN when - * requesting pages of unchanged or appended relations. Also it is critical for - * efficient work of prefetch in case massive update operations (like vacuum or remove). - */ -XLogRecPtr -SetLastWrittenLSNForBlockv(const XLogRecPtr *lsns, RelFileLocator relfilenode, - ForkNumber forknum, BlockNumber blockno, - int nblocks) -{ - LastWrittenLsnCacheEntry* entry; - BufferTag key; - bool found; - XLogRecPtr max = InvalidXLogRecPtr; - - if (lsns == NULL || nblocks == 0 || lastWrittenLsnCacheSize == 0 || - relfilenode.relNumber == InvalidOid) - return InvalidXLogRecPtr; - - key.relNumber = relfilenode.relNumber; - key.dbOid = relfilenode.dbOid; - key.spcOid = relfilenode.spcOid; - key.forkNum = forknum; - - LWLockAcquire(LastWrittenLsnLock, LW_EXCLUSIVE); - - for (int i = 0; i < nblocks; i++) - { - XLogRecPtr lsn = lsns[i]; - - key.blockNum = blockno + i; - entry = hash_search(lastWrittenLsnCache, &key, HASH_ENTER, &found); - if (found) - { - if (lsn > entry->lsn) - entry->lsn = lsn; - else - lsn = entry->lsn; - /* Unlink from LRU list */ - dlist_delete(&entry->lru_node); - } - else - { - entry->lsn = lsn; - if (hash_get_num_entries(lastWrittenLsnCache) > lastWrittenLsnCacheSize) - { - /* Replace least recently used entry */ - LastWrittenLsnCacheEntry* victim = dlist_container(LastWrittenLsnCacheEntry, lru_node, dlist_pop_head_node(&XLogCtl->lastWrittenLsnLRU)); - /* Adjust max LSN for not cached relations/chunks if needed */ - if (victim->lsn > XLogCtl->maxLastWrittenLsn) - XLogCtl->maxLastWrittenLsn = victim->lsn; - - hash_search(lastWrittenLsnCache, victim, HASH_REMOVE, NULL); - } - } - /* Link to the end of LRU list */ - dlist_push_tail(&XLogCtl->lastWrittenLsnLRU, &entry->lru_node); - max = Max(max, lsn); - } - - LWLockRelease(LastWrittenLsnLock); - - return max; -} - -/* - * SetLastWrittenLSNForBlock -- Set maximal LSN for block - */ -XLogRecPtr -SetLastWrittenLSNForBlock(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno) -{ - return SetLastWrittenLSNForBlockRange(lsn, rlocator, forknum, blkno, 1); -} - -/* - * SetLastWrittenLSNForRelation -- Set maximal LSN for relation metadata - */ -XLogRecPtr -SetLastWrittenLSNForRelation(XLogRecPtr lsn, RelFileLocator rlocator, ForkNumber forknum) -{ - return SetLastWrittenLSNForBlock(lsn, rlocator, forknum, REL_METADATA_PSEUDO_BLOCKNO); -} - -/* - * SetLastWrittenLSNForDatabase -- Set maximal LSN for the whole database - */ -XLogRecPtr -SetLastWrittenLSNForDatabase(XLogRecPtr lsn) -{ - RelFileLocator dummyNode = {InvalidOid, InvalidOid, InvalidOid}; - return SetLastWrittenLSNForBlock(lsn, dummyNode, MAIN_FORKNUM, 0); -} - void SetRedoStartLsn(XLogRecPtr RedoStartLSN) { diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index a97e7dc25d3..e0dc76209ce 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -197,7 +197,8 @@ log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum) XLogBeginInsert(); XLogRegisterData((char *) &xlrec, sizeof(xlrec)); lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE | XLR_SPECIAL_REL_UPDATE); - SetLastWrittenLSNForRelation(lsn, *rlocator, forkNum); + if (set_lwlsn_relation_hook) + set_lwlsn_relation_hook(lsn, *rlocator, forkNum); } /* diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 253c3c36c99..a8478e61b43 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -1515,7 +1515,8 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) /* * Update global last written LSN after wal-logging create database command */ - SetLastWrittenLSNForDatabase(XactLastRecEnd); + if (set_lwlsn_db_hook) + set_lwlsn_db_hook(XactLastRecEnd); /* * Close pg_database, but keep lock till commit. @@ -2182,7 +2183,8 @@ movedb(const char *dbname, const char *tblspcname) lsn = XLogInsert(RM_DBASE_ID, XLOG_DBASE_CREATE_FILE_COPY | XLR_SPECIAL_REL_UPDATE); // TODO: Do we really need to set the LSN here? - SetLastWrittenLSNForDatabase(lsn); + if (set_lwlsn_db_hook) + set_lwlsn_db_hook(lsn); } /* @@ -3355,10 +3357,9 @@ dbase_redo(XLogReaderState *record) * Make sure any future requests to the page server see the new * database. */ - { - XLogRecPtr lsn = record->EndRecPtr; - SetLastWrittenLSNForDatabase(lsn); - } + if (set_lwlsn_db_hook) + set_lwlsn_db_hook(record->EndRecPtr); + pfree(src_path); pfree(dst_path); @@ -3385,10 +3386,8 @@ dbase_redo(XLogReaderState *record) * Make sure any future requests to the page server see the new * database. */ - { - XLogRecPtr lsn = record->EndRecPtr; - SetLastWrittenLSNForDatabase(lsn); - } + if (set_lwlsn_db_hook) + set_lwlsn_db_hook(record->EndRecPtr); pfree(dbpath); } diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 743be6fcc3e..5ec8d12570d 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -2410,16 +2410,6 @@ struct config_int ConfigureNamesInt[] = check_transaction_buffers, NULL, NULL }, - { - {"lsn_cache_size", PGC_POSTMASTER, UNGROUPED, - gettext_noop("Size of last written LSN cache used by Neon."), - NULL - }, - &lastWrittenLsnCacheSize, - 128*1024, 1024, INT_MAX, - NULL, NULL, NULL - }, - { {"temp_buffers", PGC_USERSET, RESOURCES_MEM, gettext_noop("Sets the maximum number of temporary buffers used by each session."), diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 3a92973bf2f..eb1ebf4101d 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -68,7 +68,6 @@ extern PGDLLIMPORT bool track_wal_io_timing; extern PGDLLIMPORT int wal_decode_buffer_size; extern PGDLLIMPORT int CheckPointSegments; -extern int lastWrittenLsnCacheSize; /* Archive modes */ @@ -267,17 +266,6 @@ extern XLogRecPtr GetLastImportantRecPtr(void); /* neon specifics */ -extern XLogRecPtr SetLastWrittenLSNForBlock(XLogRecPtr lsn, RelFileLocator relfilenode, ForkNumber forknum, BlockNumber blkno); -extern XLogRecPtr SetLastWrittenLSNForBlockv(const XLogRecPtr *lsns, RelFileLocator relfilenode, - ForkNumber forknum, BlockNumber blockno, - int nblocks); -extern XLogRecPtr SetLastWrittenLSNForBlockRange(XLogRecPtr lsn, RelFileLocator relfilenode, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks); -extern XLogRecPtr SetLastWrittenLSNForDatabase(XLogRecPtr lsn); -extern XLogRecPtr SetLastWrittenLSNForRelation(XLogRecPtr lsn, RelFileLocator relfilenode, ForkNumber forknum); -extern XLogRecPtr GetLastWrittenLSN(RelFileLocator relfilenode, ForkNumber forknum, BlockNumber blkno); -extern void GetLastWrittenLSNv(RelFileLocator relfilenode, ForkNumber forknum, - BlockNumber blkno, int nblocks, XLogRecPtr *lsns); - extern void SetRedoStartLsn(XLogRecPtr RedoStartLSN); extern XLogRecPtr GetRedoStartLsn(void); @@ -286,6 +274,21 @@ extern void SetWalWriterSleeping(bool sleeping); extern Size WALReadFromBuffers(char *dstbuf, XLogRecPtr startptr, Size count, TimeLineID tli); +/* Hooks for LwLSN */ +typedef XLogRecPtr (*set_lwlsn_block_hook_type)(XLogRecPtr lsn, RelFileLocator relfilenode, ForkNumber forknum, BlockNumber blkno); +typedef XLogRecPtr (*set_lwlsn_block_range_hook_type)(XLogRecPtr lsn, RelFileLocator relfilenode, ForkNumber forknum, BlockNumber from, BlockNumber n_blocks); +typedef XLogRecPtr (*set_lwlsn_block_v_hook_type)(const XLogRecPtr *lsns, RelFileLocator relfilenode, ForkNumber forknum, BlockNumber blockno, int nblocks); +typedef XLogRecPtr (*set_lwlsn_db_hook_type)(XLogRecPtr lsn); +typedef XLogRecPtr (*set_lwlsn_relation_hook_type)(XLogRecPtr lsn, RelFileLocator relfilenode, ForkNumber forknum); +typedef void (*set_max_lwlsn_hook_type) (XLogRecPtr lsn); + +extern set_lwlsn_block_hook_type set_lwlsn_block_hook; +extern set_lwlsn_block_range_hook_type set_lwlsn_block_range_hook; +extern set_lwlsn_block_v_hook_type set_lwlsn_block_v_hook; +extern set_lwlsn_db_hook_type set_lwlsn_db_hook; +extern set_lwlsn_relation_hook_type set_lwlsn_relation_hook; +extern set_max_lwlsn_hook_type set_max_lwlsn_hook; + /* * Routines used by xlogrecovery.c to call back into xlog.c during recovery. */