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