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

📄 fe-connect.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
 * * A copy is needed to be able to cancel a running query from a different * thread. If the same structure is used all structure members would have * to be individually locked (if the entire structure was locked, it would * be impossible to cancel a synchronous query becuase the structure would * have to stay locked for the duration of the query). */PGcancel *PQgetCancel(PGconn *conn){	PGcancel   *cancel;	if (!conn)		return NULL;	if (conn->sock < 0)		return NULL;	cancel = malloc(sizeof(PGcancel));	if (cancel == NULL)		return NULL;	memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));	cancel->be_pid = conn->be_pid;	cancel->be_key = conn->be_key;	return cancel;}/* PQfreeCancel: free a cancel structure */voidPQfreeCancel(PGcancel *cancel){	if (cancel)		free(cancel);}/* * PQcancel and PQrequestCancel: attempt to request cancellation of the * current operation. * * The return value is TRUE if the cancel request was successfully * dispatched, FALSE if not (in which case an error message is available). * Note: successful dispatch is no guarantee that there will be any effect at * the backend.  The application must read the operation result as usual. * * CAUTION: we want this routine to be safely callable from a signal handler * (for example, an application might want to call it in a SIGINT handler). * This means we cannot use any C library routine that might be non-reentrant. * malloc/free are often non-reentrant, and anything that might call them is * just as dangerous.  We avoid sprintf here for that reason.  Building up * error messages with strcpy/strcat is tedious but should be quite safe. * We also save/restore errno in case the signal handler support doesn't. * * internal_cancel() is an internal helper function to make code-sharing * between the two versions of the cancel function possible. */static intinternal_cancel(SockAddr *raddr, int be_pid, int be_key,				char *errbuf, int errbufsize){	int			save_errno = SOCK_ERRNO;	int			tmpsock = -1;	char		sebuf[256];	int			maxlen;	struct	{		uint32		packetlen;		CancelRequestPacket cp;	}			crp;	/*	 * We need to open a temporary connection to the postmaster. Do this with	 * only kernel calls.	 */	if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) < 0)	{		StrNCpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);		goto cancel_errReturn;	}retry3:	if (connect(tmpsock, (struct sockaddr *) & raddr->addr,				raddr->salen) < 0)	{		if (SOCK_ERRNO == EINTR)			/* Interrupted system call - we'll just try again */			goto retry3;		StrNCpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);		goto cancel_errReturn;	}	/*	 * We needn't set nonblocking I/O or NODELAY options here.	 */	/* Create and send the cancel request packet. */	crp.packetlen = htonl((uint32) sizeof(crp));	crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);	crp.cp.backendPID = htonl(be_pid);	crp.cp.cancelAuthCode = htonl(be_key);retry4:	if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))	{		if (SOCK_ERRNO == EINTR)			/* Interrupted system call - we'll just try again */			goto retry4;		StrNCpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);		goto cancel_errReturn;	}	/*	 * Wait for the postmaster to close the connection, which indicates that	 * it's processed the request.  Without this delay, we might issue another	 * command only to find that our cancel zaps that command instead of the	 * one we thought we were canceling.  Note we don't actually expect this	 * read to obtain any data, we are just waiting for EOF to be signaled.	 */retry5:	if (recv(tmpsock, (char *) &crp, 1, 0) < 0)	{		if (SOCK_ERRNO == EINTR)			/* Interrupted system call - we'll just try again */			goto retry5;		/* we ignore other error conditions */	}	/* All done */	closesocket(tmpsock);	SOCK_ERRNO_SET(save_errno);	return TRUE;cancel_errReturn:	/*	 * Make sure we don't overflow the error buffer. Leave space for the \n at	 * the end, and for the terminating zero.	 */	maxlen = errbufsize - strlen(errbuf) - 2;	if (maxlen >= 0)	{		strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),				maxlen);		strcat(errbuf, "\n");	}	if (tmpsock >= 0)		closesocket(tmpsock);	SOCK_ERRNO_SET(save_errno);	return FALSE;}/* * PQcancel: request query cancel * * Returns TRUE if able to send the cancel request, FALSE if not. * * On failure, an error message is stored in *errbuf, which must be of size * errbufsize (recommended size is 256 bytes).	*errbuf is not changed on * success return. */intPQcancel(PGcancel *cancel, char *errbuf, int errbufsize){	if (!cancel)	{		StrNCpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);		return FALSE;	}	return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,						   errbuf, errbufsize);}/* * PQrequestCancel: old, not thread-safe function for requesting query cancel * * Returns TRUE if able to send the cancel request, FALSE if not. * * On failure, the error message is saved in conn->errorMessage; this means * that this can't be used when there might be other active operations on * the connection object. * * NOTE: error messages will be cut off at the current size of the * error message buffer, since we dare not try to expand conn->errorMessage! */intPQrequestCancel(PGconn *conn){	int			r;	/* Check we have an open connection */	if (!conn)		return FALSE;	if (conn->sock < 0)	{		StrNCpy(conn->errorMessage.data,				"PQrequestCancel() -- connection is not open\n",				conn->errorMessage.maxlen);		conn->errorMessage.len = strlen(conn->errorMessage.data);		return FALSE;	}	r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key,						conn->errorMessage.data, conn->errorMessage.maxlen);	if (!r)		conn->errorMessage.len = strlen(conn->errorMessage.data);	return r;}/* * 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. */intpqPacketSend(PGconn *conn, char pack_type,			 const void *buf, size_t buf_len){	/* Start the message. */	if (pqPutMsgStart(pack_type, true, conn))		return STATUS_ERROR;	/* Send the message body. */	if (pqPutnchar(buf, buf_len, conn))		return STATUS_ERROR;	/* Finish the message. */	if (pqPutMsgEnd(conn))		return STATUS_ERROR;	/* Flush to ensure backend gets it. */	if (pqFlush(conn))		return STATUS_ERROR;	return STATUS_OK;}#define MAXBUFSIZE 256static intparseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage){	char	   *service = conninfo_getval(options, "service");	char		serviceFile[MAXPGPATH];	bool		group_found = false;	int			linenr = 0,				i;	/*	 * We have to special-case the environment variable PGSERVICE here, since	 * this is and should be called before inserting environment defaults for	 * other connection options.	 */	if (service == NULL)		service = getenv("PGSERVICE");	/*	 * This could be used by any application so we can't use the binary	 * location to find our config files.	 */	snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",			 getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);	if (service != NULL)	{		FILE	   *f;		char		buf[MAXBUFSIZE],				   *line;		f = fopen(serviceFile, "r");		if (f == NULL)		{			printfPQExpBuffer(errorMessage, libpq_gettext("ERROR: service file \"%s\" not found\n"),							  serviceFile);			return 1;		}		while ((line = fgets(buf, MAXBUFSIZE - 1, f)) != NULL)		{			linenr++;			if (strlen(line) >= MAXBUFSIZE - 2)			{				fclose(f);				printfPQExpBuffer(errorMessage,								  libpq_gettext("ERROR: line %d too long in service file \"%s\"\n"),								  linenr,								  serviceFile);				return 2;			}			/* ignore EOL at end of line */			if (strlen(line) && line[strlen(line) - 1] == '\n')				line[strlen(line) - 1] = 0;			/* ignore leading blanks */			while (*line && isspace((unsigned char) line[0]))				line++;			/* ignore comments and empty lines */			if (strlen(line) == 0 || line[0] == '#')				continue;			/* Check for right groupname */			if (line[0] == '[')			{				if (group_found)				{					/* group info already read */					fclose(f);					return 0;				}				if (strncmp(line + 1, service, strlen(service)) == 0 &&					line[strlen(service) + 1] == ']')					group_found = true;				else					group_found = false;			}			else			{				if (group_found)				{					/*					 * Finally, we are in the right group and can parse the					 * line					 */					char	   *key,							   *val;					bool		found_keyword;					key = line;					val = strchr(line, '=');					if (val == NULL)					{						printfPQExpBuffer(errorMessage,										  libpq_gettext("ERROR: syntax error in service file \"%s\", line %d\n"),										  serviceFile,										  linenr);						fclose(f);						return 3;					}					*val++ = '\0';					/*					 * Set the parameter --- but don't override any previous					 * explicit setting.					 */					found_keyword = false;					for (i = 0; options[i].keyword; i++)					{						if (strcmp(options[i].keyword, key) == 0)						{							if (options[i].val == NULL)								options[i].val = strdup(val);							found_keyword = true;							break;						}					}					if (!found_keyword)					{						printfPQExpBuffer(errorMessage,										  libpq_gettext("ERROR: syntax error in service file \"%s\", line %d\n"),										  serviceFile,										  linenr);						fclose(f);						return 3;					}				}			}		}		fclose(f);	}	return 0;}/* * Conninfo parser routine * * If successful, a malloc'd PQconninfoOption array is returned. * If not successful, NULL is returned and an error message is * left in errorMessage. */static PQconninfoOption *conninfo_parse(const char *conninfo, PQExpBuffer errorMessage){	char	   *pname;	char	   *pval;	char	   *buf;	char	   *tmp;	char	   *cp;	char	   *cp2;	PQconninfoOption *options;	PQconninfoOption *option;	char		errortmp[PQERRORMSG_LENGTH];	/* Make a working copy of PQconninfoOptions */	options = malloc(sizeof(PQconninfoOptions));	if (options == NULL)	{		printfPQExpBuffer(errorMessage,						  libpq_gettext("out of memory\n"));		return NULL;	}	memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions));	/* Need a modifiable copy of the input string */	if ((buf = strdup(conninfo)) == NULL)	{		printfPQExpBuffer(errorMessage,						  libpq_gettext("out of memory\n"));		PQconninfoFree(options);		return NULL;	}	cp = buf;	while (*cp)	{		/* Skip blanks before the parameter name */		if (isspace((unsigned char) *cp))		{			cp++;			continue;		}		/* Get the parameter name */		pname = cp;		while (*cp)		{			if (*cp == '=')				break;			if (isspace((unsigned char) *cp))			{				*cp++ = '\0';				while (*cp)				{					if (!isspace((unsigned char) *cp))						break;					cp++;				}				break;			}			cp++;		}		/* Check that there is a following '=' */		if (*cp != '=')		{			printfPQExpBuffer(errorMessage,							  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),							  pname);			PQconninfoFree(options);			free(buf);			return NULL;		}		*cp++ = '\0';		/* Skip blanks after the '=' */		while (*cp)		{			if (!isspace((unsigned char) *cp))				break;			cp++;		}		/* Get the parameter value */		pval = cp;		if (*cp != '\'')		{			cp2 = pval;			while (*cp)			{				if (isspace((unsigned char) *cp))				{					*cp++ = '\0';					break;				}				if (*cp == '\\')				{					cp++;					if (*cp != '\0')						*cp2++ = *cp++;				}				else					*cp2++ = *cp++;			}			*cp2 = '\0';		}		else		{			cp2 = pval;			cp++;	

⌨️ 快捷键说明

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