aboutsummaryrefslogtreecommitdiff
path: root/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c')
-rw-r--r--src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c b/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c
new file mode 100644
index 00000000000..6e5270bf839
--- /dev/null
+++ b/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c
@@ -0,0 +1,139 @@
+/*--------------------------------------------------------------------------
+ *
+ * test_custom_rmgrs.c
+ * Code for testing custom WAL resource managers.
+ *
+ * Portions Copyright (c) 1996-2022, 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"
+
+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 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);
+}