/* * closeGTM_Conn * - properly close a connection to the backend * * This should reset or release all transient state, but NOT the connection * parameters. On exit, the GTM_Conn should be in condition to start a fresh * connection with the same parameters (see PQreset()). */ static void closeGTM_Conn(GTM_Conn *conn) { /* * Note that the protocol doesn't allow us to send Terminate messages * during the startup phase. */ if (conn->sock >= 0 && conn->status == CONNECTION_OK) { /* * Try to send "close connection" message to backend. Ignore any * error. * * Force length word for backends may try to read that in a generic * code */ gtmpqPutMsgStart('X', true, conn); gtmpqPutMsgEnd(conn); gtmpqFlush(conn); } /* * Close the connection, reset all transient state, flush I/O buffers. */ if (conn->sock >= 0) close(conn->sock); conn->sock = -1; conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just * absent */ gtm_freeaddrinfo_all(conn->addrlist_family, conn->addrlist); conn->addrlist = NULL; conn->addr_cur = NULL; conn->inStart = conn->inCursor = conn->inEnd = 0; conn->outCount = 0; }
GTM_Result * GTMPQgetResult(GTM_Conn *conn) { GTM_Result *res; if (!conn) return NULL; /* Parse any available data, if our state permits. */ while ((res = pqParseInput(conn)) == NULL) { int flushResult; /* * If data remains unsent, send it. Else we might be waiting for the * result of a command the backend hasn't even got yet. */ while ((flushResult = gtmpqFlush(conn)) > 0) { if (gtmpqWait(false, true, conn)) { flushResult = -1; break; } } /* Wait for some more data, and load it. */ if (flushResult || gtmpqWait(true, false, conn) || gtmpqReadData(conn) < 0) { /* * conn->errorMessage has been set by gtmpqWait or gtmpqReadData. */ return NULL; } } return res; }
/* * pqPacketSend() -- convenience routine to send a message to server. * * pack_type: the single-byte message type code. (Pass zero for startup * packets, which have no message type code.) * * buf, buf_len: contents of message. The given length includes only what * is in buf; the message type and message length fields are added here. * * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise. * SIDE_EFFECTS: may block. * * Note: all messages sent with this routine have a length word, whether * it's protocol 2.0 or 3.0. */ static int pqPacketSend(GTM_Conn *conn, char pack_type, const void *buf, size_t buf_len) { /* Start the message. */ if (gtmpqPutMsgStart(pack_type, true, conn)) return STATUS_ERROR; /* Send the message body. */ if (gtmpqPutnchar(buf, buf_len, conn)) return STATUS_ERROR; /* Finish the message. */ if (gtmpqPutMsgEnd(conn)) return STATUS_ERROR; /* Flush to ensure backend gets it. */ if (gtmpqFlush(conn)) return STATUS_ERROR; return STATUS_OK; }