Beispiel #1
0
static void
process_recovery_request(PCP_CONNECTION *frontend,char *buf)
{
	int wsize;
	char code[] = "CommandComplete";
	int node_id = atoi(buf);

	if ( (node_id < 0) || (node_id >= pool_config->backend_desc->num_backends) )
		ereport(ERROR,
			(errmsg("process recovery request failed"),
				 errdetail("node id %d is not valid", node_id)));

	if ((!REPLICATION &&
		 !(MASTER_SLAVE &&
		   !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP))) ||
		(MASTER_SLAVE &&
		 !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP) &&
		 node_id == PRIMARY_NODE_ID))
	{
		if (MASTER_SLAVE && !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP))
			ereport(ERROR,
				(errmsg("process recovery request failed"),
					 errdetail("primary server cannot be recovered by online recovery.")));
		else
			ereport(ERROR,
				(errmsg("process recovery request failed"),
					 errdetail("recovery request is accepted only in replication mode or stereaming replication mode.")));
	}
	else
	{
		if (pcp_mark_recovery_in_progress() == false)
			ereport(FATAL,
				(errmsg("process recovery request failed"),
					 errdetail("pgpool-II is already processing another recovery request.")));

		ereport(DEBUG1,
			(errmsg("PCP: processing recovery request"),
				 errdetail("start online recovery")));

		PG_TRY();
		{
			start_recovery(node_id);
			finish_recovery();
			pcp_write(frontend, "c", 1);
			wsize = htonl(sizeof(code) + sizeof(int));
			pcp_write(frontend, &wsize, sizeof(int));
			pcp_write(frontend, code, sizeof(code));
			do_pcp_flush(frontend);
			pcp_mark_recovery_finished();
		}
		PG_CATCH();
		{
			finish_recovery();
			pcp_mark_recovery_finished();
			PG_RE_THROW();
			
		}PG_END_TRY();
	}
	do_pcp_flush(frontend);
}
Beispiel #2
0
static void
process_status_request(PCP_CONNECTION *frontend)
{
	int nrows = 0;
	int i;
	POOL_REPORT_CONFIG *status = get_config(&nrows);
	int len = 0;
	/* First, send array size of connection_info */
	char arr_code[] = "ArraySize";
	char code[] = "ProcessConfig";
	/* Finally, indicate that all data is sent */
	char fin_code[] = "CommandComplete";

	pcp_write(frontend, "b", 1);
	len = htonl(sizeof(arr_code) + sizeof(int) + sizeof(int));
	pcp_write(frontend, &len, sizeof(int));
	pcp_write(frontend, arr_code, sizeof(arr_code));
	len = htonl(nrows);
	pcp_write(frontend, &len, sizeof(int));

	do_pcp_flush(frontend);

	for (i = 0; i < nrows; i++)
	{
		pcp_write(frontend, "b", 1);
		len = htonl(sizeof(int)
					+ sizeof(code)
					+ strlen(status[i].name) + 1
					+ strlen(status[i].value) + 1
					+ strlen(status[i].desc) + 1
					);

		pcp_write(frontend, &len, sizeof(int));
		pcp_write(frontend, code, sizeof(code));
		pcp_write(frontend, status[i].name, strlen(status[i].name)+1);
		pcp_write(frontend, status[i].value, strlen(status[i].value)+1);
		pcp_write(frontend, status[i].desc, strlen(status[i].desc)+1);
	}

	pcp_write(frontend, "b", 1);
	len = htonl(sizeof(fin_code) + sizeof(int));
	pcp_write(frontend, &len, sizeof(int));
	pcp_write(frontend, fin_code, sizeof(fin_code));
	do_pcp_flush(frontend);

	pfree(status);
	ereport(DEBUG1,
			(errmsg("PCP: processing status request"),
			 errdetail("retrieved status information")));
}
Beispiel #3
0
static void
process_detach_node(PCP_CONNECTION *frontend,char *buf, char tos)
{
	int node_id;
	int wsize;
	char code[] = "CommandComplete";
	bool gracefully;

	if (tos == 'D')
		gracefully = false;
	else
		gracefully = true;

	node_id = atoi(buf);
	ereport(DEBUG1,
			(errmsg("PCP: processing detach node"),
			 errdetail("detaching Node ID %d", node_id)));

	pool_detach_node(node_id, gracefully);

	pcp_write(frontend, "d", 1);
	wsize = htonl(sizeof(code) + sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	do_pcp_flush(frontend);
}
Beispiel #4
0
static void
process_set_configration_parameter(PCP_CONNECTION *frontend,char *buf, int len)
{
	char* param_name;
	char* param_value;
	int wsize;
	char code[] = "CommandComplete";

	param_name = buf;
	if(param_name == NULL)
		ereport(ERROR,
				(errmsg("PCP: set configuration parameter failed"),
				 errdetail("invalid pcp packet received from client")));

	param_value = (char *) memchr(buf, '\0', len);
	if(param_value == NULL)
		ereport(ERROR,
			(errmsg("set configuration parameter failed"),
				 errdetail("invalid pcp packet received from client")));

	param_value +=1;
	ereport(LOG,
			(errmsg("set configuration parameter, \"%s TO %s\"",param_name,param_value)));
	
	if(strcasecmp(param_name, "client_min_messages") == 0)
	{
		const char *ordered_valid_values[] = {"debug5","debug4","debug3","debug2","debug1","log","commerror","info","notice","warning","error",NULL};
		bool found = false;
		int i;
		for(i=0; ; i++)
		{
			char* valid_val = (char*)ordered_valid_values[i];
			if(!valid_val)
				break;

			if (!strcasecmp(param_value, valid_val))
			{
				found = true;
				pool_config->client_min_messages = i + 10;
				ereport(DEBUG1,
					(errmsg("PCP setting parameter \"%s\" to \"%s\"",param_name,param_value)));
				break;
			}
		}
		if (!found)
			ereport(ERROR,
				(errmsg("PCP: set configuration parameter failed"),
					 errdetail("invalid value \"%s\" for parameter \"%s\"",param_value,param_name)));
	}
	else
		ereport(ERROR,
			(errmsg("PCP: set configuration parameter failed"),
				 errdetail("invalid parameter \"%s\"",param_name)));

	pcp_write(frontend, "a", 1);
	wsize = htonl(sizeof(code) + sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	do_pcp_flush(frontend);
}
Beispiel #5
0
static void
process_authentication(PCP_CONNECTION *frontend, char *buf, char* salt, int *random_salt)
{
	int wsize;
	int authenticated;

	if (*random_salt)
	{
		authenticated = user_authenticate(buf, pcp_conf_file, salt, 4);
	}
	if (!*random_salt || !authenticated)
	{
		ereport(FATAL,
			(errmsg("authentication failed"),
				 errdetail("username and/or password does not match")));

		*random_salt = 0;
	}
	else
	{
		char code[] = "AuthenticationOK";
		pcp_write(frontend, "r", 1);
		wsize = htonl(sizeof(code) + sizeof(int));
		pcp_write(frontend, &wsize, sizeof(int));
		pcp_write(frontend, code, sizeof(code));
		do_pcp_flush(frontend);
		*random_salt = 0;

		ereport(DEBUG1,
			(errmsg("PCP: processing authentication request"),
				 errdetail("authentication OK")));
	}
}
Beispiel #6
0
static void
inform_watchdog_info(PCP_CONNECTION *frontend,char *buf)
{
	int wd_index;
	int wsize;
	char code[] = "CommandComplete";
	char pgpool_port_str[6];
	char wd_port_str[6];
	char status[2];

	WdInfo *wi = NULL;

	if (!pool_config->use_watchdog)
		ereport(ERROR,
				(errmsg("PCP: informing watchdog info failed"),
				 errdetail("watcdhog is not enabled")));

	wd_index = atoi(buf);
	wi = wd_get_watchdog_info(wd_index);

	if (wi == NULL)
		ereport(ERROR,
				(errmsg("PCP: informing watchdog info failed"),
				 errdetail("invalid watchdog index")));

	ereport(DEBUG2,
			(errmsg("PCP: informing watchdog info"),
			 errdetail("retrieved node information from shared memory")));

	snprintf(pgpool_port_str, sizeof(pgpool_port_str), "%d", wi->pgpool_port);
	snprintf(wd_port_str, sizeof(wd_port_str), "%d", wi->wd_port);
	snprintf(status, sizeof(status), "%d", wi->status);

	pcp_write(frontend, "w", 1);
	wsize = htonl(sizeof(code) +
				  strlen(wi->hostname)+1 +
				  strlen(pgpool_port_str)+1 +
				  strlen(wd_port_str)+1 +
				  strlen(status)+1 +
				  sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));

	pcp_write(frontend, wi->hostname, strlen(wi->hostname)+1);
	pcp_write(frontend, pgpool_port_str, strlen(pgpool_port_str)+1);
	pcp_write(frontend, wd_port_str, strlen(wd_port_str)+1);
	pcp_write(frontend, status, strlen(status)+1);
	do_pcp_flush(frontend);
}
Beispiel #7
0
static void
send_md5salt(PCP_CONNECTION *frontend, char* salt)
{
	int wsize;
	ereport(DEBUG1,
			(errmsg("PCP: sending md5 salt to client")));

	pool_random_salt(salt);

	pcp_write(frontend, "m", 1);
	wsize = htonl(sizeof(int) + 4);
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, salt, 4);
	do_pcp_flush(frontend);
}
Beispiel #8
0
static void
inform_watchdog_info(PCP_CONNECTION *frontend,char *buf)
{
	int wd_index;
	int json_data_len;
	int wsize;
	char code[] = "CommandComplete";
	char* json_data;

	if (!pool_config->use_watchdog)
		ereport(ERROR,
			(errmsg("PCP: informing watchdog info failed"),
				 errdetail("watcdhog is not enabled")));

	wd_index = atoi(buf);

	json_data = wd_get_watchdog_nodes(wd_index);
	if (json_data == NULL)
		ereport(ERROR,
			(errmsg("PCP: informing watchdog info failed"),
				 errdetail("invalid watchdog index")));

	ereport(DEBUG2,
		(errmsg("PCP: informing watchdog info"),
			 errdetail("retrieved node information from IPC socket")));

	/*
	 * This is the voilation of PCP protocol but I think
	 * in future we should shift to more adaptable protocol for
	 * data transmition.
	 */
	json_data_len = strlen(json_data);
	wsize = htonl(sizeof(code) +
				  json_data_len+ 1 +
				  sizeof(int));
	pcp_write(frontend, "w", 1);

	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));

	pcp_write(frontend, json_data, json_data_len +1);
	do_pcp_flush(frontend);

	pfree(json_data);
}
Beispiel #9
0
static void
process_promote_node(PCP_CONNECTION *frontend, char *buf, char tos)
{
	int node_id;
	int wsize;
	char code[] = "CommandComplete";
	bool gracefully;

	if (tos == 'J')
		gracefully = false;
	else
		gracefully = true;
	
	node_id = atoi(buf);
	if ( (node_id < 0) || (node_id >= pool_config->backend_desc->num_backends) )
		ereport(ERROR,
				(errmsg("could not process recovery request"),
				 errdetail("node id %d is not valid", node_id)));
	/* promoting node is reserved to Streaming Replication */
	if (!MASTER_SLAVE || (strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP) != 0))
	{
		ereport(FATAL,
			(errmsg("invalid pgpool mode for process recovery request"),
				 errdetail("not in streaming replication mode, can't promote node id %d", node_id)));
		
	}

	if (node_id == PRIMARY_NODE_ID)
	{
		ereport(FATAL,
				(errmsg("invalid pgpool mode for process recovery request"),
				 errdetail("specified node is already primary node, can't promote node id %d", node_id)));
		
	}
	ereport(DEBUG1,
			(errmsg("PCP: processing promote node"),
			 errdetail("promoting Node ID %d", node_id)));
	pool_promote_node(node_id, gracefully);

	pcp_write(frontend, "d", 1);
	wsize = htonl(sizeof(code) + sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	do_pcp_flush(frontend);
}
Beispiel #10
0
static void
inform_process_count(PCP_CONNECTION *frontend)
{
	int wsize;
	int process_count;
	char process_count_str[16];
	int *process_list = NULL;
	char code[] = "CommandComplete";
	char *mesg = NULL;
	int i;
	int total_port_len = 0;

	process_list = pool_get_process_list(&process_count);

	mesg = (char *)palloc(6*process_count);	/* port# is at most 5 characters long (MAX:65535) */

	snprintf(process_count_str, sizeof(process_count_str), "%d", process_count);

	for (i = 0; i < process_count; i++)
	{
		char port[6];
		snprintf(port, sizeof(port), "%d", process_list[i]);
		snprintf(mesg+total_port_len, strlen(port)+1, "%s", port);
		total_port_len += strlen(port)+1;
	}

	pcp_write(frontend, "n", 1);
	wsize = htonl(sizeof(code) +
				  strlen(process_count_str)+1 +
				  total_port_len +
				  sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	pcp_write(frontend, process_count_str, strlen(process_count_str)+1);
	pcp_write(frontend, mesg, total_port_len);
	do_pcp_flush(frontend);

	pfree(process_list);
	pfree(mesg);

	ereport(DEBUG1,
		(errmsg("PCP: informing process count"),
			 errdetail("%d process(es) found", process_count)));
}
Beispiel #11
0
static void
inform_node_info(PCP_CONNECTION *frontend,char *buf)
{
	int node_id;
	int wsize;
	char port_str[6];
	char status[2];
	char weight_str[20];
	char code[] = "CommandComplete";
	BackendInfo *bi = NULL;

	node_id = atoi(buf);

	bi = pool_get_node_info(node_id);

	if (bi == NULL)
		ereport(ERROR,
				(errmsg("informing node info failed"),
				 errdetail("invalid node ID")));
	
	ereport(DEBUG2,
			(errmsg("PCP: informing node info"),
			 errdetail("retrieved node information from shared memory")));
	
	snprintf(port_str, sizeof(port_str), "%d", bi->backend_port);
	snprintf(status, sizeof(status), "%d", bi->backend_status);
	snprintf(weight_str, sizeof(weight_str), "%f", bi->backend_weight);
	
	pcp_write(frontend, "i", 1);
	wsize = htonl(sizeof(code) +
				  strlen(bi->backend_hostname)+1 +
				  strlen(port_str)+1 +
				  strlen(status)+1 +
				  strlen(weight_str)+1 +
				  sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	pcp_write(frontend, bi->backend_hostname, strlen(bi->backend_hostname)+1);
	pcp_write(frontend, port_str, strlen(port_str)+1);
	pcp_write(frontend, status, strlen(status)+1);
	pcp_write(frontend, weight_str, strlen(weight_str)+1);
	do_pcp_flush(frontend);
}
Beispiel #12
0
static void
process_shutown_request(PCP_CONNECTION *frontend, char mode)
{
	char code[] = "CommandComplete";
	pid_t ppid = getppid();
	int sig,len;

	if (mode == 's')
	{
		ereport(DEBUG1,
				(errmsg("PCP: processing shutdown request"),
				 errdetail("sending SIGTERM to the parent process with PID:%d", ppid)));
		sig = SIGTERM;
	}
	else if (mode == 'f')
	{
		ereport(DEBUG1,
				(errmsg("PCP: processing shutdown request"),
				 errdetail("sending SIGINT to the parent process with PID:%d", ppid)));
		sig = SIGINT;
	}
	else if (mode == 'i')
	{
		ereport(DEBUG1,
				(errmsg("PCP: processing shutdown request"),
				 errdetail("sending SIGQUIT to the parent process with PID:%d", ppid)));
		sig = SIGQUIT;
	}
	else
	{
		ereport(ERROR,
				(errmsg("PCP: error while processing shutdown request"),
				 errdetail("invalid shutdown mode \"%c\"", mode)));
	}

	pcp_write(frontend, "t", 1);
	len = htonl(sizeof(code) + sizeof(int));
	pcp_write(frontend, &len, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	do_pcp_flush(frontend);

	pool_signal_parent(sig);
}
Beispiel #13
0
static void
process_attach_node(PCP_CONNECTION *frontend,char *buf)
{
	int node_id;
	int wsize;
	char code[] = "CommandComplete";

	node_id = atoi(buf);
	ereport(DEBUG1,
			(errmsg("PCP: processing attach node"),
			 errdetail("attaching Node ID %d", node_id)));

	send_failback_request(node_id,true);

	pcp_write(frontend, "c", 1);
	wsize = htonl(sizeof(code) + sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	do_pcp_flush(frontend);
}
Beispiel #14
0
static void
inform_node_count(PCP_CONNECTION *frontend)
{
	int wsize;
	char mesg[16];
	char code[] = "CommandComplete";
	int node_count = pool_get_node_count();

	snprintf(mesg, sizeof(mesg), "%d", node_count);

	pcp_write(frontend, "l", 1);
	wsize = htonl(sizeof(code) +
				  strlen(mesg)+1 +
				  sizeof(int));
	pcp_write(frontend, &wsize, sizeof(int));
	pcp_write(frontend, code, sizeof(code));
	pcp_write(frontend, mesg, strlen(mesg)+1);
	do_pcp_flush(frontend);

	ereport(DEBUG1,
			(errmsg("PCP: informing node count"),
			 errdetail("%d node(s) found", node_count)));
}
Beispiel #15
0
static void
inform_process_info(PCP_CONNECTION *frontend,char *buf)
{
	int proc_id;
	int wsize;
	int num_proc = pool_config->num_init_children;
	int i;

	proc_id = atoi(buf);

	if ((proc_id != 0) && (pool_get_process_info(proc_id) == NULL))
	{
		ereport(ERROR,
			(errmsg("informing process info failed"),
				 errdetail("invalid process ID : %s",buf)));
	}
	else
	{
		/* First, send array size of connection_info */
		char arr_code[] = "ArraySize";
		char con_info_size[16];
		/* Finally, indicate that all data is sent */
		char fin_code[] = "CommandComplete";

		POOL_REPORT_POOLS *pools = get_pools(&num_proc);

		if (proc_id == 0)
		{
			snprintf(con_info_size, sizeof(con_info_size), "%d", num_proc);
		}
		else
		{
			snprintf(con_info_size, sizeof(con_info_size), "%d", pool_config->max_pool * NUM_BACKENDS);
		}

		pcp_write(frontend, "p", 1);
		wsize = htonl(sizeof(arr_code) +
					  strlen(con_info_size)+1 +
					  sizeof(int));
		pcp_write(frontend, &wsize, sizeof(int));
		pcp_write(frontend, arr_code, sizeof(arr_code));
		pcp_write(frontend, con_info_size, strlen(con_info_size)+1);
		do_pcp_flush(frontend);

		/* Second, send process information for all connection_info */
		for (i=0; i<num_proc; i++)
		{
			char code[] = "ProcessInfo";
			char proc_pid[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];

			if (proc_id != 0 && proc_id != pools[i].pool_pid) continue;

			snprintf(proc_pid, sizeof(proc_pid), "%d", pools[i].pool_pid);
			snprintf(proc_start_time, sizeof(proc_start_time), "%ld", pools[i].start_time);
			snprintf(proc_create_time, sizeof(proc_create_time), "%ld", pools[i].create_time);
			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);

			pcp_write(frontend, "p", 1);
			wsize = htonl(	sizeof(code) +
						  strlen(proc_pid)+1 +
						  strlen(pools[i].database)+1 +
						  strlen(pools[i].username)+1 +
						  strlen(proc_start_time)+1 +
						  strlen(proc_create_time)+1 +
						  strlen(majorversion)+1 +
						  strlen(minorversion)+1 +
						  strlen(pool_counter)+1 +
						  strlen(backend_id)+1 +
						  strlen(backend_pid)+1 +
						  strlen(connected)+1 +
						  sizeof(int));
			pcp_write(frontend, &wsize, sizeof(int));
			pcp_write(frontend, code, sizeof(code));
			pcp_write(frontend, proc_pid, strlen(proc_pid)+1);
			pcp_write(frontend, pools[i].database, strlen(pools[i].database)+1);
			pcp_write(frontend, pools[i].username, strlen(pools[i].username)+1);
			pcp_write(frontend, proc_start_time, strlen(proc_start_time)+1);
			pcp_write(frontend, proc_create_time, strlen(proc_create_time)+1);
			pcp_write(frontend, majorversion, strlen(majorversion)+1);
			pcp_write(frontend, minorversion, strlen(minorversion)+1);
			pcp_write(frontend, pool_counter, strlen(pool_counter)+1);
			pcp_write(frontend, backend_id, strlen(backend_id)+1);
			pcp_write(frontend, backend_pid, strlen(backend_pid)+1);
			pcp_write(frontend, connected, strlen(connected)+1);
			do_pcp_flush(frontend);
		}

		pcp_write(frontend, "p", 1);
		wsize = htonl(sizeof(fin_code) +
					  sizeof(int));
		pcp_write(frontend, &wsize, sizeof(int));
		pcp_write(frontend, fin_code, sizeof(fin_code));
		do_pcp_flush(frontend);
		ereport(DEBUG1,
				(errmsg("PCP informing process info"),
				 errdetail("retrieved process information from shared memory")));
		
		pfree(pools);
	}
}