Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * message.c 4 : * Generic logical messages. 5 : * 6 : * Copyright (c) 2013-2020, PostgreSQL Global Development Group 7 : * 8 : * IDENTIFICATION 9 : * src/backend/replication/logical/message.c 10 : * 11 : * NOTES 12 : * 13 : * Generic logical messages allow XLOG logging of arbitrary binary blobs that 14 : * get passed to the logical decoding plugin. In normal XLOG processing they 15 : * are same as NOOP. 16 : * 17 : * These messages can be either transactional or non-transactional. 18 : * Transactional messages are part of current transaction and will be sent to 19 : * decoding plugin using in a same way as DML operations. 20 : * Non-transactional messages are sent to the plugin at the time when the 21 : * logical decoding reads them from XLOG. This also means that transactional 22 : * messages won't be delivered if the transaction was rolled back but the 23 : * non-transactional one will always be delivered. 24 : * 25 : * Every message carries prefix to avoid conflicts between different decoding 26 : * plugins. The plugin authors must take extra care to use unique prefix, 27 : * good options seems to be for example to use the name of the extension. 28 : * 29 : * --------------------------------------------------------------------------- 30 : */ 31 : 32 : #include "postgres.h" 33 : 34 : #include "access/xact.h" 35 : #include "miscadmin.h" 36 : #include "nodes/execnodes.h" 37 : #include "replication/logical.h" 38 : #include "replication/message.h" 39 : #include "utils/memutils.h" 40 : 41 : /* 42 : * Write logical decoding message into XLog. 43 : */ 44 : XLogRecPtr 45 32 : LogLogicalMessage(const char *prefix, const char *message, size_t size, 46 : bool transactional) 47 : { 48 : xl_logical_message xlrec; 49 : 50 : /* 51 : * Force xid to be allocated if we're emitting a transactional message. 52 : */ 53 32 : if (transactional) 54 : { 55 22 : Assert(IsTransactionState()); 56 22 : GetCurrentTransactionId(); 57 : } 58 : 59 32 : xlrec.dbId = MyDatabaseId; 60 32 : xlrec.transactional = transactional; 61 : /* trailing zero is critical; see logicalmsg_desc */ 62 32 : xlrec.prefix_size = strlen(prefix) + 1; 63 32 : xlrec.message_size = size; 64 : 65 32 : XLogBeginInsert(); 66 32 : XLogRegisterData((char *) &xlrec, SizeOfLogicalMessage); 67 32 : XLogRegisterData(unconstify(char *, prefix), xlrec.prefix_size); 68 32 : XLogRegisterData(unconstify(char *, message), size); 69 : 70 : /* allow origin filtering */ 71 32 : XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN); 72 : 73 32 : return XLogInsert(RM_LOGICALMSG_ID, XLOG_LOGICAL_MESSAGE); 74 : } 75 : 76 : /* 77 : * Redo is basically just noop for logical decoding messages. 78 : */ 79 : void 80 0 : logicalmsg_redo(XLogReaderState *record) 81 : { 82 0 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; 83 : 84 0 : if (info != XLOG_LOGICAL_MESSAGE) 85 0 : elog(PANIC, "logicalmsg_redo: unknown op code %u", info); 86 : 87 : /* This is only interesting for logical decoding, see decode.c. */ 88 0 : }