Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * sequence.c 4 : * RMGR WAL routines for sequences. 5 : * 6 : * Portions Copyright (c) 1996-2026, 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 4676 : seq_redo(XLogReaderState *record) 24 : { 25 4676 : XLogRecPtr lsn = record->EndRecPtr; 26 4676 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; 27 : Buffer buffer; 28 : Page page; 29 : Page localpage; 30 : char *item; 31 : Size itemsz; 32 4676 : xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record); 33 : sequence_magic *sm; 34 : 35 4676 : if (info != XLOG_SEQ_LOG) 36 0 : elog(PANIC, "seq_redo: unknown op code %u", info); 37 : 38 4676 : buffer = XLogInitBufferForRedo(record, 0); 39 4676 : 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 4676 : localpage = (Page) palloc(BufferGetPageSize(buffer)); 51 : 52 4676 : PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic)); 53 4676 : sm = (sequence_magic *) PageGetSpecialPointer(localpage); 54 4676 : sm->magic = SEQ_MAGIC; 55 : 56 4676 : item = (char *) xlrec + sizeof(xl_seq_rec); 57 4676 : itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec); 58 : 59 4676 : if (PageAddItem(localpage, item, itemsz, FirstOffsetNumber, false, false) == InvalidOffsetNumber) 60 0 : elog(PANIC, "seq_redo: failed to add item to page"); 61 : 62 4676 : PageSetLSN(localpage, lsn); 63 : 64 4676 : memcpy(page, localpage, BufferGetPageSize(buffer)); 65 4676 : MarkBufferDirty(buffer); 66 4676 : UnlockReleaseBuffer(buffer); 67 : 68 4676 : pfree(localpage); 69 4676 : } 70 : 71 : /* 72 : * Mask a Sequence page before performing consistency checks on it. 73 : */ 74 : void 75 2424 : seq_mask(char *page, BlockNumber blkno) 76 : { 77 2424 : mask_page_lsn_and_checksum(page); 78 : 79 2424 : mask_unused_space(page); 80 2424 : }