Datum ipaddr_send(PG_FUNCTION_ARGS) { IP_P arg1 = PG_GETARG_IP_P(0); StringInfoData buf; IP ip; int af = ip_unpack(arg1, &ip); pq_begintypsend(&buf); pq_sendbyte(&buf, af); pq_sendbyte(&buf, ip_maxbits(af)); pq_sendbyte(&buf, 1); pq_sendbyte(&buf, ip_sizeof(af)); switch (af) { case PGSQL_AF_INET: pq_sendint(&buf, ip.ip4, sizeof(IP4)); break; case PGSQL_AF_INET6: pq_sendint64(&buf, ip.ip6.bits[0]); pq_sendint64(&buf, ip.ip6.bits[1]); break; } PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/* * Write COMMIT to the output stream. */ static void pglogical_write_commit(StringInfo out, PGLogicalOutputData *data, ReorderBufferTXN *txn, XLogRecPtr commit_lsn) { uint8 flags = 0; if (txn->xact_action == XLOG_XACT_COMMIT) flags = PGLOGICAL_COMMIT; else if (txn->xact_action == XLOG_XACT_PREPARE) flags = PGLOGICAL_PREPARE; else if (txn->xact_action == XLOG_XACT_COMMIT_PREPARED) flags = PGLOGICAL_COMMIT_PREPARED; else if (txn->xact_action == XLOG_XACT_ABORT_PREPARED) flags = PGLOGICAL_ABORT_PREPARED; else Assert(false); if (flags == PGLOGICAL_COMMIT || flags == PGLOGICAL_PREPARE) { if (MtmIsFilteredTxn) { return; } } else { csn_t csn = MtmTransactionSnapshot(txn->xid); bool isRecovery = MtmIsRecoveredNode(MtmReplicationNodeId); /* * INVALID_CSN means replicated transaction (transaction initiated by some other nodes). * We do not need to send such transactions unless we perform recovery */ if (csn == INVALID_CSN && !isRecovery) { return; } if (MtmRecoveryCaughtUp(MtmReplicationNodeId, txn->end_lsn)) { MTM_LOG1("wal-sender complete recovery of node %d at LSN(commit %lx, end %lx, log %lx) in transaction %s event %d", MtmReplicationNodeId, commit_lsn, txn->end_lsn, GetXLogInsertRecPtr(), txn->gid, flags); flags |= PGLOGICAL_CAUGHT_UP; } } pq_sendbyte(out, 'C'); /* sending COMMIT */ MTM_LOG2("PGLOGICAL_SEND commit: event=%d, gid=%s, commit_lsn=%lx, txn->end_lsn=%lx, xlog=%lx", flags, txn->gid, commit_lsn, txn->end_lsn, GetXLogInsertRecPtr()); /* send the flags field */ pq_sendbyte(out, flags); pq_sendbyte(out, MtmNodeId); /* send fixed fields */ pq_sendint64(out, commit_lsn); pq_sendint64(out, txn->end_lsn); pq_sendint64(out, txn->commit_time); if (txn->xact_action == XLOG_XACT_COMMIT_PREPARED) { pq_sendint64(out, MtmGetTransactionCSN(txn->xid)); } if (txn->xact_action != XLOG_XACT_COMMIT) { pq_sendstring(out, txn->gid); } }
/* * Write BEGIN to the output stream. */ void logicalrep_write_begin(StringInfo out, ReorderBufferTXN *txn) { pq_sendbyte(out, 'B'); /* BEGIN */ /* fixed fields */ pq_sendint64(out, txn->final_lsn); pq_sendint64(out, txn->commit_time); pq_sendint(out, txn->xid, 4); }
/* * txid_snapshot_send(txid_snapshot) returns bytea * * binary output function for type txid_snapshot * * format: int4 nxip, int8 xmin, int8 xmax, int8 xip */ Datum txid_snapshot_send(PG_FUNCTION_ARGS) { TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0); StringInfoData buf; uint32 i; pq_begintypsend(&buf); pq_sendint(&buf, snap->nxip, 4); pq_sendint64(&buf, snap->xmin); pq_sendint64(&buf, snap->xmax); for (i = 0; i < snap->nxip; i++) pq_sendint64(&buf, snap->xip[i]); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/* * Write COMMIT to the output stream. */ void logicalrep_write_commit(StringInfo out, ReorderBufferTXN *txn, XLogRecPtr commit_lsn) { uint8 flags = 0; pq_sendbyte(out, 'C'); /* sending COMMIT */ /* send the flags field (unused for now) */ pq_sendbyte(out, flags); /* send fields */ pq_sendint64(out, commit_lsn); pq_sendint64(out, txn->end_lsn); pq_sendint64(out, txn->commit_time); }
/* * int8send - converts int8 to binary format */ Datum int8send(PG_FUNCTION_ARGS) { int64 arg1 = PG_GETARG_INT64(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendint64(&buf, arg1); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/* * cash_send - converts cash to binary format */ Datum cash_send(PG_FUNCTION_ARGS) { Cash arg1 = PG_GETARG_CASH(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendint64(&buf, arg1); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/* * Write ORIGIN to the output stream. */ void logicalrep_write_origin(StringInfo out, const char *origin, XLogRecPtr origin_lsn) { pq_sendbyte(out, 'O'); /* ORIGIN */ /* fixed fields */ pq_sendint64(out, origin_lsn); /* origin string */ pq_sendstring(out, origin); }
/* * Send a gpdb libpq message. */ void sendQEDetails(void) { StringInfoData buf; pq_beginmessage(&buf, 'w'); pq_sendint(&buf, (int32) Gp_listener_port, sizeof(int32)); pq_sendint64(&buf, VmemTracker_GetMaxReservedVmemBytes()); pq_sendint(&buf, sizeof(PG_VERSION_STR), sizeof(int32)); pq_sendbytes(&buf, PG_VERSION_STR, sizeof(PG_VERSION_STR)); pq_endmessage(&buf); }
/* * Write BEGIN to the output stream. */ static void pglogical_write_begin(StringInfo out, PGLogicalOutputData *data, ReorderBufferTXN *txn) { bool isRecovery = MtmIsRecoveredNode(MtmReplicationNodeId); csn_t csn = MtmTransactionSnapshot(txn->xid); MTM_LOG2("%d: pglogical_write_begin XID=%d node=%d CSN=%ld recovery=%d", MyProcPid, txn->xid, MtmReplicationNodeId, csn, isRecovery); if (csn == INVALID_CSN && !isRecovery) { MtmIsFilteredTxn = true; } else { pq_sendbyte(out, 'B'); /* BEGIN */ pq_sendint(out, MtmNodeId, 4); pq_sendint(out, isRecovery ? InvalidTransactionId : txn->xid, 4); pq_sendint64(out, csn); MtmIsFilteredTxn = false; } }
/* ---------------- * ReadyForQuery - tell dest that we are ready for a new query * * The ReadyForQuery message is sent in protocol versions 2.0 and up * so that the FE can tell when we are done processing a query string. * In versions 3.0 and up, it also carries a transaction state indicator. * * Note that by flushing the stdio buffer here, we can avoid doing it * most other places and thus reduce the number of separate packets sent. * ---------------- */ void ReadyForQuery(CommandDest dest) { switch (dest) { case DestRemote: case DestRemoteExecute: if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { StringInfoData buf; if (Gp_role == GP_ROLE_EXECUTE) { pq_beginmessage(&buf, 'k'); pq_sendint64(&buf, VmemTracker_GetMaxReservedVmemBytes()); pq_endmessage(&buf); } pq_beginmessage(&buf, 'Z'); pq_sendbyte(&buf, TransactionBlockStatusCode()); pq_endmessage(&buf); } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) pq_putemptymessage('Z'); /* Flush output at end of cycle in any case. */ pq_flush(); break; case DestNone: case DestDebug: case DestSPI: case DestTuplestore: case DestIntoRel: case DestCopyOut: break; } }