⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fe-connect.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
 * and should be freed when no longer needed via PQconninfoFree().	(In prior * versions, the returned array was static, but that's not thread-safe.) * Pre-7.0 applications that use this function will see a small memory leak * until they are updated to call PQconninfoFree. */PQconninfoOption *PQconndefaults(void){	PQExpBufferData errorBuf;	PQconninfoOption *connOptions;	initPQExpBuffer(&errorBuf);	connOptions = conninfo_parse("", &errorBuf);	termPQExpBuffer(&errorBuf);	return connOptions;}/* ---------------- *		PQsetdbLogin * * establishes a connection to a postgres backend through the postmaster * at the specified host and port. * * returns a PGconn* which is needed for all subsequent libpq calls * * if the status field of the connection returned is CONNECTION_BAD, * then only the errorMessage is likely to be useful. * ---------------- */PGconn *PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,			 const char *pgtty, const char *dbName, const char *login,			 const char *pwd){	PGconn	   *conn;	/*	 * Allocate memory for the conn structure	 */	conn = makeEmptyPGconn();	if (conn == NULL)		return NULL;	/*	 * Parse an empty conninfo string in order to set up the same defaults	 * that PQconnectdb() would use.	 */	if (!connectOptions1(conn, ""))		return conn;	/*	 * Absorb specified options into conn structure, overriding defaults	 */	if (pghost && pghost[0] != '\0')	{		if (conn->pghost)			free(conn->pghost);		conn->pghost = strdup(pghost);	}	if (pgport && pgport[0] != '\0')	{		if (conn->pgport)			free(conn->pgport);		conn->pgport = strdup(pgport);	}	if (pgoptions && pgoptions[0] != '\0')	{		if (conn->pgoptions)			free(conn->pgoptions);		conn->pgoptions = strdup(pgoptions);	}	if (pgtty && pgtty[0] != '\0')	{		if (conn->pgtty)			free(conn->pgtty);		conn->pgtty = strdup(pgtty);	}	if (dbName && dbName[0] != '\0')	{		if (conn->dbName)			free(conn->dbName);		conn->dbName = strdup(dbName);	}	if (login && login[0] != '\0')	{		if (conn->pguser)			free(conn->pguser);		conn->pguser = strdup(login);	}	if (pwd && pwd[0] != '\0')	{		if (conn->pgpass)			free(conn->pgpass);		conn->pgpass = strdup(pwd);	}	/*	 * Compute derived options	 */	if (!connectOptions2(conn))		return conn;	/*	 * Connect to the database	 */	if (connectDBStart(conn))		(void) connectDBComplete(conn);	return conn;}/* ---------- * connectNoDelay - * Sets the TCP_NODELAY socket option. * Returns 1 if successful, 0 if not. * ---------- */static intconnectNoDelay(PGconn *conn){#ifdef	TCP_NODELAY	int			on = 1;	if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,				   (char *) &on,				   sizeof(on)) < 0)	{		char		sebuf[256];		printfPQExpBuffer(&conn->errorMessage,			libpq_gettext("could not set socket to TCP no delay mode: %s\n"),						  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));		return 0;	}#endif	return 1;}/* ---------- * connectFailureMessage - * create a friendly error message on connection failure. * ---------- */static voidconnectFailureMessage(PGconn *conn, int errorno){	char		sebuf[256];#ifdef HAVE_UNIX_SOCKETS	if (IS_AF_UNIX(conn->raddr.addr.ss_family))	{		char		service[NI_MAXHOST];		pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,						   NULL, 0,						   service, sizeof(service),						   NI_NUMERICSERV);		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("could not connect to server: %s\n"							"\tIs the server running locally and accepting\n"							"\tconnections on Unix domain socket \"%s\"?\n"),						  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),						  service);	}	else#endif   /* HAVE_UNIX_SOCKETS */	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("could not connect to server: %s\n"					 "\tIs the server running on host \"%s\" and accepting\n"										"\tTCP/IP connections on port %s?\n"),						  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),						  conn->pghostaddr						  ? conn->pghostaddr						  : (conn->pghost							 ? conn->pghost							 : "???"),						  conn->pgport);	}}/* ---------- * connectDBStart - *		Begin the process of making a connection to the backend. * * Returns 1 if successful, 0 if not. * ---------- */static intconnectDBStart(PGconn *conn){	int			portnum;	char		portstr[128];	struct addrinfo *addrs = NULL;	struct addrinfo hint;	const char *node;	int			ret;	if (!conn)		return 0;	/* Ensure our buffers are empty */	conn->inStart = conn->inCursor = conn->inEnd = 0;	conn->outCount = 0;	/*	 * Determine the parameters to pass to pg_getaddrinfo_all.	 */	/* Initialize hint structure */	MemSet(&hint, 0, sizeof(hint));	hint.ai_socktype = SOCK_STREAM;	hint.ai_family = AF_UNSPEC;	/* Set up port number as a string */	if (conn->pgport != NULL && conn->pgport[0] != '\0')		portnum = atoi(conn->pgport);	else		portnum = DEF_PGPORT;	snprintf(portstr, sizeof(portstr), "%d", portnum);	if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')	{		/* Using pghostaddr avoids a hostname lookup */		node = conn->pghostaddr;		hint.ai_family = AF_UNSPEC;		hint.ai_flags = AI_NUMERICHOST;	}	else if (conn->pghost != NULL && conn->pghost[0] != '\0')	{		/* Using pghost, so we have to look-up the hostname */		node = conn->pghost;		hint.ai_family = AF_UNSPEC;	}	else	{#ifdef HAVE_UNIX_SOCKETS		/* pghostaddr and pghost are NULL, so use Unix domain socket */		node = NULL;		hint.ai_family = AF_UNIX;		UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);#else		/* Without Unix sockets, default to localhost instead */		node = "localhost";		hint.ai_family = AF_UNSPEC;#endif   /* HAVE_UNIX_SOCKETS */	}	/* Use pg_getaddrinfo_all() to resolve the address */	ret = pg_getaddrinfo_all(node, portstr, &hint, &addrs);	if (ret || !addrs)	{		if (node)			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("could not translate host name \"%s\" to address: %s\n"),							  node, gai_strerror(ret));		else			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),							  portstr, gai_strerror(ret));		if (addrs)			pg_freeaddrinfo_all(hint.ai_family, addrs);		goto connect_errReturn;	}#ifdef USE_SSL	/* setup values based on SSL mode */	if (conn->sslmode[0] == 'd')	/* "disable" */		conn->allow_ssl_try = false;	else if (conn->sslmode[0] == 'a')	/* "allow" */		conn->wait_ssl_try = true;#endif	/*	 * Set up to try to connect, with protocol 3.0 as the first attempt.	 */	conn->addrlist = addrs;	conn->addr_cur = addrs;	conn->addrlist_family = hint.ai_family;	conn->pversion = PG_PROTOCOL(3, 0);	conn->status = CONNECTION_NEEDED;	/*	 * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),	 * so that it can easily be re-executed if needed again during the	 * asynchronous startup process.  However, we must run it once here,	 * because callers expect a success return from this routine to mean that	 * we are in PGRES_POLLING_WRITING connection state.	 */	if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)		return 1;connect_errReturn:	if (conn->sock >= 0)	{		pqsecure_close(conn);		closesocket(conn->sock);		conn->sock = -1;	}	conn->status = CONNECTION_BAD;	return 0;}/* *		connectDBComplete * * Block and complete a connection. * * Returns 1 on success, 0 on failure. */static intconnectDBComplete(PGconn *conn){	PostgresPollingStatusType flag = PGRES_POLLING_WRITING;	time_t		finish_time = ((time_t) -1);	if (conn == NULL || conn->status == CONNECTION_BAD)		return 0;	/*	 * Set up a time limit, if connect_timeout isn't zero.	 */	if (conn->connect_timeout != NULL)	{		int			timeout = atoi(conn->connect_timeout);		if (timeout > 0)		{			/*			 * Rounding could cause connection to fail; need at least 2 secs			 */			if (timeout < 2)				timeout = 2;			/* calculate the finish time based on start + timeout */			finish_time = time(NULL) + timeout;		}	}	for (;;)	{		/*		 * Wait, if necessary.	Note that the initial state (just after		 * PQconnectStart) is to wait for the socket to select for writing.		 */		switch (flag)		{			case PGRES_POLLING_OK:				return 1;		/* success! */			case PGRES_POLLING_READING:				if (pqWaitTimed(1, 0, conn, finish_time))				{					conn->status = CONNECTION_BAD;					return 0;				}				break;			case PGRES_POLLING_WRITING:				if (pqWaitTimed(0, 1, conn, finish_time))				{					conn->status = CONNECTION_BAD;					return 0;				}				break;			default:				/* Just in case we failed to set it in PQconnectPoll */				conn->status = CONNECTION_BAD;				return 0;		}		/*		 * Now try to advance the state machine.		 */		flag = PQconnectPoll(conn);	}}/* ---------------- *		PQconnectPoll * * Poll an asynchronous connection. * * Returns a PostgresPollingStatusType. * Before calling this function, use select(2) to determine when data * has arrived.. * * You must call PQfinish whether or not this fails. * * This function and PQconnectStart are intended to allow connections to be * made without blocking the execution of your program on remote I/O. However, * there are a number of caveats: * *	 o	If you call PQtrace, ensure that the stream object into which you trace *		will not block. *	 o	If you do not supply an IP address for the remote host (i.e. you *		supply a host name instead) then PQconnectStart will block on *		gethostbyname.	You will be fine if using Unix sockets (i.e. by *		supplying neither a host name nor a host address). *	 o	If your backend wants to use Kerberos authentication then you must *		supply both a host name and a host address, otherwise this function *		may block on gethostname. * * ---------------- */PostgresPollingStatusTypePQconnectPoll(PGconn *conn){	PGresult   *res;	char		sebuf[256];	if (conn == NULL)		return PGRES_POLLING_FAILED;	/* Get the new data */	switch (conn->status)	{			/*			 * We really shouldn't have been polled in these two cases, but we			 * can handle it.			 */		case CONNECTION_BAD:			return PGRES_POLLING_FAILED;		case CONNECTION_OK:			return PGRES_POLLING_OK;			/* These are reading states */		case CONNECTION_AWAITING_RESPONSE:		case CONNECTION_AUTH_OK:			{				/* Load waiting data */				int			n = pqReadData(conn);				if (n < 0)					goto error_return;				if (n == 0)					return PGRES_POLLING_READING;				break;			}			/* These are writing states, so we just proceed. */		case CONNECTION_STARTED:		case CONNECTION_MADE:			break;			/* We allow pqSetenvPoll to decide whether to proceed. */		case CONNECTION_SETENV:			break;			/* Special cases: proceed without waiting. */		case CONNECTION_SSL_STARTUP:		case CONNECTION_NEEDED:			break;		default:			printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext(											"invalid connection state, "								 "probably indicative of memory corruption\n"											));			goto error_return;	}keep_going:						/* We will come back to here until there is								 * nothing left to do. */	switch (conn->status)	{		case CONNECTION_NEEDED:			{				/*				 * Try to initiate a connection to one of the addresses				 * returned by pg_getaddrinfo_all().  conn->addr_cur is the				 * next one to try. We fail when we run out of addresses				 * (reporting the error returned for the *last* alternative,				 * which may not be what users expect :-().				 */				while (conn->addr_cur != NULL)				{					struct addrinfo *addr_cur = conn->addr_cur;					/* Remember current address for possible error msg */					memcpy(&conn->raddr.addr, addr_cur->ai_addr,						   addr_cur->ai_addrlen);					conn->raddr.salen = addr_cur->ai_addrlen;					/* Open a socket */					conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);					if (conn->sock < 0)					{						/*						 * ignore socket() failure if we have more addresses						 * to try						 */						if (addr_cur->ai_next != NULL)						{							conn->addr_cur = addr_cur->ai_next;							continue;						}						printfPQExpBuffer(&conn->errorMessage,							  libpq_gettext("could not create socket: %s\n"),							SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));						break;					}					/*					 * Select socket options: no delay of outgoing data for					 * TCP sockets, nonblock mode, close-on-exec. Fail if any

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -