예제 #1
0
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;
}
예제 #2
0
/*
 * Collect password response packet from frontend.
 *
 * Returns NULL if couldn't get password, else malloc'd string.
 */
static char *recv_password_packet(POOL_CONNECTION *frontend)
{
	int rsize;
	char *passwd;
	char *returnVal;

	if (frontend->protoVersion == PROTO_MAJOR_V3)
	{
		/* Expect 'p' message type */
		char kind;

		if (pool_read(frontend, &kind, 1) < 0)
			return NULL;

		if (kind != 'p')
		{
			pool_error("expected password response, got message type %c",
					   kind);
			return NULL;		/* bad message type */
		}
	}
	/* pre-3.0 protocol does not send a message type */

	if (pool_read(frontend, &rsize, sizeof(int)) < 0)
		return NULL;

	rsize = ntohl(rsize) - 4;
	passwd = pool_read2(frontend, rsize); /* retrieve password */
	if (passwd == NULL)
		return NULL;

	/* Do not echo password to logs, for security. */
	pool_debug("received password packet from frontend for pgpool's HBA");

	/*
	 * Return the received string.  Note we do not attempt to do any
	 * character-set conversion on it; since we don't yet know the
	 * client's encoding, there wouldn't be much point.
	 */
	returnVal = strdup(passwd);
	if (returnVal == NULL)
	{
		pool_error("recv_password_packet: strdup failed: %s", strerror(errno));
		exit(1);
	}
	return returnVal;
}
예제 #3
0
/* attempt to negotiate a secure connection */
void pool_ssl_negotiate_clientserver(POOL_CONNECTION *cp) {
	int ssl_packet[2] = { htonl(sizeof(int)*2), htonl(NEGOTIATE_SSL_CODE) };
	char server_response;

	cp->ssl_active = -1;

	if ( (!pool_config->ssl) || init_ssl_ctx(cp, ssl_conn_clientserver))
		return;

	ereport(DEBUG1,
		(errmsg("attempting to negotiate a secure connection"),
			 errdetail("sending client->server SSL request")));
	pool_write_and_flush(cp, ssl_packet, sizeof(int)*2);

	if (pool_read(cp, &server_response, 1) < 0)
	{
		ereport(WARNING,
				(errmsg("error while attempting to negotiate a secure connection, pool_read failed")));
 		return;
	}

	ereport(DEBUG1,
		(errmsg("attempting to negotiate a secure connection"),
			 errdetail("client->server SSL response: %c", server_response)));

	switch (server_response) {
		case 'S':
			SSL_set_fd(cp->ssl, cp->fd);
			SSL_RETURN_VOID_IF( (SSL_connect(cp->ssl) < 0),
			                    "SSL_connect");
			cp->ssl_active = 1;
			break;
		case 'N':
			/*
			 * If backend does not support SSL but pgpool does, we get this.
			 * i.e. This is normal.
			 */
			ereport(DEBUG1,
				(errmsg("attempting to negotiate a secure connection"),
					 errdetail("server doesn't want to talk SSL")));
			break;
		default:
			ereport(WARNING,
					(errmsg("error while attempting to negotiate a secure connection, unhandled response: %c", server_response)));
			break;
	}
}
예제 #4
0
POOL_STATUS EmptyQueryResponse(POOL_CONNECTION *frontend,
							   POOL_CONNECTION_POOL *backend)
{
	char c;
	int i;

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i))
		{
			if (pool_read(CONNECTION(backend, i), &c, sizeof(c)) < 0)
				return POOL_END;
		}
	}

	pool_write(frontend, "I", 1);
	return pool_write_and_flush(frontend, "", 1);
}
예제 #5
0
파일: pool.c 프로젝트: mslusarz/nvml
/*
 * pool_get_first_valid_btt -- return offset to first valid BTT Info
 *
 * - Return offset to valid BTT Info header in pool file.
 * - Start looking from given offset.
 * - Convert BTT Info header to host endianness.
 * - Return the BTT Info header by pointer.
 * - If zeroed pointer provided would check if all checked BTT Info are zeroed
 *	which is useful for BLK pools
 */
uint64_t
pool_get_first_valid_btt(struct pool_data *pool, struct btt_info *infop,
	uint64_t offset, bool *zeroed)
{
	/* if we have valid arena get BTT Info header from it */
	if (pool->narenas != 0) {
		struct arena *arenap = TAILQ_FIRST(&pool->arenas);
		memcpy(infop, &arenap->btt_info, sizeof(*infop));
		return arenap->offset;
	}

	const size_t info_size = sizeof(*infop);

	/* theoretical offsets to BTT Info header and backup */
	uint64_t offsets[2] = {offset, 0};

	while (offsets[0] < pool->set_file->size) {
		/* calculate backup offset */
		offsets[1] = pool_next_arena_offset(pool, offsets[0]) -
			info_size;

		/* check both offsets: header and backup */
		for (int i = 0; i < 2; ++i) {
			if (pool_read(pool, infop, info_size, offsets[i]))
				continue;

			/* check if all possible BTT Info are zeroed */
			if (zeroed)
				*zeroed &= util_is_zeroed((const void *)infop,
					info_size);

			/* check if read BTT Info is valid */
			if (pool_btt_info_valid(infop)) {
				btt_info_convert2h(infop);
				return offsets[i];
			}
		}

		/* jump to next arena */
		offsets[0] += BTT_MAX_ARENA;
	}

	return 0;
}
예제 #6
0
static void read_pool_data_routine(void* data)
{
	e_int32 ret,i=0;
	scan_data_t sdata;
	scan_pool_t *pool = (scan_pool_t *) data;
	DMSG((STDOUT,"scan job:read_data_routine start.\r\n"));
	//TODO:更详细的异常处理
	while (1)
	{
		ret = pool_read(pool, &sdata);
		if (ret <= 0)
		{
			break;
		}
		DMSG((STDOUT,"read_data_routine write data at angle: %f.\r\n",(float)sdata.h_angle));
		usleep(100000); //模拟费时的操作100ms
	}
	DMSG((STDOUT,"scan job:write_data_routine done.\r\n"));
	count++;
}
예제 #7
0
static void read_pool_data_routine(laser_sick_t *ls) {
	e_int32 ret;
	scan_data_t sdata;
#if DEBUG_TIME
	e_uint32 start_time;
#endif
	DMSG((STDOUT,"scan job:read_data_routine start.\r\n"));

	//创建数据交错缓冲区
	if (ls->interlace_v > 1)
		ls->scan_data_buf = (scan_data_t*) malloc(
				sizeof(scan_data_t) * ls->interlace_v);

	//TODO:更详细的异常处理
	while (ls->state == STATE_WORK) {
		ret = pool_read(&ls->pool, &sdata);
		if (ret <= 0) {
			DMSG((STDOUT,"pool has been cleared, leave!\r\n"));
			break;
		}
#if DEBUG_TIME
		start_time = GetTickCount();
#endif
//		DMSG((STDOUT,"read_data_routine read data at angle: %f.\r\n", sdata.h_angle));
		filter_data(ls, &sdata);
#if DEBUG_TIME
		DMSG((STDOUT,"[%d] Phrase data use:%u\n",sdata.layer_num,GetTickCount()-start_time));
#endif
	}

	free(ls->scan_data_buf);

	if (e_check(ls->slip_idx != ls->width, "#ERROR# 列数与要求的不一致!\n")) {
		DMSG(
				(STDOUT, "ls->slip_idx = %u, ls->width = %u \n", (unsigned int)ls->slip_idx,(unsigned int)ls->width));
		ls->width = ls->slip_idx; //TODO:修复这里,不允许简单丢掉!!
	}
	pool_cancle(&ls->pool);
	DMSG((STDOUT,"scan job:read_data_routine done.\r\n"));
}
예제 #8
0
파일: check_cto.c 프로젝트: GBuella/nvml
/*
 * cto_read -- (internal) read pmemcto header
 */
static int
cto_read(PMEMpoolcheck *ppc)
{
	/*
	 * Here we want to read the pmemcto header without the pool_hdr as we've
	 * already done it before.
	 *
	 * Take the pointer to fields right after pool_hdr, compute the size and
	 * offset of remaining fields.
	 */
	uint8_t *ptr = (uint8_t *)&ppc->pool->hdr.cto;
	ptr += sizeof(ppc->pool->hdr.cto.hdr);

	size_t size = sizeof(ppc->pool->hdr.cto) -
		sizeof(ppc->pool->hdr.cto.hdr);
	uint64_t offset = sizeof(ppc->pool->hdr.log.hdr);

	if (pool_read(ppc->pool, ptr, size, offset))
		return CHECK_ERR(ppc, "cannot read pmemcto structure");

	return 0;
}
예제 #9
0
/*
* Read startup packet
*
* Read the startup packet and parse the contents.
*/
static StartupPacket *read_startup_packet(POOL_CONNECTION *cp)
{
	StartupPacket *sp;
	StartupPacket_v2 *sp2;
	int protov;
	int len;
	char *p;

	sp = (StartupPacket *)calloc(sizeof(*sp), 1);
	if (!sp)
	{
		pool_error("read_startup_packet: out of memory");
		return NULL;
	}

	if (pool_config->authentication_timeout > 0)
	{
		pool_signal(SIGALRM, authentication_timeout);
		alarm(pool_config->authentication_timeout);
	}

	/* read startup packet length */
	if (pool_read(cp, &len, sizeof(len)))
	{
		pool_error("read_startup_packet: incorrect packet length (%d)", len);
		pool_free_startup_packet(sp);
		alarm(0);
		pool_signal(SIGALRM, SIG_IGN);
		return NULL;
	}
	len = ntohl(len);
	len -= sizeof(len);

	if (len <= 0 || len >= MAX_STARTUP_PACKET_LENGTH)
	{
		pool_error("read_startup_packet: incorrect packet length (%d)", len);
		pool_free_startup_packet(sp);
		alarm(0);
		pool_signal(SIGALRM, SIG_IGN);
		return NULL;
	}

	sp->startup_packet = calloc(len, 1);
	if (!sp->startup_packet)
	{
		pool_error("read_startup_packet: out of memory");
		pool_free_startup_packet(sp);
		alarm(0);
		pool_signal(SIGALRM, SIG_IGN);
		return NULL;
	}

	/* read startup packet */
	if (pool_read(cp, sp->startup_packet, len))
	{
		pool_free_startup_packet(sp);
		alarm(0);
		pool_signal(SIGALRM, SIG_IGN);
		return NULL;
	}

	sp->len = len;
	memcpy(&protov, sp->startup_packet, sizeof(protov));
	sp->major = ntohl(protov)>>16;
	sp->minor = ntohl(protov) & 0x0000ffff;
	p = sp->startup_packet;

	switch(sp->major)
	{
		case PROTO_MAJOR_V2: /* V2 */
			sp2 = (StartupPacket_v2 *)(sp->startup_packet);

			sp->database = calloc(SM_DATABASE+1, 1);
			if (!sp->database)
			{
				pool_error("read_startup_packet: out of memory");
				pool_free_startup_packet(sp);
				alarm(0);
				pool_signal(SIGALRM, SIG_IGN);
				return NULL;
			}
			strncpy(sp->database, sp2->database, SM_DATABASE);

			sp->user = calloc(SM_USER+1, 1);
			if (!sp->user)
			{
				pool_error("read_startup_packet: out of memory");
				pool_free_startup_packet(sp);
				alarm(0);
				pool_signal(SIGALRM, SIG_IGN);
				return NULL;
			}
			strncpy(sp->user, sp2->user, SM_USER);

			break;

		case PROTO_MAJOR_V3: /* V3 */
			p += sizeof(int);	/* skip protocol version info */

			while(*p)
			{
				if (!strcmp("user", p))
				{
					p += (strlen(p) + 1);
					sp->user = strdup(p);
					if (!sp->user)
					{
						pool_error("read_startup_packet: out of memory");
						pool_free_startup_packet(sp);
						alarm(0);
						pool_signal(SIGALRM, SIG_IGN);
						return NULL;
					}
				}
				else if (!strcmp("database", p))
				{
					p += (strlen(p) + 1);
					sp->database = strdup(p);
					if (!sp->database)
					{
						pool_error("read_startup_packet: out of memory");
						pool_free_startup_packet(sp);
						alarm(0);
						pool_signal(SIGALRM, SIG_IGN);
						return NULL;
					}
				}

				/*
				 * From 9.0, the start up packet may include
				 * application name. After receiving such that packet,
				 * backend sends parameter status of application_name.
				 * Upon reusing connection to backend, we need to
				 * emulate this behavior of backend. So we remember
				 * this and send parameter status packet to frontend
				 * instead of backend in
				 * connect_using_existing_connection().
				 */
				else if (!strcmp("application_name", p))
				{
					p += (strlen(p) + 1);
					sp->application_name = p;
					pool_debug("read_startup_packet: application_name: %s", p);
				}

				p += (strlen(p) + 1);
			}
			break;

		case 1234:		/* cancel or SSL request */
			/* set dummy database, user info */
			sp->database = calloc(1, 1);
			if (!sp->database)
			{
				pool_error("read_startup_packet: out of memory");
				pool_free_startup_packet(sp);
				alarm(0);
				pool_signal(SIGALRM, SIG_IGN);
				return NULL;
			}
			sp->user = calloc(1, 1);
			if (!sp->user)
			{
				pool_error("read_startup_packet: out of memory");
				pool_free_startup_packet(sp);
				alarm(0);
				pool_signal(SIGALRM, SIG_IGN);
				return NULL;
			}
			break;

		default:
			pool_error("read_startup_packet: invalid major no: %d", sp->major);
			pool_free_startup_packet(sp);
			alarm(0);
			pool_signal(SIGALRM, SIG_IGN);
			return NULL;
	}

	pool_debug("Protocol Major: %d Minor: %d database: %s user: %s",
			   sp->major, sp->minor, sp->database, sp->user);
	alarm(0);
	pool_signal(SIGALRM, SIG_IGN);
	return sp;
}
예제 #10
0
/*
 * Do authentication. Assuming the only caller is
 * *make_persistent_db_connection().
 */
static int s_do_auth(POOL_CONNECTION_POOL_SLOT *cp, char *password)
{
	char kind;
	int status;
	int length;
	int auth_kind;
	char state;
	char *p;
	int pid, key;
	bool keydata_done;

	/*
	 * read kind expecting 'R' packet (authentication response)
	 */
	status = pool_read(cp->con, &kind, sizeof(kind));
	if (status < 0)
	{
		pool_error("s_do_auth: error while reading message kind");
		return -1;
	}

	if (kind != 'R')
	{
		pool_error("s_do_auth: expecting R got %c", kind);
		return -1;
	}

	/* read message length */
	status = pool_read(cp->con, &length, sizeof(length));
	if (status < 0)
	{
		pool_error("s_do_auth: error while reading message length");
		return -1;
	}
	length = ntohl(length);

	/* read auth kind */
	status = pool_read(cp->con, &auth_kind, sizeof(auth_kind));
	if (status < 0)
	{
		pool_error("s_do_auth: error while reading auth kind");
		return -1;
	}
	auth_kind = ntohl(auth_kind);
	pool_debug("s_do_auth: auth kind: %d", auth_kind);

	if (auth_kind == 0)	/* trust authentication? */
	{
		cp->con->auth_kind = 0;
	}
	else if (auth_kind == 3) /* clear text password? */
	{
		int size = htonl(strlen(password) + 5);

		pool_write(cp->con, "p", 1);
		pool_write(cp->con, &size, sizeof(size));
		pool_write_and_flush(cp->con, password, strlen(password) + 1);
		status = pool_flush(cp->con);
		if (status > 0)
		{
			pool_error("s_do_auth: error while sending clear text password");
			return -1;
		}
		return s_do_auth(cp, password);
	}
	else if (auth_kind == 4) /* crypt password? */
	{
		int size;
		char salt[3];
		char *crypt_password;

		status = pool_read(cp->con, &salt, 2);
		if (status > 0)
		{
			pool_error("s_do_auth: error while reading crypt salt");
			return -1;
		}
		salt[2] = '\0';

		crypt_password = crypt(password, salt);
		size = htonl(strlen(crypt_password) + 5);
		pool_write(cp->con, "p", 1);
		pool_write(cp->con, &size, sizeof(size));
		pool_write_and_flush(cp->con, crypt_password, strlen(crypt_password) + 1);
		status = pool_flush(cp->con);
		if (status > 0)
		{
			pool_error("s_do_auth: error while sending crypt password");
			return -1;
		}
		return s_do_auth(cp, password);
	}
	else if (auth_kind == 5) /* md5 password? */
	{
		char salt[4];
		char *buf, *buf1;
		int size;

		status = pool_read(cp->con, &salt, 4);
		if (status > 0)
		{
			pool_error("s_do_auth: error while reading md5 salt");
			return -1;
		}

		buf = malloc(2 * (MD5_PASSWD_LEN + 4)); /* hash + "md5" + '\0' */
		if (buf == NULL)
		{
			pool_error("s_do_auth(): malloc failed: %s", strerror(errno));
			return -1;
		}
		memset(buf, 0, 2 * (MD5_PASSWD_LEN + 4));

		/* build md5 password */
		buf1 = buf + MD5_PASSWD_LEN + 4;
		pool_md5_encrypt(password, cp->sp->user, strlen(cp->sp->user), buf1);
		pool_md5_encrypt(buf1, salt, 4, buf + 3);
		memcpy(buf, "md5", 3);

		size = htonl(strlen(buf) + 5);
		pool_write(cp->con, "p", 1);
		pool_write(cp->con, &size, sizeof(size));
		pool_write_and_flush(cp->con, buf, strlen(buf) + 1);
		status = pool_flush(cp->con);
		if (status > 0)
		{
			pool_error("s_do_auth: error while sending md5 password");
			return -1;
		}

		status = s_do_auth(cp, password);
		free(buf);
		return status;
	}
	else
	{
		pool_error("s_do_auth: auth kind %d not supported yet", auth_kind);
		return -1;
	}

	/*
	 * Read backend key data and wait until Ready for query arriving or
	 * error happens.
	 */

	keydata_done = false;

	for (;;)
	{
		status = pool_read(cp->con, &kind, sizeof(kind));
		if (status < 0)
		{
			pool_error("s_do_auth: error while reading message kind");
			return -1;
		}

		switch (kind)
		{
			case 'K':	/* backend key data */
				keydata_done = true;
				pool_debug("s_do_auth: backend key data received");

				/* read message length */
				status = pool_read(cp->con, &length, sizeof(length));
				if (status < 0)
				{
					pool_error("s_do_auth: error while reading message length");
					return -1;
				}
				if (ntohl(length) != 12)
				{
					pool_error("s_do_auth: backend key data length is not 12 (%d)", ntohl(length));
				}

				/* read pid */
				if (pool_read(cp->con, &pid, sizeof(pid)) < 0)
				{
					pool_error("s_do_auth: failed to read pid");
					return -1;
				}
				cp->pid = pid;

				/* read key */
				if (pool_read(cp->con, &key, sizeof(key)) < 0)
				{
					pool_error("s_do_auth: failed to read key");
					return -1;
				}
				cp->key = key;
				break;

			case 'Z':	/* Ready for query */
				/* read message length */
				status = pool_read(cp->con, &length, sizeof(length));
				if (status < 0)
				{
					pool_error("s_do_auth: error while reading message length");
					return -1;
				}
				length = ntohl(length);

				/* read transaction state */
				status = pool_read(cp->con, &state, sizeof(state));
				if (status < 0)
				{
					pool_error("s_do_auth: error while reading transaction state");
					return -1;
				}

				pool_debug("s_do_auth: transaction state: %c", state);
				cp->con->tstate = state;

				if (!keydata_done)
				{
					pool_error("s_do_auth: ready for query arrived before receiving keydata");
				}
				return 0;
				break;

			case 'S':	/* parameter status */
			case 'N':	/* notice response */
			case 'E':	/* error response */
				/* Just throw away data */
				status = pool_read(cp->con, &length, sizeof(length));
				if (status < 0)
				{
					pool_error("s_do_auth: error while reading message length. kind:%c", kind);
					return -1;
				}

				length = ntohl(length);
				length -= 4;

				p = pool_read2(cp->con, length);
				if (p == NULL)
					return -1;
				break;

			default:
				pool_error("s_do_auth: unknown response \"%c\" while processing BackendKeyData",
						   kind);
				break;
		}
	}
	return -1;
}
예제 #11
0
/* --------------------------------
 * 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;
}
예제 #12
0
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);
}
예제 #13
0
POOL_STATUS FunctionResultResponse(POOL_CONNECTION *frontend,
								   POOL_CONNECTION_POOL *backend)
{
	char dummy;
	int len;
	char *result = 0;
	int i;

	pool_write(frontend, "V", 1);

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i))
		{
			if (pool_read(CONNECTION(backend, i), &dummy, 1) < 0)
				return POOL_ERROR;
		}
	}
	pool_write(frontend, &dummy, 1);

	/* non empty result? */
	if (dummy == 'G')
	{
		for (i=0;i<NUM_BACKENDS;i++)
		{
			if (VALID_BACKEND(i))
			{
				/* length of result in bytes */
				if (pool_read(CONNECTION(backend, i), &len, sizeof(len)) < 0)
					return POOL_ERROR;
			}
		}
		pool_write(frontend, &len, sizeof(len));

		len = ntohl(len);

		for (i=0;i<NUM_BACKENDS;i++)
		{
			if (VALID_BACKEND(i))
			{
				/* result value itself */
				if ((result = pool_read2(MASTER(backend), len)) == NULL)
					return POOL_ERROR;
			}
		}
		pool_write(frontend, result, len);
	}

	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i))
		{
			/* unused ('0') */
			if (pool_read(MASTER(backend), &dummy, 1) < 0)
				return POOL_ERROR;
		}
	}
	pool_write(frontend, "0", 1);

	return pool_flush(frontend);
}
예제 #14
0
POOL_STATUS AsciiRow(POOL_CONNECTION *frontend,
					 POOL_CONNECTION_POOL *backend,
					 short num_fields)
{
	static char nullmap[8192], nullmap1[8192];
	int nbytes;
	int i, j;
	unsigned char mask;
	int size, size1 = 0;
	char *buf = NULL, *sendbuf = NULL;
	char msgbuf[1024];

	pool_write(frontend, "D", 1);

	nbytes = (num_fields + 7)/8;

	if (nbytes <= 0)
		return POOL_CONTINUE;

	/* NULL map */
	pool_read(MASTER(backend), nullmap, nbytes);
	memcpy(nullmap1, nullmap, nbytes);
	for (i=0;i<NUM_BACKENDS;i++)
	{
		if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i))
		{
			pool_read(CONNECTION(backend, i), nullmap, nbytes);
			if (memcmp(nullmap, nullmap1, nbytes))
			{
				/* XXX: NULLMAP maybe different among
				   backends. If we were a paranoid, we have to treat
				   this as a fatal error. However in the real world
				   we'd better to adapt this situation. Just throw a
				   log... */
				pool_debug("AsciiRow: NULLMAP differ between master and %d th backend", i);
			}
		}
	}

	if (pool_write(frontend, nullmap1, nbytes) < 0)
		return POOL_END;

	mask = 0;

	for (i = 0;i<num_fields;i++)
	{
		if (mask == 0)
			mask = 0x80;

		/* NOT NULL? */
		if (mask & nullmap[i/8])
		{
			/* field size */
			if (pool_read(MASTER(backend), &size, sizeof(int)) < 0)
				return POOL_END;

			size1 = ntohl(size) - 4;

			/* read and send actual data only when size > 0 */
			if (size1 > 0)
			{
				sendbuf = pool_read2(MASTER(backend), size1);
				if (sendbuf == NULL)
					return POOL_END;
			}

			/* forward to frontend */
			pool_write(frontend, &size, sizeof(int));
			pool_write(frontend, sendbuf, size1);
			snprintf(msgbuf, Min(sizeof(msgbuf), size1+1), "%s", sendbuf);
			pool_debug("AsciiRow: len: %d data: %s", size1, msgbuf);

			for (j=0;j<NUM_BACKENDS;j++)
			{
				if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j))
				{
					/* field size */
					if (pool_read(CONNECTION(backend, j), &size, sizeof(int)) < 0)
						return POOL_END;

					buf = NULL;
					size = ntohl(size) - 4;

					/* XXX: field size maybe different among
					   backends. If we were a paranoid, we have to treat
					   this as a fatal error. However in the real world
					   we'd better to adapt this situation. Just throw a
					   log... */
					if (size != size1)
						pool_debug("AsciiRow: %d th field size does not match between master(%d) and %d th backend(%d)",
								   i, ntohl(size), j, ntohl(size1));

					/* read and send actual data only when size > 0 */
					if (size > 0)
					{
						buf = pool_read2(CONNECTION(backend, j), size);
						if (buf == NULL)
							return POOL_END;
					}
				}
			}
		}

		mask >>= 1;
	}

	if (pool_flush(frontend))
		return POOL_END;

	return POOL_CONTINUE;
}