1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/*--------------------------------------------------------------------------
*
* test_custom_rmgrs.c
* Code for testing custom WAL resource managers.
*
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c
*
* Custom WAL resource manager for records containing a simple textual
* payload, no-op redo, and no decoding.
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xloginsert.h"
#include "fmgr.h"
#include "utils/pg_lsn.h"
#include "varatt.h"
PG_MODULE_MAGIC;
/*
* test_custom_rmgrs WAL record message.
*/
typedef struct xl_testcustomrmgrs_message
{
Size message_size; /* size of the message */
char message[FLEXIBLE_ARRAY_MEMBER]; /* payload */
} xl_testcustomrmgrs_message;
#define SizeOfTestCustomRmgrsMessage (offsetof(xl_testcustomrmgrs_message, message))
#define XLOG_TEST_CUSTOM_RMGRS_MESSAGE 0x00
/*
* While developing or testing, use RM_EXPERIMENTAL_ID for rmid. For a real
* extension, reserve a new resource manager ID to avoid conflicting with
* other extensions; see:
* https://wiki.postgresql.org/wiki/CustomWALResourceManagers
*/
#define RM_TESTCUSTOMRMGRS_ID RM_EXPERIMENTAL_ID
#define TESTCUSTOMRMGRS_NAME "test_custom_rmgrs"
/* RMGR API, see xlog_internal.h */
void testcustomrmgrs_redo(XLogReaderState *record);
void testcustomrmgrs_desc(StringInfo buf, XLogReaderState *record);
const char *testcustomrmgrs_identify(uint8 info);
static const RmgrData testcustomrmgrs_rmgr = {
.rm_name = TESTCUSTOMRMGRS_NAME,
.rm_redo = testcustomrmgrs_redo,
.rm_desc = testcustomrmgrs_desc,
.rm_identify = testcustomrmgrs_identify
};
/*
* Module load callback
*/
void
_PG_init(void)
{
/*
* In order to create our own custom resource manager, we have to be
* loaded via shared_preload_libraries. Otherwise, registration will fail.
*/
RegisterCustomRmgr(RM_TESTCUSTOMRMGRS_ID, &testcustomrmgrs_rmgr);
}
/* RMGR API implementation */
/*
* Redo is just a noop for this module, because we aren't testing recovery of
* any real structure.
*/
void
testcustomrmgrs_redo(XLogReaderState *record)
{
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
if (info != XLOG_TEST_CUSTOM_RMGRS_MESSAGE)
elog(PANIC, "testcustomrmgrs_redo: unknown op code %u", info);
}
void
testcustomrmgrs_desc(StringInfo buf, XLogReaderState *record)
{
char *rec = XLogRecGetData(record);
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
if (info == XLOG_TEST_CUSTOM_RMGRS_MESSAGE)
{
xl_testcustomrmgrs_message *xlrec = (xl_testcustomrmgrs_message *) rec;
appendStringInfo(buf, "payload (%zu bytes): ", xlrec->message_size);
appendBinaryStringInfo(buf, xlrec->message, xlrec->message_size);
}
}
const char *
testcustomrmgrs_identify(uint8 info)
{
if ((info & ~XLR_INFO_MASK) == XLOG_TEST_CUSTOM_RMGRS_MESSAGE)
return "TEST_CUSTOM_RMGRS_MESSAGE";
return NULL;
}
/*
* SQL function for writing a simple message into WAL with the help of custom
* WAL resource manager.
*/
PG_FUNCTION_INFO_V1(test_custom_rmgrs_insert_wal_record);
Datum
test_custom_rmgrs_insert_wal_record(PG_FUNCTION_ARGS)
{
text *arg = PG_GETARG_TEXT_PP(0);
char *payload = VARDATA_ANY(arg);
Size len = VARSIZE_ANY_EXHDR(arg);
XLogRecPtr lsn;
xl_testcustomrmgrs_message xlrec;
xlrec.message_size = len;
XLogBeginInsert();
XLogRegisterData((char *) &xlrec, SizeOfTestCustomRmgrsMessage);
XLogRegisterData((char *) payload, len);
/* Let's mark this record as unimportant, just in case. */
XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT);
lsn = XLogInsert(RM_TESTCUSTOMRMGRS_ID, XLOG_TEST_CUSTOM_RMGRS_MESSAGE);
PG_RETURN_LSN(lsn);
}
|