Exemple #1
0
/*
 * Discard connection and memory allocated by
 * make_persistent_db_connection().
 */
void discard_persistent_db_connection(POOL_CONNECTION_POOL_SLOT *cp)
{
	int len;

	if(cp == NULL)
		return;

	pool_write(cp->con, "X", 1);
	len = htonl(4);
	pool_write(cp->con, &len, sizeof(len));

	/*
	 * XXX we cannot call pool_flush() here since backend may already
	 * close the socket and pool_flush() automatically invokes fail
	 * over handler. This could happen in copy command (remember the
	 * famous "lost synchronization with server, resetting
	 * connection" message)
	 */
	pool_set_nonblock(cp->con->fd);
	pool_flush_it(cp->con);
	pool_unset_nonblock(cp->con->fd);

	pool_close(cp->con);
	free(cp->sp->startup_packet);
	free(cp->sp->database);
	free(cp->sp->user);
	free(cp->sp);
	free(cp);
}
Exemple #2
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;
}
Exemple #3
0
/* --------------------------------
 * ForwardCacheToFrontend - simply forwards cached data to the frontend
 *
 * since the cached data passed from the caller is in escaped binary string
 * format, unescape it and send it to the frontend appending 'Z' at the end.
 * returns 0 on success, -1 otherwise.
 * --------------------------------
 */
static int ForwardCacheToFrontend(POOL_CONNECTION *frontend, char *cache, char tstate)
{
	int sendlen;
	size_t sz;
	char *binary_cache = NULL;

	binary_cache = (char *)PQunescapeBytea((unsigned char *)cache, &sz);
	sendlen = (int) sz;
	if (malloc_failed(binary_cache))
		return -1;

	pool_debug("ForwardCacheToFrontend: query cache found (%d bytes)", sendlen);

	/* forward cache to the frontend */
	pool_write(frontend, binary_cache, sendlen);

	/* send ReadyForQuery to the frontend*/
	pool_write(frontend, "Z", 1);
	sendlen = htonl(5);
	pool_write(frontend, &sendlen, sizeof(int));
	if (pool_write_and_flush(frontend, &tstate, 1) < 0)
	{
		pool_error("pool_query_cache_lookup: error while writing data to the frontend");
		PQfreemem(binary_cache);
		return -1;
	}

	PQfreemem(binary_cache);
	return 0;
}
Exemple #4
0
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);
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
bool
pool_write_data(TDS_POOL_SOCKET *from, TDS_POOL_SOCKET *to)
{
	int ret;
	TDSSOCKET *tds;

	tdsdump_log(TDS_DBG_INFO1, "trying to send\n");

	tds = from->tds;
	tdsdump_log(TDS_DBG_INFO1, "sending %d bytes\n", tds->in_len);
	/* cf. net.c for better technique.  */
	ret = pool_write(tds_get_s(to->tds), tds->in_buf + tds->in_pos, tds->in_len - tds->in_pos);
	/* write failed, cleanup member */
	if (ret < 0)
		return false;

	tds->in_pos += ret;
	if (tds->in_pos < tds->in_len) {
		/* partial write, schedule a future write */
		to->poll_send = true;
		from->poll_recv = false;
	} else {
		to->poll_send = false;
		from->poll_recv = true;
	}
	return true;
}
Exemple #8
0
/*
* send startup packet
*/
int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp)
{
	int len;

	len = htonl(cp->sp->len + sizeof(len));
	pool_write(cp->con, &len, sizeof(len));
	return pool_write_and_flush(cp->con, cp->sp->startup_packet, cp->sp->len);
}
void send_complete_and_ready(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, const int num_rows)
{
	int len;
	int msg_len;
	char msg[16];

	msg_len = snprintf(msg, 16, "SELECT %d", num_rows);

	/* if we had more than 16 bytes, including '\0', the string was truncatured
	 * shouldn't happen though, as it would means more than "SELECT 99999999" */
	if (msg_len > 15) msg_len = 15;

	/* complete command response */
	pool_write(frontend, "C", 1);
	if (MAJOR(backend) == PROTO_MAJOR_V3)
	{
		len = htonl(4 + strlen(msg)+1);
		pool_write(frontend, &len, sizeof(len));
	}
	pool_write(frontend, msg, strlen(msg)+1);

	/* ready for query */
	pool_write(frontend, "Z", 1);
	if (MAJOR(backend) == PROTO_MAJOR_V3)
	{
		len = htonl(5);
		pool_write(frontend, &len, sizeof(len));
		pool_write(frontend, "I", 1);
	}

	pool_flush(frontend);
}
Exemple #10
0
static void sendAuthRequest(POOL_CONNECTION *frontend, AuthRequest areq)
{
	int wsize;					/* number of bytes to write */
	int areq_nbo;				/* areq in network byte order */

	/*
	 * If AUTH_REQ_OK, then frontend is OK to connect __with_pgpool__.
	 * Do not send 'R' to the frontend, he still needs to authenticate
	 * himself with the backend.
	 */
	if (areq == AUTH_REQ_OK)
		return;

	/* request a password */
	pool_write(frontend, "R", 1);

	if (frontend->protoVersion == PROTO_MAJOR_V3)
	{
/* 		if (areq == AUTH_REQ_MD5) */
/* 			wsize = htonl(sizeof(int)*2+4); */
/* 		else if (areq == AUTH_REQ_CRYPT) */
/* 			wsize = htonl(sizeof(int)*2+2); */
/* 		else */
			wsize = htonl(sizeof(int)*2);
		pool_write(frontend, &wsize, sizeof(int));
	}

	areq_nbo = htonl(areq);
	pool_write(frontend, &areq_nbo, sizeof(int));

	/* Add the salt for encrypted passwords. */
/* 	if (areq == AUTH_REQ_MD5) */
/* 		pq_sendbytes(&buf, port->md5Salt, 4); */
/* 	else if (areq == AUTH_REQ_CRYPT) */
/* 		pq_sendbytes(&buf, port->cryptSalt, 2); */

	pool_flush(frontend);
}
void version_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
{
	static short num_fields = 1;
	static char *field_names[] = {"pool_version"};
	short s;
	int len;
	int size;
	int hsize;

	static unsigned char nullmap[2] = {0xff, 0xff};
	int nbytes = (num_fields + 7)/8;

	POOL_REPORT_VERSION *version = get_version();

	send_row_description(frontend, backend, num_fields, field_names);

	if (MAJOR(backend) == PROTO_MAJOR_V2)
	{
		/* ascii row */
			pool_write(frontend, "D", 1);
			pool_write_and_flush(frontend, nullmap, nbytes);

		size = strlen(version[0].version);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
		pool_write(frontend, version[0].version, size);
	}
	else
	{
		/* data row */
			pool_write(frontend, "D", 1);
		len = 6; /* int32 + int16; */
		len += 4 + strlen(version[0].version); /* int32 + data */
			len = htonl(len);
			pool_write(frontend, &len, sizeof(len));
			s = htons(num_fields);
			pool_write(frontend, &s, sizeof(s));

		len = htonl(strlen(version[0].version));
			pool_write(frontend, &len, sizeof(len));
		pool_write(frontend, version[0].version, strlen(version[0].version));
	}

	send_complete_and_ready(frontend, backend, 1);

	free(version);
	}
Exemple #12
0
static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
{
	int index;
	char *name, *value;
	int len, sendlen;

	index = 0;
	while (pool_get_param(&MASTER(backend)->params, index++, &name, &value) == 0)
	{
		pool_write(frontend, "S", 1);
		len = sizeof(sendlen) + strlen(name) + 1 + strlen(value) + 1;
		sendlen = htonl(len);
		pool_write(frontend, &sendlen, sizeof(sendlen));
		pool_write(frontend, name, strlen(name) + 1);
		pool_write(frontend, value, strlen(value) + 1);
	}

	if (pool_flush(frontend))
	{
		pool_error("pool_send_params: pool_flush() failed");
		return -1;
	}
	return 0;
}
Exemple #13
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);
}
Exemple #14
0
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;
}
Exemple #15
0
static void write_pool_data_routine(void* data)
{
	e_int32 ret,i;
	scan_data_t sdata;
	scan_pool_t *pool = (scan_pool_t *) data;
	DMSG((STDOUT,"scan job:write_data_routine start.\r\n"));
	//TODO:更详细的异常处理
	for(i=0;i<DATA_NUMBER;i++)
	{
		sdata.h_angle = (e_float64)i;
		ret = pool_write(pool, &sdata);
		if (ret <= 0)
		{
			break;
		}
	}
	DMSG((STDOUT,"scan job:write_data_routine done."));
	pool_disconnect(pool);//断开队列
//	pool_cancle(pool);//比较两者的不同行为
	count++;
}
Exemple #16
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);
}
void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
		{
	static short num_fields = 5;
	static char *field_names[] = {"node_id","hostname", "port", "status", "lb_weight"};
	int i;
	short s;
	int len;
	int nrows;
	int size;
	int hsize;
	static unsigned char nullmap[2] = {0xff, 0xff};
	int nbytes = (num_fields + 7)/8;

	POOL_REPORT_NODES* nodes = get_nodes(&nrows);

	send_row_description(frontend, backend, num_fields, field_names);

	if (MAJOR(backend) == PROTO_MAJOR_V2)
	{
		/* ascii row */
		for (i=0;i<nrows;i++)
		{
			pool_write(frontend, "D", 1);
			pool_write_and_flush(frontend, nullmap, nbytes);

			size = strlen(nodes[i].node_id);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, nodes[i].node_id, size);

			size = strlen(nodes[i].hostname);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, nodes[i].hostname, size);

			size = strlen(nodes[i].port);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, nodes[i].port, size);

			size = strlen(nodes[i].status);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, nodes[i].status, size);

			size = strlen(nodes[i].lb_weight);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, nodes[i].lb_weight, size);
		}
	}
	else
	{
		/* data row */
		for (i=0;i<nrows;i++)
		{
			pool_write(frontend, "D", 1);
			len = 6; /* int32 + int16; */
			len += 4 + strlen(nodes[i].node_id);   /* int32 + data; */
			len += 4 + strlen(nodes[i].hostname);  /* int32 + data; */
			len += 4 + strlen(nodes[i].port);      /* int32 + data; */
			len += 4 + strlen(nodes[i].status);    /* int32 + data; */
			len += 4 + strlen(nodes[i].lb_weight); /* int32 + data; */
			len = htonl(len);
			pool_write(frontend, &len, sizeof(len));
			s = htons(num_fields);
			pool_write(frontend, &s, sizeof(s));

			len = htonl(strlen(nodes[i].node_id));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, nodes[i].node_id, strlen(nodes[i].node_id));

			len = htonl(strlen(nodes[i].hostname));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, nodes[i].hostname, strlen(nodes[i].hostname));

			len = htonl(strlen(nodes[i].port));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, nodes[i].port, strlen(nodes[i].port));

			len = htonl(strlen(nodes[i].status));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, nodes[i].status, strlen(nodes[i].status));

			len = htonl(strlen(nodes[i].lb_weight));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, nodes[i].lb_weight, strlen(nodes[i].lb_weight));
		}
	}

	send_complete_and_ready(frontend, backend, nrows);

	free(nodes);
	}
void pools_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
{
	static short num_fields = 12;
	static char *field_names[] = {"pool_pid", "start_time", "pool_id", "backend_id", "database", "username", "create_time",
                                  "majorversion", "minorversion", "pool_counter", "pool_backendpid", "pool_connected"};
	short s;
	int len;
	int i;
	static unsigned char nullmap[2] = {0xff, 0xff};
	int nbytes = (num_fields + 7)/8;
	int nrows;
	int size;
	int hsize;
	char proc_pid[16];
	char pool_id[16];
	char proc_start_time[20];
	char proc_create_time[20];
	char majorversion[5];
	char minorversion[5];
	char pool_counter[16];
	char backend_id[16];
	char backend_pid[16];
	char connected[2];

    POOL_REPORT_POOLS *pools = get_pools(&nrows);

	send_row_description(frontend, backend, num_fields, field_names);

	if (MAJOR(backend) == PROTO_MAJOR_V2) hsize = 4;
	else hsize = 0;

		/* ascii row */
		for (i=0;i<nrows;i++)
		{
			snprintf(proc_pid, sizeof(proc_pid), "%d", pools[i].pool_pid);
			snprintf(pool_id, sizeof(pool_id), "%d", pools[i].pool_id);
			if (pools[i].start_time)
				strftime(proc_start_time, POOLCONFIG_MAXDATELEN, "%Y-%m-%d %H:%M:%S", localtime(&pools[i].start_time));
			else
				*proc_start_time = '\0';
			if (pools[i].create_time)
				strftime(proc_create_time, POOLCONFIG_MAXDATELEN, "%Y-%m-%d %H:%M:%S", localtime(&pools[i].create_time));
			else
				*proc_create_time = '\0';
			snprintf(majorversion, sizeof(majorversion), "%d", pools[i].pool_majorversion);
			snprintf(minorversion, sizeof(minorversion), "%d", pools[i].pool_minorversion);
			snprintf(pool_counter, sizeof(pool_counter), "%d", pools[i].pool_counter);
			snprintf(backend_id, sizeof(backend_pid), "%d", pools[i].backend_id);
			snprintf(backend_pid, sizeof(backend_pid), "%d", pools[i].pool_backendpid);
			snprintf(connected, sizeof(connected), "%d", pools[i].pool_connected);

			if (MAJOR(backend) == PROTO_MAJOR_V2)
			{
				pool_write(frontend, "D", 1);
				pool_write_and_flush(frontend, nullmap, nbytes);
			}
			else
			{
				pool_write(frontend, "D", 1);
				len = 6; /* int32 + int16; */
				len += 4 + strlen(proc_pid);          /* int32 + data */
				len += 4 + strlen(proc_start_time);        /* int32 + data */
				len += 4 + strlen(pool_id);           /* int32 + data */
				len += 4 + strlen(backend_id);        /* int32 + data */
				len += 4 + strlen(pools[i].database);          /* int32 + data */
				len += 4 + strlen(pools[i].username);          /* int32 + data */
				len += 4 + strlen(proc_create_time);       /* int32 + data */
				len += 4 + strlen(majorversion); /* int32 + data */
				len += 4 + strlen(minorversion); /* int32 + data */
				len += 4 + strlen(pool_counter);      /* int32 + data */
				len += 4 + strlen(backend_pid);   /* int32 + data */
				len += 4 + strlen(connected);    /* int32 + data */
			
				len = htonl(len);
				pool_write(frontend, &len, sizeof(len));
				s = htons(num_fields);
				pool_write(frontend, &s, sizeof(s));
			}

			len = strlen(proc_pid);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, proc_pid, len);

			len = strlen(proc_start_time);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, proc_start_time, len);

			len = strlen(pool_id);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, pool_id, len);

			len = strlen(backend_id);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, backend_id, len);

			len = strlen(pools[i].database);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, pools[i].database, len);

			len = strlen(pools[i].username);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, pools[i].username, len);

			len = strlen(proc_create_time);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, proc_create_time, len);

			len = strlen(majorversion);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, majorversion, len);

			len = strlen(minorversion);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, minorversion, len);

			len = strlen(pool_counter);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, pool_counter, len);

			len = strlen(backend_pid);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, backend_pid, len);

			len = strlen(connected);
			size = htonl(len+hsize);
			pool_write(frontend, &size, sizeof(size));
			pool_write(frontend, connected, len);
		}

	send_complete_and_ready(frontend, backend, nrows);

	free(pools);
}
void send_row_description(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
							short num_fields, char **field_names)
{
	static char *cursorname = "blank";
	static int oid = 0;
	static short fsize = -1;
	static int mod = 0;
	short n;
	int i;
	short s;
	int len;
	short colnum;

	if (MAJOR(backend) == PROTO_MAJOR_V2)
	{
		/* cursor response */
		pool_write(frontend, "P", 1);
		pool_write(frontend, cursorname, strlen(cursorname)+1);
	}

	/* row description */
	pool_write(frontend, "T", 1);

	if (MAJOR(backend) == PROTO_MAJOR_V3)
	{
		/* information about computed byte in section "RowDescription (B)" here:
		 * http://www.postgresql.org/docs/current/static/protocol-message-formats.html */

		len = 6; /* int32 + int16 */

		for (i=0;i<num_fields;i++)
		{
			/* String + '\0' + 3* int32 + 3* int16 */
			len += strlen(field_names[i]) +1 +18;
		}

		len = htonl(len);
		pool_write(frontend, &len, sizeof(len));
	}

	n = htons(num_fields);
	pool_write(frontend, &n, sizeof(short));

	for (i=0;i<num_fields;i++)
	{
		pool_write(frontend, field_names[i], strlen(field_names[i])+1);		/* field name */

		if (MAJOR(backend) == PROTO_MAJOR_V3)
		{
			pool_write(frontend, &oid, sizeof(oid));	/* table oid */
			colnum = htons(i);
			pool_write(frontend, &colnum, sizeof(colnum));	/* column number */
		}

		pool_write(frontend, &oid, sizeof(oid));		/* data type oid */
		s = htons(fsize);
		pool_write(frontend, &s, sizeof(fsize));		/* field size */
		pool_write(frontend, &mod, sizeof(mod));		/* modifier */

		if (MAJOR(backend) == PROTO_MAJOR_V3)
		{
			s = htons(0);
			pool_write(frontend, &s, sizeof(fsize));	/* field format (text) */
		}
	}
	pool_flush(frontend);
}
void config_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
		{
	static char *field_names[] = {"item", "value", "description"};
	static unsigned char nullmap[2] = {0xff, 0xff};
	static short num_fields = 3;
	short s;
	int nbytes = (num_fields + 7)/8;
	int len;
	int nrows;
	int size;
	int hsize;
	int i;

	POOL_REPORT_CONFIG *status = get_config(&nrows);

	send_row_description(frontend, backend, num_fields, field_names);

	if (MAJOR(backend) == PROTO_MAJOR_V2)
	{
		/* ascii row */
		for (i=0;i<nrows;i++)
		{
			pool_write(frontend, "D", 1);
			pool_write_and_flush(frontend, nullmap, nbytes);

			size = strlen(status[i].name);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, status[i].name, size);

			size = strlen(status[i].value);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, status[i].value, size);

			size = strlen(status[i].desc);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, status[i].desc, size);
		}
	}
	else
	{
		/* data row */
		for (i=0;i<nrows;i++)
		{
			pool_write(frontend, "D", 1);
			len = 6; /* int32 + int16; */
			len += 4 + strlen(status[i].name);  /* int32 + data; */
			len += 4 + strlen(status[i].value); /* int32 + data; */
			len += 4 + strlen(status[i].desc);  /* int32 + data; */
			len = htonl(len);
			pool_write(frontend, &len, sizeof(len));
			s = htons(num_fields);
			pool_write(frontend, &s, sizeof(s));

			len = htonl(strlen(status[i].name));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, status[i].name, strlen(status[i].name));

			len = htonl(strlen(status[i].value));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, status[i].value, strlen(status[i].value));

			len = htonl(strlen(status[i].desc));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, status[i].desc, strlen(status[i].desc));
		}
	}

	send_complete_and_ready(frontend, backend, nrows);

	free(status);
}
void processes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
		{
	static short num_fields = 6;
	static char *field_names[] = {"pool_pid", "start_time", "database", "username", "create_time", "pool_counter"};
	short s;
	int len;
	int nrows;
	int size;
	int hsize;
    int i;
    static unsigned char nullmap[2] = {0xff, 0xff};
	int nbytes = (num_fields + 7)/8;

    POOL_REPORT_PROCESSES *processes = get_processes(&nrows);

	send_row_description(frontend, backend, num_fields, field_names);

	if (MAJOR(backend) == PROTO_MAJOR_V2)
	{
		/* ascii row */
		for (i=0;i<nrows;i++)
		{
			pool_write(frontend, "D", 1);
			pool_write_and_flush(frontend, nullmap, nbytes);

			size = strlen(processes[i].pool_pid);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, processes[i].pool_pid, size);

			size = strlen(processes[i].start_time);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, processes[i].start_time, size);

			size = strlen(processes[i].database);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, processes[i].database, size);

			size = strlen(processes[i].username);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, processes[i].username, size);

			size = strlen(processes[i].create_time);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, processes[i].create_time, size);

			size = strlen(processes[i].pool_counter);
			hsize = htonl(size+4);
			pool_write(frontend, &hsize, sizeof(hsize));
			pool_write(frontend, processes[i].pool_counter, size);
		}
	}
	else
	{
		/* data row */
		for (i=0;i<nrows;i++)
		{
			pool_write(frontend, "D", 1);
			len = 6; /* int32 + int16; */
			len += 4 + strlen(processes[i].pool_pid);     /* int32 + data */
			len += 4 + strlen(processes[i].start_time);   /* int32 + data */
			len += 4 + strlen(processes[i].database);     /* int32 + data */
			len += 4 + strlen(processes[i].username);     /* int32 + data */
			len += 4 + strlen(processes[i].create_time);  /* int32 + data */
			len += 4 + strlen(processes[i].pool_counter); /* int32 + data */
			len = htonl(len);
			pool_write(frontend, &len, sizeof(len));
			s = htons(num_fields);
			pool_write(frontend, &s, sizeof(s));

			len = htonl(strlen(processes[i].pool_pid));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, processes[i].pool_pid, strlen(processes[i].pool_pid));

			len = htonl(strlen(processes[i].start_time));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, processes[i].start_time, strlen(processes[i].start_time));

			len = htonl(strlen(processes[i].database));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, processes[i].database, strlen(processes[i].database));

			len = htonl(strlen(processes[i].username));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, processes[i].username, strlen(processes[i].username));

			len = htonl(strlen(processes[i].create_time));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, processes[i].create_time, strlen(processes[i].create_time));

			len = htonl(strlen(processes[i].pool_counter));
			pool_write(frontend, &len, sizeof(len));
			pool_write(frontend, processes[i].pool_counter, strlen(processes[i].pool_counter));
		}
	}

	send_complete_and_ready(frontend, backend, nrows);

	free(processes);
	}
Exemple #22
0
/*
* combo of pool_write and pool_flush
*/
int pool_write_and_flush(POOL_CONNECTION *cp, void *buf, int len)
{
	if (pool_write(cp, buf, len))
		return -1;
	return pool_flush(cp);
}
Exemple #23
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;
}
Exemple #24
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;
}
Exemple #25
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);
}
Exemple #26
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;
}
Exemple #27
0
/*
 * process cancel request
 */
void cancel_request(CancelPacket *sp)
{
	int	len;
	int fd;
	POOL_CONNECTION *con;
	int i,j,k;
	ConnectionInfo *c = NULL;
	CancelPacket cp;
	bool found = false;

	pool_debug("Cancel request received");

	/* look for cancel key from shmem info */
	for (i=0;i<pool_config->num_init_children;i++)
	{
		for (j=0;j<pool_config->max_pool;j++)
		{
			for (k=0;k<NUM_BACKENDS;k++)
			{
				c = pool_coninfo(i, j, k);
				pool_debug("con_info: address:%p database:%s user:%s pid:%d key:%d i:%d",
						   c, c->database, c->user, ntohl(c->pid), ntohl(c->key),i);

				if (c->pid == sp->pid && c->key == sp->key)
				{
					pool_debug("found pid:%d key:%d i:%d",ntohl(c->pid), ntohl(c->key),i);
					c = pool_coninfo(i, j, 0);
					found = true;
					goto found;
				}
			}
		}
	}

 found:
	if (!found)
	{
		pool_error("cancel_request: invalid cancel key: pid:%d key:%d",ntohl(sp->pid), ntohl(sp->key));
		return;	/* invalid key */
	}

	for (i=0;i<NUM_BACKENDS;i++,c++)
	{
		if (!VALID_BACKEND(i))
			continue;

		if (*(BACKEND_INFO(i).backend_hostname) == '/')
			fd = connect_unix_domain_socket(i, TRUE);
		else
			fd = connect_inet_domain_socket(i, TRUE);

		if (fd < 0)
		{
			pool_error("Could not create socket for sending cancel request for backend %d", i);
			return;
		}

		con = pool_open(fd);
		if (con == NULL)
			return;

		len = htonl(sizeof(len) + sizeof(CancelPacket));
		pool_write(con, &len, sizeof(len));

		cp.protoVersion = sp->protoVersion;
		cp.pid = c->pid;
		cp.key = c->key;

		pool_log("cancel_request: canceling backend pid:%d key: %d", ntohl(cp.pid),ntohl(cp.key));

		if (pool_write_and_flush(con, &cp, sizeof(CancelPacket)) < 0)
			pool_error("Could not send cancel request packet for backend %d", i);

		pool_close(con);

		/*
		 * this is needed to ensure that the next DB node executes the
		 * query supposed to be canceled.
		 */
		sleep(1);
	}
}
Exemple #28
0
/*
 * Reuse existing connection
 */
static bool connect_using_existing_connection(POOL_CONNECTION *frontend, 
											  POOL_CONNECTION_POOL *backend,
											  StartupPacket *sp)
{
	int i, freed = 0;
	/*
	 * Save startup packet info
	 */
	for (i = 0; i < NUM_BACKENDS; i++)
	{
		if (VALID_BACKEND(i))
		{
			if (!freed)
			{
				pool_free_startup_packet(backend->slots[i]->sp);
				freed = 1;
			}
			backend->slots[i]->sp = sp;
		}
	}

	/* Reuse existing connection to backend */

	if (pool_do_reauth(frontend, backend))
	{
		pool_close(frontend);
		connection_count_down();
		return false;
	}

	if (MAJOR(backend) == 3)
	{
		char command_buf[1024];

		/* If we have received application_name in the start up
		 * packet, we send SET command to backend. Also we add or
		 * replace existing application_name data.
		 */
		if (sp->application_name)
		{
			snprintf(command_buf, sizeof(command_buf), "SET application_name TO '%s'", sp->application_name);

			for (i=0;i<NUM_BACKENDS;i++)
			{
				if (VALID_BACKEND(i))
					if (do_command(frontend, CONNECTION(backend, i),
							   command_buf, MAJOR(backend),
								   MASTER_CONNECTION(backend)->pid,
								   MASTER_CONNECTION(backend)->key, 0) != POOL_CONTINUE)
					{
						pool_error("connect_using_existing_connection: do_command failed. command: %s", command_buf);
						return false;
					}
			}

			pool_add_param(&MASTER(backend)->params, "application_name", sp->application_name);
		}

		if (send_params(frontend, backend))
		{
			pool_close(frontend);
			connection_count_down();
			return false;
		}
	}

	/* Send ReadyForQuery to frontend */
	pool_write(frontend, "Z", 1);

	if (MAJOR(backend) == 3)
	{
		int len;
		char tstate;

		len = htonl(5);
		pool_write(frontend, &len, sizeof(len));
		tstate = TSTATE(backend, MASTER_NODE_ID);
		pool_write(frontend, &tstate, 1);
	}

	if (pool_flush(frontend) < 0)
	{
		pool_close(frontend);
		connection_count_down();
		return false;
	}
	return true;
}
Exemple #29
0
static void write_pool_data_routine(laser_sick_t *ls) {
	e_int32 ret, first_time = 1, delay, profile_number;
	e_float64 angle_dif, started_angle, before_angle; //记录起始位置,保证180度是对齐的
	scan_data_t sdata = { 0 };
#if DEBUG_TIME
	e_uint32 start_time;
#endif

	DMSG((STDOUT,"scan job:write_data_routine start.\r\n"));
	angle_dif = ls->angle_dif_per_cloumn;
	delay = ANGLE_TO_STEP(angle_dif) * PULSE_SPEED_TO_STEP_TIME(ls->speed_h)
			/ 1e3;
	before_angle =
			STEP_TO_ANGLE((630000.0/PULSE_SPEED_TO_STEP_TIME(ls->speed_h)));

	ret = sld_set_sensor_mode_to_rotate(ls->sick);
	e_assert(ret>0);

	DMSG((STDOUT,"control trun to start angle...\n"));
//等待扫描仪就位,会有准备工作开始
	do {
		sdata.h_angle = lm_turntable_get_angle() - ls->pre_scan_angle
				+ ls->start_angle_h;
		if (sdata.h_angle > ls->start_angle_h - before_angle) {
			break;
		}
		Delay(delay);
	} while (ls->state == STATE_WORK);

	DMSG((STDOUT,"control now on start angle.start to get data...\n"));

	ret = sld_set_sensor_mode_to_measure_ex(ls->sick);
	e_assert(ret>0);

	ret = lm_start_record_angle(ls->writer);
	e_assert(ret>0);

	while (ls->state == STATE_WORK) {
#if DEBUG_TIME
		start_time = GetTickCount();
#endif
		ret = sld_get_measurements_ex(ls->sick, &sdata);
//		DMSG((STDOUT,"profile_counter=%d profile_number=%d\n",sdata.profile_counter,sdata.profile_number));
		if (!first_time) {
			if (profile_number != sdata.profile_number)
				DMSG(
						(STDOUT,"lost a data layer_num=%d profile_number=%d\n",sdata.layer_num,profile_number));
		}
		profile_number = sdata.profile_number + 1;

		if (ret == E_ERROR_TIME_OUT) {
			DMSG((STDOUT,"sld_get_measurements ERROR: RETRY.\r\n"));
			Delay(10);
			continue;
		} else if (ret <= 0) {
			DMSG(
					(STDOUT,"sld_get_measurements sickld is down?ret=%d Out.\r\n",(int)ret));
			break;
		}
#if DEBUG_TIME
		DMSG((STDOUT,"Get use %u\n",GetTickCount()-start_time));
#endif
//		print_sdata(ls,&sdata);
		ret = pool_write(&ls->pool, &sdata);
		if (ret < 0)
			DMSG(
					(STDOUT,"data pool disconnected,write data routine now stop.\n"));
//		DMSG((STDOUT,"[%d] %f end: %f\n",sdata.profile_number, sdata.h_angle,ls->end_angle_h));
		first_time = 0;
	}
	lm_stop_record_angle();
	sld_set_sensor_mode_to_idle(ls->sick);
	DMSG((STDOUT,"scan job:write_data_routine done.\n"));
}