Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * sequence.c 4 : * RMGR WAL routines for sequences. 5 : * 6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group 7 : * Portions Copyright (c) 1994, Regents of the University of California 8 : * 9 : * 10 : * IDENTIFICATION 11 : * src/backend/commands/sequence_xlog.c 12 : * 13 : *------------------------------------------------------------------------- 14 : */ 15 : #include "postgres.h" 16 : 17 : #include "access/bufmask.h" 18 : #include "access/xlogutils.h" 19 : #include "commands/sequence_xlog.h" 20 : #include "storage/bufmgr.h" 21 : 22 : void 23 4650 : seq_redo(XLogReaderState *record) 24 : { 25 4650 : XLogRecPtr lsn = record->EndRecPtr; 26 4650 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; 27 : Buffer buffer; 28 : Page page; 29 : Page localpage; 30 : char *item; 31 : Size itemsz; 32 4650 : xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record); 33 : sequence_magic *sm; 34 : 35 4650 : if (info != XLOG_SEQ_LOG) 36 0 : elog(PANIC, "seq_redo: unknown op code %u", info); 37 : 38 4650 : buffer = XLogInitBufferForRedo(record, 0); 39 4650 : page = BufferGetPage(buffer); 40 : 41 : /* 42 : * We always reinit the page. However, since this WAL record type is also 43 : * used for updating sequences, it's possible that a hot-standby backend 44 : * is examining the page concurrently; so we mustn't transiently trash the 45 : * buffer. The solution is to build the correct new page contents in 46 : * local workspace and then memcpy into the buffer. Then only bytes that 47 : * are supposed to change will change, even transiently. We must palloc 48 : * the local page for alignment reasons. 49 : */ 50 4650 : localpage = (Page) palloc(BufferGetPageSize(buffer)); 51 : 52 4650 : PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic)); 53 4650 : sm = (sequence_magic *) PageGetSpecialPointer(localpage); 54 4650 : sm->magic = SEQ_MAGIC; 55 : 56 4650 : item = (char *) xlrec + sizeof(xl_seq_rec); 57 4650 : itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec); 58 : 59 4650 : if (PageAddItem(localpage, item, itemsz, FirstOffsetNumber, false, false) == InvalidOffsetNumber) 60 0 : elog(PANIC, "seq_redo: failed to add item to page"); 61 : 62 4650 : PageSetLSN(localpage, lsn); 63 : 64 4650 : memcpy(page, localpage, BufferGetPageSize(buffer)); 65 4650 : MarkBufferDirty(buffer); 66 4650 : UnlockReleaseBuffer(buffer); 67 : 68 4650 : pfree(localpage); 69 4650 : } 70 : 71 : /* 72 : * Mask a Sequence page before performing consistency checks on it. 73 : */ 74 : void 75 2372 : seq_mask(char *page, BlockNumber blkno) 76 : { 77 2372 : mask_page_lsn_and_checksum(page); 78 : 79 2372 : mask_unused_space(page); 80 2372 : }