Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/*
 * 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;
}