コード例 #1
0
ファイル: pool_proto2.c プロジェクト: Randalthor80/pgpool2
POOL_STATUS CompletedResponse(POOL_CONNECTION *frontend,
							  POOL_CONNECTION_POOL *backend)
{
	int i;
	char *string = NULL;
	char *string1 = NULL;
	int len, len1 = 0;

	/* read command tag */
	string = pool_read_string(MASTER(backend), &len, 0);
	if (string == NULL)
		return POOL_END;
	else if (!strncmp(string, "BEGIN", 5))
		TSTATE(backend, MASTER_NODE_ID) = 'T';
	else if (!strncmp(string, "COMMIT", 6) || !strncmp(string, "ROLLBACK", 8))
		TSTATE(backend, MASTER_NODE_ID) = 'I';

	len1 = len;
	string1 = strdup(string);

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (!VALID_BACKEND(i) || IS_MASTER_NODE_ID(i))
			continue;

		/* read command tag */
		string = pool_read_string(CONNECTION(backend, i), &len, 0);
		if (string == NULL)
			return POOL_END;
		else if (!strncmp(string, "BEGIN", 5))
			TSTATE(backend, i) = 'T';
		else if (!strncmp(string, "COMMIT", 6) || !strncmp(string, "ROLLBACK", 8))
			TSTATE(backend, i) = 'I';
 
		if (len != len1)
		{
			pool_debug("CompletedResponse: message length does not match between master(%d \"%s\",) and %d th server (%d \"%s\",)",
					   len, string, i, len1, string1);

			/* we except INSERT, because INSERT response has OID */
			if (strncmp(string1, "INSERT", 6))
			{
				free(string1);
				return POOL_END;
			}
		}
	}
	/* forward to the frontend */
	pool_write(frontend, "C", 1);
	pool_debug("CompletedResponse: string: \"%s\"", string1);
	if (pool_write(frontend, string1, len1) < 0)
	{
		free(string1);
		return POOL_END;
	}

	free(string1);
	return pool_flush(frontend);
}
コード例 #2
0
ファイル: pool_proto2.c プロジェクト: Randalthor80/pgpool2
POOL_STATUS CursorResponse(POOL_CONNECTION *frontend,
						   POOL_CONNECTION_POOL *backend)
{
	char *string = NULL;
	char *string1 = NULL;
	int len, len1 = 0;
	int i;

	/* read cursor name */
	string = pool_read_string(MASTER(backend), &len, 0);
	if (string == NULL)
		return POOL_END;
	len1 = len;
	string1 = strdup(string);

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i))
		{
			/* read cursor name */
			string = pool_read_string(CONNECTION(backend, i), &len, 0);
			if (string == NULL)
				return POOL_END;
			if (len != len1)
			{
				pool_error("CursorResponse: length does not match between master(%d) and %d th backend(%d)",
						   len, i, len1);
				pool_error("CursorResponse: master(%s) %d th backend(%s)", string1, i, string);
				free(string1);
				return POOL_END;
			}
		}
	}

	/* forward to the frontend */
	pool_write(frontend, "P", 1);
	if (pool_write(frontend, string1, len1) < 0)
	{
		free(string1);
		return POOL_END;
	}
	free(string1);

	if (pool_flush(frontend))
		return POOL_END;

	return POOL_CONTINUE;
}
コード例 #3
0
ファイル: pool_proto2.c プロジェクト: Randalthor80/pgpool2
POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend,
								 POOL_CONNECTION_POOL *backend)
{
	int pid, pid1;
	char *condition, *condition1 = NULL;
	int len, len1 = 0;
	int i;
	POOL_STATUS status;

	pool_write(frontend, "A", 1);

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i))
		{
			if (pool_read(CONNECTION(backend, i), &pid, sizeof(pid)) < 0)
				return POOL_ERROR;
			condition = pool_read_string(CONNECTION(backend, i), &len, 0);
			if (condition == NULL)
				return POOL_END;

			if (IS_MASTER_NODE_ID(i))
			{
				pid1 = pid;
				len1 = len;
				condition1 = strdup(condition);
			}
		}
	}

	pool_write(frontend, &pid1, sizeof(pid1));
	status = pool_write_and_flush(frontend, condition1, len1);
	free(condition1);
	return status;
}
コード例 #4
0
ファイル: pool_proto2.c プロジェクト: Randalthor80/pgpool2
POOL_STATUS NoticeResponse(POOL_CONNECTION *frontend,
						   POOL_CONNECTION_POOL *backend)
{
	char *string = NULL;
	int len;
	int i;

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i))
		{
			/* read notice message */
			string = pool_read_string(CONNECTION(backend, i), &len, 0);
			if (string == NULL)
				return POOL_END;
		}
	}

	/* forward to the frontend */
	pool_write(frontend, "N", 1);
	if (pool_write_and_flush(frontend, string, len) < 0)
	{
		return POOL_END;
	}
	return POOL_CONTINUE;
}
コード例 #5
0
ファイル: pool_proto2.c プロジェクト: Randalthor80/pgpool2
POOL_STATUS ErrorResponse(POOL_CONNECTION *frontend,
						  POOL_CONNECTION_POOL *backend)
{
	char *string = NULL;
	int len;
	int i;
	POOL_STATUS ret = POOL_CONTINUE;

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i))
		{
			/* read error message */
			string = pool_read_string(CONNECTION(backend, i), &len, 0);
			if (string == NULL)
				return POOL_END;
		}
	}

	/* forward to the frontend */
	pool_write(frontend, "E", 1);
	if (pool_write_and_flush(frontend, string, len) < 0)
		return POOL_END;

	/* 
	 * check session context, because this function is called 
	 * by pool_do_auth too.
	 */
	if (pool_get_session_context())
		ret = raise_intentional_error_if_need(backend);

	/* change transaction state */
	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i))
		{
			if (TSTATE(backend, i) == 'T')
				TSTATE(backend, i) = 'E';
		}
	}

	return ret;
}
コード例 #6
0
ファイル: pool_query_cache.c プロジェクト: mfyang/pgpool-II
/* --------------------------------
 * search_system_db_for_cache - search for query cache in libpq protocol level
 *
 * sends a cache searching query string using libpq protocol to the SystemDB.
 * if the SystemDB returns cache, forward the data to the frontend, and return
 * CACHE_FOUND. if cache was not found, silently discards the remaining data
 * returned by the SystemDB, and return CACHE_NOT_FOUND. returns CACHE_ERROR
 * if an error was encountered.
 * --------------------------------
 */
static CACHE_STATUS
search_system_db_for_cache(POOL_CONNECTION *frontend, char *sql, int sql_len, struct timeval *t, char tstate)
{
	fd_set readmask;
	int fds;
	int num_fds;
	struct timeval *timeout = NULL;
	char kind;
	int readlen;
	char *data = NULL;
	CACHE_STATUS return_value = CACHE_ERROR;
	int cache_found = 0;

	pool_debug("pool_query_cache_lookup: executing query: \"%s\"", sql);

	pool_write(SYSDB_CON, "Q", 1);
	if (SYSDB_MAJOR == PROTO_MAJOR_V3)
	{
		int sendlen = htonl(sql_len + 4);
		pool_write(SYSDB_CON, &sendlen, sizeof(sendlen));
	}
	if (pool_write_and_flush(SYSDB_CON, sql, sql_len) < 0)
	{
		pool_error("pool_query_cache_lookup: error while sending data to the SystemDB");
		return CACHE_ERROR;
	}

	if ((t->tv_sec + t->tv_usec) == 0)
		timeout = NULL;
	else
		timeout = t;

	/* don't really need select() or for(;;) here, but we may need it someday... or not */
	for (;;)
	{
		FD_ZERO(&readmask);
		num_fds = 0;

		num_fds = SYSDB_CON->fd + 1;
		FD_SET(SYSDB_CON->fd, &readmask);
		fds = select(num_fds, &readmask, NULL, NULL, timeout);
		if (fds == -1)
		{
			if (errno == EINTR)
				continue;

			pool_error("pool_query_cache_lookup: select() failed. reason: %s", strerror(errno));
			return CACHE_ERROR;
		}

		/* select() timeout */
		if (fds == 0)
			return CACHE_ERROR;

		for (;;)
		{
			if (! FD_ISSET(SYSDB_CON->fd, &readmask))
			{
				pool_error("pool_query_cache_lookup: select() failed");
				return CACHE_ERROR;
			}

			/* read kind */
			if (pool_read(SYSDB_CON, &kind, sizeof(kind)) < 0)
			{
				pool_error("pool_query_cache_lookup: error while reading message kind");
				return CACHE_ERROR;
			}
			pool_debug("pool_query_cache_lookup: received %c from systemdb", kind);

			/* just do the routine work of reading data in. data won't be used */
			if (kind == 'T')
			{
				if (SYSDB_MAJOR == PROTO_MAJOR_V3)
				{
					if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
					{
						pool_error("pool_query_cache_lookup: error while reading message length");
						return CACHE_ERROR;
					}
					readlen = ntohl(readlen) - sizeof(int);
					data = pool_read2(SYSDB_CON, readlen);
				}
				else
				{
					data = pool_read_string(SYSDB_CON, &readlen, 0);
				}
			}
			else if (kind == 'D') /* cache found! forward it to the frontend */
			{
				char *cache;
				int status;

				cache_found = 1;

				if (SYSDB_MAJOR == PROTO_MAJOR_V3)
				{
					if (pool_read(SYSDB_CON, &readlen, sizeof(readlen)) < 0)
					{
						pool_error("pool_query_cache_lookup: error while reading message length");
						return CACHE_ERROR;
					}
					readlen = ntohl(readlen) - sizeof(int);
					cache = pool_read2(SYSDB_CON, readlen);
				}
				else
				{
					cache = pool_read_string(SYSDB_CON, &readlen, 0);
				}

				if (cache == NULL)
				{
					pool_error("pool_query_cache_lookup: error while reading message body");
					return CACHE_ERROR;
				}

				cache[readlen] = '\0';

				cache += sizeof(short);	/* number of columns in 'D' (we know it's always going to be 1, so skip) */
				cache += sizeof(int); /* length of escaped bytea cache in string format. don't need the length */

				status = ForwardCacheToFrontend(frontend, cache, tstate);
				if (status < 0)
				{
					/* fatal error has occured while forwarding cache */
					pool_error("pool_query_cache_lookup: query cache forwarding failed");
					return_value = CACHE_ERROR;
				}
			}
			else if (kind == 'C') /* see if 'D' was received */
			{
				if (cache_found)
					return_value = CACHE_FOUND;
				else
					return_value = CACHE_NOT_FOUND;

				/* must discard the remaining data */
				if (SYSDB_MAJOR == PROTO_MAJOR_V3)
				{
					if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
					{
						pool_error("pool_query_cache_lookup: error while reading message length");
						return CACHE_ERROR;
					}
					readlen = ntohl(readlen) - sizeof(int);
					data = pool_read2(SYSDB_CON, readlen);
				}
				else
				{
					data = pool_read_string(SYSDB_CON, &readlen, 0);
				}
			}
			else if (kind == 'Z')
			{
				/* must discard the remaining data */
				if (SYSDB_MAJOR == PROTO_MAJOR_V3)
				{
					if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
					{
						pool_error("pool_query_cache_lookup: error while reading message length");
						return CACHE_ERROR;
					}
					readlen = ntohl(readlen) - sizeof(int);
					data = pool_read2(SYSDB_CON, readlen);
				}
				else
				{
					data = pool_read_string(SYSDB_CON, &readlen, 0);
				}

				break;
			}
			else if (kind == 'E')
			{
				/* must discard the remaining data */
				if (SYSDB_MAJOR == PROTO_MAJOR_V3)
				{
					if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0)
					{
						pool_error("pool_query_cache_lookup: error while reading message length");
						return CACHE_ERROR;
					}
					readlen = ntohl(readlen) - sizeof(int);
					data = pool_read2(SYSDB_CON, readlen);
				}
				else
				{
					data = pool_read_string(SYSDB_CON, &readlen, 0);
				}

				return_value = CACHE_ERROR;
			}
			else
			{
				/* shouldn't get here, but just in case */
				return CACHE_ERROR;
			}
		}

		break;
	}

	return return_value;
}
コード例 #7
0
ファイル: pool_proto2.c プロジェクト: Randalthor80/pgpool2
int RowDescription(POOL_CONNECTION *frontend,
				   POOL_CONNECTION_POOL *backend,
				   short *result)
{
	short num_fields, num_fields1 = 0;
	int oid, mod;
	int oid1, mod1;
	short size, size1;
	char *string;
	int len, len1;
	int i;

	pool_read(MASTER(backend), &num_fields, sizeof(short));
	num_fields1 = num_fields;
	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i))
		{
			/* # of fields (could be 0) */
			pool_read(CONNECTION(backend, i), &num_fields, sizeof(short));
			if (num_fields != num_fields1)
			{
				pool_error("RowDescription: num_fields does not match between backends master(%d) and %d th backend(%d)",
						   num_fields, i, num_fields1);
				return POOL_FATAL;
			}
		}
	}

	/* forward it to the frontend */
	pool_write(frontend, "T", 1);
	pool_write(frontend, &num_fields, sizeof(short));
	num_fields = ntohs(num_fields);
	for (i = 0;i<num_fields;i++)
	{
		int j;

		/* field name */
		string = pool_read_string(MASTER(backend), &len, 0);
		if (string == NULL)
			return POOL_END;
		len1 = len;
		if (pool_write(frontend, string, len) < 0)
			return POOL_END;

		for (j=0;j<NUM_BACKENDS;j++)
		{
			if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j))
			{
				string = pool_read_string(CONNECTION(backend, j), &len, 0);
				if (string == NULL)
					return POOL_END;

				if (len != len1)
				{
					pool_error("RowDescription: field length does not match between backends master(%d) and %d th backend(%d)",
							   ntohl(len), j, ntohl(len1));
					return POOL_FATAL;
				}
			}
		}

		/* type oid */
		pool_read(MASTER(backend), &oid, sizeof(int));
		oid1 = oid;
		pool_debug("RowDescription: type oid: %d", ntohl(oid));
		for (j=0;j<NUM_BACKENDS;j++)
		{
			if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j))
			{
				pool_read(CONNECTION(backend, j), &oid, sizeof(int));

				/* we do not regard oid mismatch as fatal */
				if (oid != oid1)
				{
					pool_debug("RowDescription: field oid does not match between backends master(%d) and %d th backend(%d)",
							   ntohl(oid), j, ntohl(oid1));
				}
			}
		}
		if (pool_write(frontend, &oid1, sizeof(int)) < 0)
			return POOL_END;

		/* size */
		pool_read(MASTER(backend), &size, sizeof(short));
		size1 = size;
		for (j=0;j<NUM_BACKENDS;j++)
		{
			if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j))
			{
				pool_read(CONNECTION(backend, j), &size, sizeof(short));
				if (size1 != size1)
				{
					pool_error("RowDescription: field size does not match between backends master(%d) and %d th backend(%d)",
							   ntohs(size), j, ntohs(size1));
					return POOL_FATAL;
				}
			}
		}
		pool_debug("RowDescription: field size: %d", ntohs(size));
		pool_write(frontend, &size1, sizeof(short));

		/* modifier */
		pool_read(MASTER(backend), &mod, sizeof(int));
		pool_debug("RowDescription: modifier: %d", ntohs(mod));
		mod1 = mod;
		for (j=0;j<NUM_BACKENDS;j++)
		{
			if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j))
			{
				pool_read(CONNECTION(backend, j), &mod, sizeof(int));
				if (mod != mod1)
				{
					pool_debug("RowDescription: modifier does not match between backends master(%d) and %d th backend(%d)",
							   ntohl(mod), j, ntohl(mod1));
				}
			}
		}
		if (pool_write(frontend, &mod1, sizeof(int)) < 0)
			return POOL_END;
	}

	*result = num_fields;

	return pool_flush(frontend);
}