Move WAL sequence code into its own file

This split exists for most of the other RMGRs, and makes cleaner the
separation between the WAL code, the redo code and the record
description code (already in its own file) when it comes to the sequence
RMGR.  The redo and masking routines are moved to a new file,
sequence_xlog.c.  All the RMGR routines are now located in a new header,
sequence_xlog.h.

This separation is useful for a different patch related to sequences
that I have been working on, where it makes a refactoring of sequence.c
easier if its RMGR routines and its core routines are split.

Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Discussion: https://postgr.es/m/aSfTxIWjiXkTKh1E@paquier.xyz
This commit is contained in:
Michael Paquier 2025-12-01 16:21:41 +09:00
parent d03668ea05
commit a87987cafc
9 changed files with 132 additions and 95 deletions

View File

@ -14,7 +14,7 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "commands/sequence.h" #include "commands/sequence_xlog.h"
void void

View File

@ -33,7 +33,7 @@
#include "access/xact.h" #include "access/xact.h"
#include "catalog/storage_xlog.h" #include "catalog/storage_xlog.h"
#include "commands/dbcommands_xlog.h" #include "commands/dbcommands_xlog.h"
#include "commands/sequence.h" #include "commands/sequence_xlog.h"
#include "commands/tablespace.h" #include "commands/tablespace.h"
#include "replication/decode.h" #include "replication/decode.h"
#include "replication/message.h" #include "replication/message.h"

View File

@ -53,6 +53,7 @@ OBJS = \
schemacmds.o \ schemacmds.o \
seclabel.o \ seclabel.o \
sequence.o \ sequence.o \
sequence_xlog.o \
statscmds.o \ statscmds.o \
subscriptioncmds.o \ subscriptioncmds.o \
tablecmds.o \ tablecmds.o \

View File

@ -41,6 +41,7 @@ backend_sources += files(
'schemacmds.c', 'schemacmds.c',
'seclabel.c', 'seclabel.c',
'sequence.c', 'sequence.c',
'sequence_xlog.c',
'statscmds.c', 'statscmds.c',
'subscriptioncmds.c', 'subscriptioncmds.c',
'tablecmds.c', 'tablecmds.c',

View File

@ -14,7 +14,6 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/bufmask.h"
#include "access/htup_details.h" #include "access/htup_details.h"
#include "access/multixact.h" #include "access/multixact.h"
#include "access/relation.h" #include "access/relation.h"
@ -22,9 +21,7 @@
#include "access/table.h" #include "access/table.h"
#include "access/transam.h" #include "access/transam.h"
#include "access/xact.h" #include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h" #include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/dependency.h" #include "catalog/dependency.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
@ -34,11 +31,13 @@
#include "catalog/storage_xlog.h" #include "catalog/storage_xlog.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "commands/sequence.h" #include "commands/sequence.h"
#include "commands/sequence_xlog.h"
#include "commands/tablecmds.h" #include "commands/tablecmds.h"
#include "funcapi.h" #include "funcapi.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h" #include "storage/lmgr.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "storage/smgr.h" #include "storage/smgr.h"
@ -58,16 +57,6 @@
*/ */
#define SEQ_LOG_VALS 32 #define SEQ_LOG_VALS 32
/*
* The "special area" of a sequence's buffer page looks like this.
*/
#define SEQ_MAGIC 0x1717
typedef struct sequence_magic
{
uint32 magic;
} sequence_magic;
/* /*
* We store a SeqTable item for every sequence we have touched in the current * We store a SeqTable item for every sequence we have touched in the current
* session. This is needed to hold onto nextval/currval state. (We can't * session. This is needed to hold onto nextval/currval state. (We can't
@ -1907,56 +1896,6 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
void
seq_redo(XLogReaderState *record)
{
XLogRecPtr lsn = record->EndRecPtr;
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
Buffer buffer;
Page page;
Page localpage;
char *item;
Size itemsz;
xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
sequence_magic *sm;
if (info != XLOG_SEQ_LOG)
elog(PANIC, "seq_redo: unknown op code %u", info);
buffer = XLogInitBufferForRedo(record, 0);
page = BufferGetPage(buffer);
/*
* We always reinit the page. However, since this WAL record type is also
* used for updating sequences, it's possible that a hot-standby backend
* is examining the page concurrently; so we mustn't transiently trash the
* buffer. The solution is to build the correct new page contents in
* local workspace and then memcpy into the buffer. Then only bytes that
* are supposed to change will change, even transiently. We must palloc
* the local page for alignment reasons.
*/
localpage = (Page) palloc(BufferGetPageSize(buffer));
PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
sm = (sequence_magic *) PageGetSpecialPointer(localpage);
sm->magic = SEQ_MAGIC;
item = (char *) xlrec + sizeof(xl_seq_rec);
itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
if (PageAddItem(localpage, item, itemsz, FirstOffsetNumber, false, false) == InvalidOffsetNumber)
elog(PANIC, "seq_redo: failed to add item to page");
PageSetLSN(localpage, lsn);
memcpy(page, localpage, BufferGetPageSize(buffer));
MarkBufferDirty(buffer);
UnlockReleaseBuffer(buffer);
pfree(localpage);
}
/* /*
* Flush cached sequence information. * Flush cached sequence information.
*/ */
@ -1971,14 +1910,3 @@ ResetSequenceCaches(void)
last_used_seq = NULL; last_used_seq = NULL;
} }
/*
* Mask a Sequence page before performing consistency checks on it.
*/
void
seq_mask(char *page, BlockNumber blkno)
{
mask_page_lsn_and_checksum(page);
mask_unused_space(page);
}

View File

@ -0,0 +1,80 @@
/*-------------------------------------------------------------------------
*
* sequence.c
* RMGR WAL routines for sequences.
*
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/backend/commands/sequence_xlog.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/bufmask.h"
#include "access/xlogutils.h"
#include "commands/sequence_xlog.h"
#include "storage/bufmgr.h"
void
seq_redo(XLogReaderState *record)
{
XLogRecPtr lsn = record->EndRecPtr;
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
Buffer buffer;
Page page;
Page localpage;
char *item;
Size itemsz;
xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
sequence_magic *sm;
if (info != XLOG_SEQ_LOG)
elog(PANIC, "seq_redo: unknown op code %u", info);
buffer = XLogInitBufferForRedo(record, 0);
page = BufferGetPage(buffer);
/*
* We always reinit the page. However, since this WAL record type is also
* used for updating sequences, it's possible that a hot-standby backend
* is examining the page concurrently; so we mustn't transiently trash the
* buffer. The solution is to build the correct new page contents in
* local workspace and then memcpy into the buffer. Then only bytes that
* are supposed to change will change, even transiently. We must palloc
* the local page for alignment reasons.
*/
localpage = (Page) palloc(BufferGetPageSize(buffer));
PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
sm = (sequence_magic *) PageGetSpecialPointer(localpage);
sm->magic = SEQ_MAGIC;
item = (char *) xlrec + sizeof(xl_seq_rec);
itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
if (PageAddItem(localpage, item, itemsz, FirstOffsetNumber, false, false) == InvalidOffsetNumber)
elog(PANIC, "seq_redo: failed to add item to page");
PageSetLSN(localpage, lsn);
memcpy(page, localpage, BufferGetPageSize(buffer));
MarkBufferDirty(buffer);
UnlockReleaseBuffer(buffer);
pfree(localpage);
}
/*
* Mask a Sequence page before performing consistency checks on it.
*/
void
seq_mask(char *page, BlockNumber blkno)
{
mask_page_lsn_and_checksum(page);
mask_unused_space(page);
}

View File

@ -24,7 +24,7 @@
#include "access/xlog_internal.h" #include "access/xlog_internal.h"
#include "catalog/storage_xlog.h" #include "catalog/storage_xlog.h"
#include "commands/dbcommands_xlog.h" #include "commands/dbcommands_xlog.h"
#include "commands/sequence.h" #include "commands/sequence_xlog.h"
#include "commands/tablespace.h" #include "commands/tablespace.h"
#include "replication/message.h" #include "replication/message.h"
#include "replication/origin.h" #include "replication/origin.h"

View File

@ -13,14 +13,10 @@
#ifndef SEQUENCE_H #ifndef SEQUENCE_H
#define SEQUENCE_H #define SEQUENCE_H
#include "access/xlogreader.h"
#include "catalog/objectaddress.h" #include "catalog/objectaddress.h"
#include "fmgr.h" #include "fmgr.h"
#include "lib/stringinfo.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "parser/parse_node.h" #include "parser/parse_node.h"
#include "storage/relfilelocator.h"
typedef struct FormData_pg_sequence_data typedef struct FormData_pg_sequence_data
{ {
@ -42,15 +38,6 @@ typedef FormData_pg_sequence_data *Form_pg_sequence_data;
#define SEQ_COL_FIRSTCOL SEQ_COL_LASTVAL #define SEQ_COL_FIRSTCOL SEQ_COL_LASTVAL
#define SEQ_COL_LASTCOL SEQ_COL_CALLED #define SEQ_COL_LASTCOL SEQ_COL_CALLED
/* XLOG stuff */
#define XLOG_SEQ_LOG 0x00
typedef struct xl_seq_rec
{
RelFileLocator locator;
/* SEQUENCE TUPLE DATA FOLLOWS AT THE END */
} xl_seq_rec;
extern int64 nextval_internal(Oid relid, bool check_permissions); extern int64 nextval_internal(Oid relid, bool check_permissions);
extern Datum nextval(PG_FUNCTION_ARGS); extern Datum nextval(PG_FUNCTION_ARGS);
extern List *sequence_options(Oid relid); extern List *sequence_options(Oid relid);
@ -63,9 +50,4 @@ extern void ResetSequence(Oid seq_relid);
extern void SetSequence(Oid relid, int64 next, bool is_called); extern void SetSequence(Oid relid, int64 next, bool is_called);
extern void ResetSequenceCaches(void); extern void ResetSequenceCaches(void);
extern void seq_redo(XLogReaderState *record);
extern void seq_desc(StringInfo buf, XLogReaderState *record);
extern const char *seq_identify(uint8 info);
extern void seq_mask(char *page, BlockNumber blkno);
#endif /* SEQUENCE_H */ #endif /* SEQUENCE_H */

View File

@ -0,0 +1,45 @@
/*-------------------------------------------------------------------------
*
* sequence_xlog.h
* Sequence WAL definitions.
*
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/commands/sequence_xlog.h
*
*-------------------------------------------------------------------------
*/
#ifndef SEQUENCE_XLOG_H
#define SEQUENCE_XLOG_H
#include "access/xlogreader.h"
#include "lib/stringinfo.h"
/* Record identifier */
#define XLOG_SEQ_LOG 0x00
/*
* The "special area" of a sequence's buffer page looks like this.
*/
#define SEQ_MAGIC 0x1717
typedef struct sequence_magic
{
uint32 magic;
} sequence_magic;
/* Sequence WAL record */
typedef struct xl_seq_rec
{
RelFileLocator locator;
/* SEQUENCE TUPLE DATA FOLLOWS AT THE END */
} xl_seq_rec;
extern void seq_redo(XLogReaderState *record);
extern void seq_desc(StringInfo buf, XLogReaderState *record);
extern const char *seq_identify(uint8 info);
extern void seq_mask(char *page, BlockNumber blkno);
#endif /* SEQUENCE_XLOG_H */