/* * DistributedLog resource manager's routines */ void DistributedLog_redo(XLogRecPtr beginLoc, XLogRecPtr lsn, XLogRecord *record) { MIRRORED_LOCK_DECLARE; uint8 info = record->xl_info & ~XLR_INFO_MASK; MIRRORED_LOCK; if (info == DISTRIBUTEDLOG_ZEROPAGE) { int page; int slotno; memcpy(&page, XLogRecGetData(record), sizeof(int)); elog((Debug_print_full_dtm ? LOG : DEBUG5), "Redo DISTRIBUTEDLOG_ZEROPAGE page %d", page); LWLockAcquire(DistributedLogControlLock, LW_EXCLUSIVE); slotno = DistributedLog_ZeroPage(page, false); SimpleLruWritePage(DistributedLogCtl, slotno, NULL); Assert(!DistributedLogCtl->shared->page_dirty[slotno]); LWLockRelease(DistributedLogControlLock); elog((Debug_print_full_dtm ? LOG : DEBUG5), "DistributedLog_redo zero page = %d", page); } else if (info == DISTRIBUTEDLOG_TRUNCATE) { int page; memcpy(&page, XLogRecGetData(record), sizeof(int)); elog((Debug_print_full_dtm ? LOG : DEBUG5), "Redo DISTRIBUTEDLOG_TRUNCATE page %d", page); /* * During XLOG replay, latest_page_number isn't set up yet; insert * a suitable value to bypass the sanity test in SimpleLruTruncate. */ DistributedLogCtl->shared->latest_page_number = page; SimpleLruTruncate(DistributedLogCtl, page); elog((Debug_print_full_dtm ? LOG : DEBUG5), "DistributedLog_redo truncate to cutoff page = %d", page); } else elog(PANIC, "DistributedLog_redo: unknown op code %u", info); MIRRORED_UNLOCK; }
/* * Remove all SUBTRANS segments before the one holding the passed transaction ID * * This is normally called during checkpoint, with oldestXact being the * oldest TransactionXmin of any running transaction. */ void TruncateSUBTRANS(TransactionId oldestXact) { int cutoffPage; /* * The cutoff point is the start of the segment containing oldestXact. We * pass the *page* containing oldestXact to SimpleLruTruncate. */ cutoffPage = TransactionIdToPage(oldestXact); SimpleLruTruncate(SubTransCtl, cutoffPage); }
/* * Remove all DistributedXidMap segments before the one holding the passed * DTM Global XID. * * This is normally called when a distributed snapshot arrives indicating the * xmin of all current distributed snapshots has moved forward. */ void TruncateDistributedXidMap(DistributedTransactionId oldestXact) { int cutoffPage; /* * The cutoff point is the start of the segment containing oldestXact. We * pass the *page* containing oldestXact to SimpleLruTruncate. */ cutoffPage = DistributedTransactionIdToPage(oldestXact); // UNDONE: Save cutoff page and don't call SimpleLruTruncate when there // is no change to the cuttoff page. SimpleLruTruncate(DistributedXidMapCtl, cutoffPage, false); }
/* * Remove all SUBTRANS segments before the one holding the passed transaction ID * * This is normally called during checkpoint, with oldestXact being the * oldest TransactionXmin of any running transaction. */ void TruncateSUBTRANS(TransactionId oldestXact) { int cutoffPage; /* * The cutoff point is the start of the segment containing oldestXact. We * pass the *page* containing oldestXact to SimpleLruTruncate. We step * back one transaction to avoid passing a cutoff page that hasn't been * created yet in the rare case that oldestXact would be the first item on * a page and oldestXact == next XID. In that case, if we didn't subtract * one, we'd trigger SimpleLruTruncate's wraparound detection. */ TransactionIdRetreat(oldestXact); cutoffPage = TransactionIdToPage(oldestXact); SimpleLruTruncate(SubTransCtl, cutoffPage); }
/* * Remove all SUBTRANS segments before the one holding the passed transaction ID * * This is normally called during checkpoint, with oldestXact being the * oldest TransactionXmin of any running transaction. */ void TruncateSUBTRANS(TransactionId oldestXact) { MIRRORED_LOCK_DECLARE; int cutoffPage; /* * The cutoff point is the start of the segment containing oldestXact. We * pass the *page* containing oldestXact to SimpleLruTruncate. */ cutoffPage = TransactionIdToPage(oldestXact); MIRRORED_LOCK; SimpleLruTruncate(SubTransCtl, cutoffPage, false); MIRRORED_UNLOCK; }
/* * Remove all CommitTs segments before the one holding the passed * transaction ID. * * Note that we don't need to flush XLOG here. */ void TruncateCommitTs(TransactionId oldestXact) { int cutoffPage; /* * The cutoff point is the start of the segment containing oldestXact. We * pass the *page* containing oldestXact to SimpleLruTruncate. */ cutoffPage = TransactionIdToCTsPage(oldestXact); /* Check to see if there's any files that could be removed */ if (!SlruScanDirectory(CommitTsCtl, SlruScanDirCbReportPresence, &cutoffPage)) return; /* nothing to remove */ /* Write XLOG record */ WriteTruncateXlogRec(cutoffPage); /* Now we can remove the old CommitTs segment(s) */ SimpleLruTruncate(CommitTsCtl, cutoffPage); }
/* * CommitTS resource manager's routines */ void commit_ts_redo(XLogReaderState *record) { uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; /* Backup blocks are not used in commit_ts records */ Assert(!XLogRecHasAnyBlockRefs(record)); if (info == COMMIT_TS_ZEROPAGE) { int pageno; int slotno; memcpy(&pageno, XLogRecGetData(record), sizeof(int)); LWLockAcquire(CommitTsControlLock, LW_EXCLUSIVE); slotno = ZeroCommitTsPage(pageno, false); SimpleLruWritePage(CommitTsCtl, slotno); Assert(!CommitTsCtl->shared->page_dirty[slotno]); LWLockRelease(CommitTsControlLock); } else if (info == COMMIT_TS_TRUNCATE) { int pageno; memcpy(&pageno, XLogRecGetData(record), sizeof(int)); /* * During XLOG replay, latest_page_number isn't set up yet; insert a * suitable value to bypass the sanity test in SimpleLruTruncate. */ CommitTsCtl->shared->latest_page_number = pageno; SimpleLruTruncate(CommitTsCtl, pageno); } else if (info == COMMIT_TS_SETTS) { xl_commit_ts_set *setts = (xl_commit_ts_set *) XLogRecGetData(record); int nsubxids; TransactionId *subxids; nsubxids = ((XLogRecGetDataLen(record) - SizeOfCommitTsSet) / sizeof(TransactionId)); if (nsubxids > 0) { subxids = palloc(sizeof(TransactionId) * nsubxids); memcpy(subxids, XLogRecGetData(record) + SizeOfCommitTsSet, sizeof(TransactionId) * nsubxids); } else subxids = NULL; TransactionTreeSetCommitTsData(setts->mainxid, nsubxids, subxids, setts->timestamp, setts->nodeid, true); if (subxids) pfree(subxids); } else elog(PANIC, "commit_ts_redo: unknown op code %u", info); }