#include "resource.h"
static ResourceType pg_resource_type = {
(resource_pool_init_func)pg_resourcepool_init,
(resource_pool_destroy_func)pg_resourcepool_destroy,
(resource_pool_createresource_func)pg_resourcepool_createresource,
(resource_pool_freeresource_func)pg_resourcepool_freeresource,
(resource_pool_prepare_func)pg_resourcepool_prepare,
(resource_pool_finish_func)pg_resourcepool_finish,
(resource_pool_getresourcedata_func)pg_resourcepool_getresourcedata
};
ResourceType* pg_get_resource_type(
void) {
return &pg_resource_type;
}
void * pg_resourcepool_init(
pool_handle_t *pool,
const char *rpname, pblock *pb) {
char *connection = pblock_findval(
"Connection", pb);
if(!connection) {
log_ereport(
LOG_MISCONFIG,
"Resource pool %s: Missing Connection parameter", rpname);
return NULL;
}
PGconn *test_connection = PQconnectdb(connection);
pg_check_connection(
LOG_WARN, rpname, test_connection);
if(test_connection) PQfinish(test_connection);
PgResourcePool *pg = pool_malloc(pool,
sizeof(PgResourcePool));
if(!pg) {
return NULL;
}
pg->pool = pool;
pg->name = rpname;
pg->connection = connection;
return pg;
}
int pg_check_connection(
int loglevel,
const char *rpname, PGconn *connection) {
if(!connection) {
log_ereport(loglevel,
"Resource pool %s: Cannot create PQ connection", rpname);
return 1;
}
if(PQstatus(connection) !=
CONNECTION_OK) {
char *err = PQerrorMessage(connection);
int errlen =
0;
if(err) {
errlen = strlen(err);
if(errlen >
0 && err[errlen-
1] ==
'\n') {
errlen--;
}
}
log_ereport(loglevel,
"Resource pool %s: Failed to connect to database: %.*s", rpname, errlen, err);
return 1;
}
return 0;
}
void pg_resourcepool_destroy(PgResourcePool *pg) {
}
void * pg_resourcepool_createresource(PgResourcePool *pg) {
PGconn *connection = PQconnectdb(pg->connection);
if(pg_check_connection(
LOG_FAILURE, pg->name, connection)) {
return NULL;
}
PgResource *res = pool_malloc(pg->pool,
sizeof(PgResource));
if(!res) {
PQfinish(connection);
log_ereport(
LOG_CATASTROPHE,
"pg_resourcepool_createresource: OOM");
return NULL;
}
res->connection = connection;
return res;
}
void pg_resourcepool_freeresource(PgResourcePool *pg, PgResource *res) {
if(res->connection) {
PQfinish(res->connection);
}
pool_free(pg->pool, res);
}
int pg_resourcepool_prepare(PgResourcePool *pg, PgResource *res) {
PGresult *result = PQexec(res->connection,
"BEGIN");
PQclear(result);
return 0;
}
int pg_resourcepool_finish(PgResourcePool *pg, PgResource *res) {
PGresult *result = PQexec(res->connection,
"COMMIT");
if(PQresultStatus(result) !=
PGRES_COMMAND_OK) {
log_ereport(
LOG_FAILURE,
"pg_dav_proppatch_finish: COMMIT failed failed: %s", PQerrorMessage(res->connection));
}
PQclear(result);
return 0;
}
void * pg_resourcepool_getresourcedata(PgResource *res) {
return res->connection;
}