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

📄 fe-misc.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
			/*			 * We don't insist that the enlarge worked, but we need some room			 */			if (conn->inBufSize - conn->inEnd < 100)				return -1;		/* errorMessage already set */		}	}	/* OK, try to read some data */retry3:	nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,						  conn->inBufSize - conn->inEnd);	if (nread < 0)	{		if (SOCK_ERRNO == EINTR)			goto retry3;		/* Some systems return EAGAIN/EWOULDBLOCK for no data */#ifdef EAGAIN		if (SOCK_ERRNO == EAGAIN)			return someread;#endif#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))		if (SOCK_ERRNO == EWOULDBLOCK)			return someread;#endif		/* We might get ECONNRESET here if using TCP and backend died */#ifdef ECONNRESET		if (SOCK_ERRNO == ECONNRESET)			goto definitelyFailed;#endif		printfPQExpBuffer(&conn->errorMessage,				   libpq_gettext("could not receive data from server: %s\n"),						  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));		return -1;	}	if (nread > 0)	{		conn->inEnd += nread;		/*		 * Hack to deal with the fact that some kernels will only give us back		 * 1 packet per recv() call, even if we asked for more and there is		 * more available.	If it looks like we are reading a long message,		 * loop back to recv() again immediately, until we run out of data or		 * buffer space.  Without this, the block-and-restart behavior of		 * libpq's higher levels leads to O(N^2) performance on long messages.		 *		 * Since we left-justified the data above, conn->inEnd gives the		 * amount of data already read in the current message.	We consider		 * the message "long" once we have acquired 32k ...		 */		if (conn->inEnd > 32768 &&			(conn->inBufSize - conn->inEnd) >= 8192)		{			someread = 1;			goto retry3;		}		return 1;	}	if (someread)		return 1;				/* got a zero read after successful tries */	/*	 * A return value of 0 could mean just that no data is now available, or	 * it could mean EOF --- that is, the server has closed the connection.	 * Since we have the socket in nonblock mode, the only way to tell the	 * difference is to see if select() is saying that the file is ready.	 * Grumble.  Fortunately, we don't expect this path to be taken much,	 * since in normal practice we should not be trying to read data unless	 * the file selected for reading already.	 *	 * In SSL mode it's even worse: SSL_read() could say WANT_READ and then	 * data could arrive before we make the pqReadReady() test.  So we must	 * play dumb and assume there is more data, relying on the SSL layer to	 * detect true EOF.	 */#ifdef USE_SSL	if (conn->ssl)		return 0;#endif	switch (pqReadReady(conn))	{		case 0:			/* definitely no data available */			return 0;		case 1:			/* ready for read */			break;		default:			goto definitelyFailed;	}	/*	 * Still not sure that it's EOF, because some data could have just	 * arrived.	 */retry4:	nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,						  conn->inBufSize - conn->inEnd);	if (nread < 0)	{		if (SOCK_ERRNO == EINTR)			goto retry4;		/* Some systems return EAGAIN/EWOULDBLOCK for no data */#ifdef EAGAIN		if (SOCK_ERRNO == EAGAIN)			return 0;#endif#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))		if (SOCK_ERRNO == EWOULDBLOCK)			return 0;#endif		/* We might get ECONNRESET here if using TCP and backend died */#ifdef ECONNRESET		if (SOCK_ERRNO == ECONNRESET)			goto definitelyFailed;#endif		printfPQExpBuffer(&conn->errorMessage,				   libpq_gettext("could not receive data from server: %s\n"),						  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));		return -1;	}	if (nread > 0)	{		conn->inEnd += nread;		return 1;	}	/*	 * OK, we are getting a zero read even though select() says ready. This	 * means the connection has been closed.  Cope.	 */definitelyFailed:	printfPQExpBuffer(&conn->errorMessage,					  libpq_gettext(								"server closed the connection unexpectedly\n"				   "\tThis probably means the server terminated abnormally\n"							 "\tbefore or while processing the request.\n"));	conn->status = CONNECTION_BAD;		/* No more connection to backend */	pqsecure_close(conn);	closesocket(conn->sock);	conn->sock = -1;	return -1;}/* * pqSendSome: send data waiting in the output buffer. * * len is how much to try to send (typically equal to outCount, but may * be less). * * Return 0 on success, -1 on failure and 1 when not all data could be sent * because the socket would block and the connection is non-blocking. */static intpqSendSome(PGconn *conn, int len){	char	   *ptr = conn->outBuffer;	int			remaining = conn->outCount;	int			result = 0;	if (conn->sock < 0)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("connection not open\n"));		return -1;	}	/* while there's still data to send */	while (len > 0)	{		int			sent;		char		sebuf[256];		sent = pqsecure_write(conn, ptr, len);		if (sent < 0)		{			/*			 * Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble. If it's			 * EPIPE or ECONNRESET, assume we've lost the backend connection			 * permanently.			 */			switch (SOCK_ERRNO)			{#ifdef EAGAIN				case EAGAIN:					break;#endif#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))				case EWOULDBLOCK:					break;#endif				case EINTR:					continue;				case EPIPE:#ifdef ECONNRESET				case ECONNRESET:#endif					printfPQExpBuffer(&conn->errorMessage,									  libpq_gettext(								"server closed the connection unexpectedly\n"					"\tThis probably means the server terminated abnormally\n"							 "\tbefore or while processing the request.\n"));					/*					 * We used to close the socket here, but that's a bad idea					 * since there might be unread data waiting (typically, a					 * NOTICE message from the backend telling us it's					 * committing hara-kiri...).  Leave the socket open until					 * pqReadData finds no more data can be read.  But abandon					 * attempt to send data.					 */					conn->outCount = 0;					return -1;				default:					printfPQExpBuffer(&conn->errorMessage,						libpq_gettext("could not send data to server: %s\n"),							SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));					/* We don't assume it's a fatal error... */					conn->outCount = 0;					return -1;			}		}		else		{			ptr += sent;			len -= sent;			remaining -= sent;		}		if (len > 0)		{			/*			 * We didn't send it all, wait till we can send more.			 *			 * If the connection is in non-blocking mode we don't wait, but			 * return 1 to indicate that data is still pending.			 */			if (pqIsnonblocking(conn))			{				result = 1;				break;			}			/*			 * There are scenarios in which we can't send data because the			 * communications channel is full, but we cannot expect the server			 * to clear the channel eventually because it's blocked trying to			 * send data to us.  (This can happen when we are sending a large			 * amount of COPY data, and the server has generated lots of			 * NOTICE responses.)  To avoid a deadlock situation, we must be			 * prepared to accept and buffer incoming data before we try			 * again.  Furthermore, it is possible that such incoming data			 * might not arrive until after we've gone to sleep.  Therefore,			 * we wait for either read ready or write ready.			 */			if (pqReadData(conn) < 0)			{				result = -1;	/* error message already set up */				break;			}			if (pqWait(TRUE, TRUE, conn))			{				result = -1;				break;			}		}	}	/* shift the remaining contents of the buffer */	if (remaining > 0)		memmove(conn->outBuffer, ptr, remaining);	conn->outCount = remaining;	return result;}/* * pqFlush: send any data waiting in the output buffer * * Return 0 on success, -1 on failure and 1 when not all data could be sent * because the socket would block and the connection is non-blocking. */intpqFlush(PGconn *conn){	if (conn->Pfdebug)		fflush(conn->Pfdebug);	if (conn->outCount > 0)		return pqSendSome(conn, conn->outCount);	return 0;}/* * pqWait: wait until we can read or write the connection socket * * JAB: If SSL enabled and used and forRead, buffered bytes short-circuit the * call to select(). * * We also stop waiting and return if the kernel flags an exception condition * on the socket.  The actual error condition will be detected and reported * when the caller tries to read or write the socket. */intpqWait(int forRead, int forWrite, PGconn *conn){	return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);}/* * pqWaitTimed: wait, but not past finish_time. * * If finish_time is exceeded then we return failure (EOF).  This is like * the response for a kernel exception because we don't want the caller * to try to read/write in that case. * * finish_time = ((time_t) -1) disables the wait limit. */intpqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time){	int			result;	result = pqSocketCheck(conn, forRead, forWrite, finish_time);	if (result < 0)		return EOF;				/* errorMessage is already set */	if (result == 0)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("timeout expired\n"));		return EOF;	}	return 0;}/* * pqReadReady: is select() saying the file is ready to read? * Returns -1 on failure, 0 if not ready, 1 if ready. */intpqReadReady(PGconn *conn){	return pqSocketCheck(conn, 1, 0, (time_t) 0);}/* * pqWriteReady: is select() saying the file is ready to write? * Returns -1 on failure, 0 if not ready, 1 if ready. */intpqWriteReady(PGconn *conn){	return pqSocketCheck(conn, 0, 1, (time_t) 0);}/* * Checks a socket, using poll or select, for data to be read, written, * or both.  Returns >0 if one or more conditions are met, 0 if it timed * out, -1 if an error occurred. * * If SSL is in use, the SSL buffer is checked prior to checking the socket * for read data directly. */static intpqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time){	int			result;	if (!conn)		return -1;	if (conn->sock < 0)	{		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("socket not open\n"));		return -1;	}#ifdef USE_SSL	/* Check for SSL library buffering read bytes */	if (forRead && conn->ssl && SSL_pending(conn->ssl) > 0)	{		/* short-circuit the select */		return 1;	}#endif	/* We will retry as long as we get EINTR */	do		result = pqSocketPoll(conn->sock, forRead, forWrite, end_time);	while (result < 0 && SOCK_ERRNO == EINTR);	if (result < 0)	{		char		sebuf[256];		printfPQExpBuffer(&conn->errorMessage,						  libpq_gettext("select() failed: %s\n"),						  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));	}	return result;}/* * Check a file descriptor for read and/or write data, possibly waiting. * If neither forRead nor forWrite are set, immediately return a timeout * condition (without waiting).  Return >0 if condition is met, 0 * if a timeout occurred, -1 if an error or interrupt occurred. * * Timeout is infinite if end_time is -1.  Timeout is immediate (no blocking) * if end_time is 0 (or indeed, any time before now). */static intpqSocketPoll(int sock, int forRead, int forWrite, time_t end_time){	/* We use poll(2) if available, otherwise select(2) */#ifdef HAVE_POLL	struct pollfd input_fd;	int			timeout_ms;	if (!forRead && !forWrite)		return 0;	input_fd.fd = sock;	input_fd.events = POLLERR;	input_fd.revents = 0;	if (forRead)		input_fd.events |= POLLIN;	if (forWrite)		input_fd.events |= POLLOUT;	/* Compute appropriate timeout interval */	if (end_time == ((time_t) -1))		timeout_ms = -1;	else	{		time_t		now = time(NULL);		if (end_time > now)			timeout_ms = (end_time - now) * 1000;		else			timeout_ms = 0;	}	return poll(&input_fd, 1, timeout_ms);#else							/* !HAVE_POLL */	fd_set		input_mask;	fd_set		output_mask;	fd_set		except_mask;	struct timeval timeout;	struct timeval *ptr_timeout;	if (!forRead && !forWrite)		return 0;	FD_ZERO(&input_mask);	FD_ZERO(&output_mask);	FD_ZERO(&except_mask);	if (forRead)		FD_SET(sock, &input_mask);	if (forWrite)		FD_SET(sock, &output_mask);	FD_SET(sock, &except_mask);	/* Compute appropriate timeout interval */	if (end_time == ((time_t) -1))		ptr_timeout = NULL;	else	{		time_t		now = time(NULL);		if (end_time > now)			timeout.tv_sec = end_time - now;		else			timeout.tv_sec = 0;		timeout.tv_usec = 0;		ptr_timeout = &timeout;	}	return select(sock + 1, &input_mask, &output_mask,				  &except_mask, ptr_timeout);#endif   /* HAVE_POLL */}/* * A couple of "miscellaneous" multibyte related functions. They used * to be in fe-print.c but that file is doomed. *//* * returns the byte length of the word beginning s, using the * specified encoding. */intPQmblen(const char *s, int encoding){	return (pg_encoding_mblen(encoding, s));}/* * returns the display length of the word beginning s, using the * specified encoding. */intPQdsplen(const char *s, int encoding){	return (pg_encoding_dsplen(encoding, s));}/* * Get encoding id from environment variable PGCLIENTENCODING. */intPQenv2encoding(void){	char	   *str;	int			encoding = PG_SQL_ASCII;	str = getenv("PGCLIENTENCODING");	if (str && *str != '\0')		encoding = pg_char_to_encoding(str);	return (encoding);}#ifdef ENABLE_NLSchar *libpq_gettext(const char *msgid){	static bool already_bound = false;	if (!already_bound)	{		/* dgettext() preserves errno, but bindtextdomain() doesn't */#ifdef WIN32		int			save_errno = GetLastError();#else		int			save_errno = errno;#endif		const char *ldir;		already_bound = true;		/* No relocatable lookup here because the binary could be anywhere */		ldir = getenv("PGLOCALEDIR");		if (!ldir)			ldir = LOCALEDIR;		bindtextdomain("libpq", ldir);#ifdef WIN32		SetLastError(save_errno);#else		errno = save_errno;#endif	}	return dgettext("libpq", msgid);}#endif   /* ENABLE_NLS */

⌨️ 快捷键说明

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