コード例 #1
0
ファイル: child.c プロジェクト: codeforall/pgpool2_newtree
/*
 * Do house keeping works when pgpool child process exits
 */
void child_exit(int code)
{
	if (getpid() == mypid)
	{
		pool_log("child_exit: called from pgpool main. ignored.");
		return;
	}

	/* count down global connection counter */
	if (accepted)
		connection_count_down();

	/* prepare to shutdown connections to system db */
	if(pool_config->parallel_mode || pool_config->enable_query_cache)
	{
		if (system_db_info->pgconn)
			pool_close_libpq_connection();
		if (pool_system_db_connection())
			pool_close(pool_system_db_connection()->con);
	}

	if (pool_config->memory_cache_enabled && !pool_is_shmem_cache())
	{
		memcached_disconnect();
	}

	/* let backend know now we are exiting */
	if (pool_connection_pool)
		send_frontend_exits();

	exit(code);
}
コード例 #2
0
ファイル: pool_query_cache.c プロジェクト: mfyang/pgpool-II
/* --------------------------------
 * pool_query_cache_table_exists - checks if query_cache table exists in the SystemDB
 *
 * This function is called once and only once from the pgpool parent process.
 * return 1 if query_cache table exists, 0 otherwise.
 * --------------------------------
 */
int
pool_query_cache_table_exists(void)
{
	PGresult *pg_result = NULL;
	char *sql = NULL;
	int sql_len = strlen(pool_config->system_db_schema) + strlen(QUERY_CACHE_TABLE_NAME) + 64;

	if (! system_db_connection_exists())
		return 0;

	sql = (char *)malloc(sql_len);
	if (malloc_failed(sql))
		return 0;

	snprintf(sql, sql_len,
			 "SELECT hash, query, value, dbname, create_time FROM %s.%s LIMIT 1",
			 pool_config->system_db_schema,
			 QUERY_CACHE_TABLE_NAME);

	pg_result = PQexec(system_db_info->pgconn, sql);
	if (!pg_result || PQresultStatus(pg_result) != PGRES_TUPLES_OK)
	{
		pool_error("pool_query_cache_table_exists: PQexec() failed. reason: %s",
				   PQerrorMessage(system_db_info->pgconn));

		PQclear(pg_result);
		free(sql);
		return 0;
	}

	PQclear(pg_result);
	pool_close_libpq_connection();
	free(sql);

	return 1;
}
コード例 #3
0
void pool_backend_timer(void)
{
#define TMINTMAX 0x7fffffff

	POOL_CONNECTION_POOL *p = pool_connection_pool;
	int i, j;
	time_t now;
	time_t nearest = TMINTMAX;
	ConnectionInfo *info;

	POOL_SETMASK(&BlockSig);

	now = time(NULL);

	pool_debug("pool_backend_timer_handler called at %ld", now);

	for (i=0;i<pool_config->max_pool;i++, p++)
	{
		if (!MASTER_CONNECTION(p))
			continue;
		if (!MASTER_CONNECTION(p)->sp)
			continue;
		if (MASTER_CONNECTION(p)->sp->user == NULL)
			continue;

		/* timer expire? */
		if (MASTER_CONNECTION(p)->closetime)
		{
			int freed = 0;

			pool_debug("pool_backend_timer_handler: expire time: %ld",
					   MASTER_CONNECTION(p)->closetime+pool_config->connection_life_time);

			if (now >= (MASTER_CONNECTION(p)->closetime+pool_config->connection_life_time))
			{
				/* discard expired connection */
				pool_debug("pool_backend_timer_handler: expires user %s database %s",
						   MASTER_CONNECTION(p)->sp->user, MASTER_CONNECTION(p)->sp->database);

				pool_send_frontend_exits(p);

				for (j=0;j<NUM_BACKENDS;j++)
				{
					if (!VALID_BACKEND(j))
						continue;

					if (!freed)
					{
						pool_free_startup_packet(CONNECTION_SLOT(p, j)->sp);
						freed = 1;
					}

					pool_close(CONNECTION(p, j));
					free(CONNECTION_SLOT(p, j));
				}
				info = p->info;
				memset(p, 0, sizeof(POOL_CONNECTION_POOL));
				p->info = info;
				memset(p->info, 0, sizeof(ConnectionInfo) * MAX_NUM_BACKENDS);

				/* prepare to shutdown connections to system db */
				if(pool_config->system_db_dynamic_connection && (pool_config->parallel_mode || pool_config->enable_query_cache))
				{
					if (system_db_info->pgconn)
						pool_close_libpq_connection();
					if (pool_system_db_connection() && pool_system_db_connection()->con)
					{
						pool_send_frontend_exit(pool_system_db_connection()->con);
						pool_close(pool_system_db_connection()->con);
					}

					if( system_db_info->connection )
					{
						free( system_db_info->connection );
						memset(system_db_info->connection, 0, sizeof(POOL_CONNECTION_POOL_SLOT));
						system_db_info->connection = NULL;
					}
				}
			}
			else
			{
				/* look for nearest timer */
				if (MASTER_CONNECTION(p)->closetime < nearest)
					nearest = MASTER_CONNECTION(p)->closetime;
			}
		}
	}

	/* any remaining timer */
	if (nearest != TMINTMAX)
	{
		nearest = pool_config->connection_life_time - (now - nearest);
		if (nearest <= 0)
		  nearest = 1;
		pool_signal(SIGALRM, pool_backend_timer_handler);
		alarm(nearest);
	}

	POOL_SETMASK(&UnBlockSig);
}
コード例 #4
0
ファイル: pool_system.c プロジェクト: CHINA-JD/prestogres
/*
 * pool_memset_system_db_info:
 *    Initializes distribution rules. Distribution rules are stored in
 *    System DB. So we have to execute query, and expand results on
 *    memory.
 */
int pool_memset_system_db_info (SystemDBInfo *info)
{
    int i;
    static char sql[1024],sql2[1024];
    PGresult *result;
    DistDefInfo *dist_info = NULL;
    RepliDefInfo *repli_info = NULL;

    if (!system_db_info->pgconn ||
            (PQstatus(system_db_info->pgconn) != CONNECTION_OK))
    {
        if (system_db_connect())
            return -1;
    }

    /* get distribution rules */
    snprintf(sql,
             sizeof(sql),
             "SELECT dbname, schema_name, table_name,col_name,array_upper(col_list,1),col_list,type_list, dist_def_func FROM %s.dist_def",
             pool_config->system_db_schema);

    result = PQexec(system_db_info->pgconn, sql);
    if (!result || PQresultStatus(result) != PGRES_TUPLES_OK)
    {
        ereport(WARNING,
                (errmsg("error while initializing distribution rules, PQexec failed: \"%s\"", PQerrorMessage(system_db_info->pgconn))));
        return -1;
    }
    else
    {
        info->dist_def_num = PQntuples(result);
        if (PQntuples(result) > 0)
        {
            dist_info = palloc(sizeof(DistDefInfo) * info->dist_def_num);
        }


        info->dist_def_slot = dist_info;

        for (i = 0; i < PQntuples(result); ++i)
        {
            char *t_dbname;
            char *t_schema_name;
            char *t_table_name;
            char *t_dist_key_col_name;
            char *t_dist_def_func;
            int num;
            int len;

            num = atol(PQgetvalue(result, i ,4));
            t_dbname = palloc(strlen(PQgetvalue(result,i,0)) + 1);
            strcpy(t_dbname, PQgetvalue(result,i,0));
            dist_info[i].dbname = t_dbname;

            t_schema_name = palloc(strlen(PQgetvalue(result,i,1)) + 1);
            strcpy(t_schema_name, PQgetvalue(result,i,1));
            dist_info[i].schema_name = t_schema_name;

            t_table_name = palloc(strlen(PQgetvalue(result,i,2)) + 1);
            strcpy(t_table_name, PQgetvalue(result,i,2));
            dist_info[i].table_name = t_table_name;

            t_dist_key_col_name = palloc(strlen(PQgetvalue(result,i,3)) + 1);
            strcpy(t_dist_key_col_name, PQgetvalue(result,i,3));
            dist_info[i].dist_key_col_name = t_dist_key_col_name;

            t_dist_def_func = palloc(strlen(PQgetvalue(result,i,7)) + 1);
            strcpy(t_dist_def_func, PQgetvalue(result,i,7));
            dist_info[i].dist_def_func = t_dist_def_func;

            dist_info[i].col_num = num;

            dist_info[i].col_list = palloc0(num * sizeof(char *));
            dist_info[i].type_list = palloc0(num * sizeof(char *));

            if (get_col_list(&dist_info[i]) < 0)
            {
                ereport(WARNING,
                        (errmsg("error while initializing distribution rules, failed to get column list")));

                PQclear(result);
                pool_close_libpq_connection();
                return -1;
            }

            /* create PREPARE statement */
            len = strlen(t_dbname) + strlen(t_schema_name) +
                  strlen(t_table_name) + strlen("pgpool_");

            dist_info[i].prepare_name = palloc(len + 1);

            snprintf(dist_info[i].prepare_name, len+1, "pgpool_%s%s%s",
                     t_dbname, t_schema_name, t_table_name);
            dist_info[i].prepare_name[len] = '\0';
        }
    }

    PQclear(result);

    /* get replication rules */
    snprintf(sql2,
             sizeof(sql2),
             "SELECT dbname, schema_name, table_name, array_upper(col_list,1),col_list,type_list FROM %s.replicate_def",
             pool_config->system_db_schema);

    result = PQexec(system_db_info->pgconn, sql2);

    if (!result)
    {
        ereport(WARNING,
                (errmsg("error while initializing distribution rules, PQexec failed: \"%s\"", PQerrorMessage(system_db_info->pgconn))));
        return -1;
    }
    else if (PQresultStatus(result) != PGRES_TUPLES_OK)
    {
        info->repli_def_num = 0;
        info->repli_def_slot = NULL;
    }
    else
    {
        info->repli_def_num = PQntuples(result);
        if (PQntuples(result) > 0)
        {
            repli_info = palloc(sizeof(RepliDefInfo) * info->repli_def_num);
        }

        info->repli_def_slot = repli_info;

        for (i = 0; i < PQntuples(result); ++i)
        {
            char *t_dbname;
            char *t_schema_name;
            char *t_table_name;
            int num;
            int len;

            num = atol(PQgetvalue(result, i ,3));
            t_dbname = palloc(strlen(PQgetvalue(result,i,0)) + 1);
            strcpy(t_dbname, PQgetvalue(result,i,0));
            repli_info[i].dbname = t_dbname;

            t_schema_name = palloc(strlen(PQgetvalue(result,i,1)) + 1);
            strcpy(t_schema_name, PQgetvalue(result,i,1));
            repli_info[i].schema_name = t_schema_name;

            t_table_name = palloc(strlen(PQgetvalue(result,i,2)) + 1);
            strcpy(t_table_name, PQgetvalue(result,i,2));
            repli_info[i].table_name = t_table_name;

            repli_info[i].col_num = num;

            repli_info[i].col_list = palloc0(num * sizeof(char *));
            repli_info[i].type_list = palloc0(num * sizeof(char *));

            if (get_col_list2(&repli_info[i]) < 0)
            {
                ereport(WARNING,
                        (errmsg("error while initializing distribution rules, failed to get column list")));
                PQclear(result);
                pool_close_libpq_connection();
                return -1;
            }

            /* create PREPARE statement */
            len = strlen(t_dbname) + strlen(t_schema_name) +
                  strlen(t_table_name) + strlen("pgpool_");

            repli_info[i].prepare_name = palloc(len + 1);
            snprintf(repli_info[i].prepare_name, len+1, "pgpool_%s%s%s",
                     t_dbname, t_schema_name, t_table_name);
            repli_info[i].prepare_name[len] = '\0';
        }
    }

    PQclear(result);

    pool_close_libpq_connection();
    return i;
}
コード例 #5
0
ファイル: pool_query_cache.c プロジェクト: mfyang/pgpool-II
/* --------------------------------
 * pool_query_cache_register() - register query cache to the SystemDB
 *
 * returns 0 on sucess, -1 otherwise
 * --------------------------------
 */
int
pool_query_cache_register(char kind,
						  POOL_CONNECTION *frontend,
						  char *database,
						  char *data,
						  int data_len,
						  char *query)
{
	int ret;
	int send_len;

	if (! system_db_connection_exists())
		return -1;
	if (! CACHE_TABLE_INFO.has_prepared_statement)
		define_prepared_statements();

	switch (kind)
	{
		case 'T':				/* RowDescription */
		{
			/* for all SELECT result data from the backend, 'T' must come first */
			if (query_cache_info != NULL)
			{
				pool_error("pool_query_cache_register: received RowDescription in the wrong order");
				free_query_cache_info();
				return -1;
			}

			pool_debug("pool_query_cache_register: saving cache for query: \"%s\"", query);

			/* initialize query_cache_info and save the query */
			ret = init_query_cache_info(frontend, database, query);
			if (ret)
				return ret;

			/* store data into the cache */
			write_cache(&kind, 1);
			send_len = htonl(data_len + sizeof(int));
			write_cache(&send_len, sizeof(int));
			write_cache(data, data_len);

			break;
		}

		case 'D':				/* DataRow */
		{
			/* for all SELECT result data from the backend, 'T' must come first */
			if (query_cache_info == NULL)
			{
				pool_error("pool_query_cache_register: received DataRow in the wrong order");
				return -1;
			}

			write_cache(&kind, 1);
			send_len = htonl(data_len + sizeof(int));
			write_cache(&send_len, sizeof(int));
			write_cache(data, data_len);

			break;
		}

		case 'C':				/* CommandComplete */
		{
			PGresult *pg_result = NULL;
			char *escaped_query = NULL;
			size_t escaped_query_len;
			time_t now = time(NULL);
			char *values[5];
			int values_len[5];
			int values_format[5];
			int i;

			/* for all SELECT result data from the backend, 'T' must come first */
			if (query_cache_info == NULL)
			{
				pool_error("pool_query_cache_register: received CommandComplete in the wrong order");
				return -1;
			}

			/* pack CommandComplete data into the cache */
			write_cache(&kind, 1);
			send_len = htonl(data_len + sizeof(int));
			write_cache(&send_len, sizeof(int));
			write_cache(data, data_len);

			query_cache_info->create_time = pq_time_to_str(now);
			if (malloc_failed(query_cache_info->create_time))
			{
				free_query_cache_info();
				return -1;
			}

			escaped_query = (char *)malloc(strlen(query_cache_info->query) * 2 + 1);
			if (malloc_failed(escaped_query))
			{
				free_query_cache_info();
				return -1;
			}

/* 			escaped_query_len = PQescapeStringConn(system_db_info->pgconn, */
/* 												   escaped_query, */
/* 												   query_cache_info->query, */
/* 												   strlen(query_cache_info->query))); */
			escaped_query_len = PQescapeString(escaped_query, query_cache_info->query, strlen(query_cache_info->query));

			/* all the result data have been received. store into the SystemDB */
			values[0] = strdup(query_cache_info->md5_query);
			values[1] = strdup(escaped_query);
			values[2] = (char *)malloc(query_cache_info->cache_offset);
			memcpy(values[2], query_cache_info->cache, query_cache_info->cache_offset);
			values[3] = strdup(query_cache_info->db_name);
			values[4] = strdup(query_cache_info->create_time);
			for (i = 0; i < 5; i++)
			{
				if (malloc_failed(values[i]))
				{
					pool_error("pool_query_cache_register: malloc() failed");
					free_query_cache_info();
					{
						int j;
						for (j = 0; j < i; j++)
							free(values[j]);
					}
					return -1;
				}

				values_len[i] = strlen(values[i]);
			}
			values_format[0] = values_format[1] = values_format[3] = values_format[4] = 0;
			values_format[2] = 1;
			values_len[2] = query_cache_info->cache_offset;

			pg_result = PQexecPrepared(system_db_info->pgconn,
									   CACHE_TABLE_INFO.register_prepared_statement,
									   5,
									   (const char * const *)values,
									   values_len,
									   values_format,
									   0);
			if (!pg_result || PQresultStatus(pg_result) != PGRES_COMMAND_OK)
			{
				pool_error("pool_query_cache_register: PQexecPrepared() failed. reason: %s",
						   PQerrorMessage(system_db_info->pgconn));

				PQclear(pg_result);
				PQfreemem(escaped_query);
				free_query_cache_info();
				for (i = 0; i < 5; i++)
					free(values[i]);
				return -1;
			}

			PQclear(pg_result);
			PQfreemem(escaped_query);
			for (i = 0; i < 5; i++)
				free(values[i]);
			free_query_cache_info();

			break;
		}

		case 'E':
		{
			pool_debug("pool_query_cache_register: received 'E': free query cache buffer");

			pool_close_libpq_connection();
			free_query_cache_info();

			break;
		}
	}

	return 0;
}
コード例 #6
0
ファイル: pool_query_cache.c プロジェクト: mfyang/pgpool-II
/* --------------------------------
 * pool_query_cache_lookup - retrieve query cache from the SystemDB
 *
 * creates a SQL query string for searching a cache from the SystemDB.
 *
 * returns POOL_CONTINUE if cache is found. returns POOL_END if cache was
 * not found. returns POOL_ERROR if an error has been encountered while
 * searching.
 *
 * Note that POOL_END and POOL_ERROR are treated the same by the caller
 * (pool_process_query.c).
 * POOL_END and POOL_ERROR both indicates to the caller that the search
 * query must be forwarded to the backends in order to retrieve data and
 * the result be cached.
 * Only difference is that POOL_ERROR indicates that some fatal error has
 * occured; query cache function, however, should be seemless to the user
 * whether cache was not found or error has occured during cache retrieve.
 * --------------------------------
 */
POOL_STATUS
pool_query_cache_lookup(POOL_CONNECTION *frontend, char *query, char *database, char tstate)
{
	char *sql = NULL;
	int sql_len;
	char md5_query[33];
	struct timeval timeout;
	int status;

	if (! system_db_connection_exists())
		return POOL_ERROR;		/* same as POOL_END ... at least for now */

	sql_len =
		strlen(pool_config->system_db_schema) +
		strlen(QUERY_CACHE_TABLE_NAME) +
		sizeof(md5_query) +
		strlen(database) +
		64;
	sql = (char *)malloc(sql_len);
	if (malloc_failed(sql))
		return POOL_ERROR;		/* should I exit here rather than returning an error? */

	/* cached data lookup */
	pool_md5_hash(query, strlen(query), md5_query);
	snprintf(sql, sql_len, "SELECT value FROM %s.%s WHERE hash = '%s' AND dbname = '%s'",
			 pool_config->system_db_schema,
			 QUERY_CACHE_TABLE_NAME,
			 md5_query,
			 database);

	/* set timeout value for select */
	timeout.tv_sec = pool_config->child_life_time;
	timeout.tv_usec = 0;

	pool_debug("pool_query_cache_lookup: searching cache for query: \"%s\"", query);
	status = search_system_db_for_cache(frontend, sql, strlen(sql)+1, &timeout, tstate);

	/* make sure that the remaining data is discarded */
	SYSDB_CON->po = 0;
	SYSDB_CON->len = 0;

	free(sql);

	/* cache found, and no backend communication needed */
	if (status == CACHE_FOUND)
	{
		return POOL_CONTINUE;
	}

	/* cache not found */

	if (status == CACHE_ERROR)
	{
		pool_error("pool_query_cache_lookup: query cache lookup failed");
		/* reset the SystemDB connection */
		if (system_db_info->pgconn)
			pool_close_libpq_connection();
		return POOL_ERROR;		/* same as POOL_END ... at least for now */
	}

	pool_debug("pool_query_cache_lookup: query cache not found");
	return POOL_END;
}