From 53e4b851883571c92073c87986759bd98dab9c7e Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 18 Aug 2004 22:47:38 +0000 Subject: Thread safety and locking checks. --- daemon/pgsql.c | 89 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 31 deletions(-) (limited to 'daemon/pgsql.c') diff --git a/daemon/pgsql.c b/daemon/pgsql.c index 6bdb158..56eebd1 100644 --- a/daemon/pgsql.c +++ b/daemon/pgsql.c @@ -25,7 +25,7 @@ typedef struct pgsql_context /* Base Handler ------------------------------------------------------ */ bd_context_t bd; - /* Settings ---------------------------------------------------------- */ + /* Read Only --------------------------------------------------------- */ const char* host; /* The connection host or path */ const char* port; /* The connection port */ const char* user; /* The pgsql user name */ @@ -39,7 +39,7 @@ typedef struct pgsql_context int pgsql_max; /* Number of open connections allowed */ int pgsql_timeout; /* Maximum amount of time to dedicate to a query */ - /* Context ----------------------------------------------------------- */ + /* Require Locking --------------------------------------------------- */ PGconn** pool; /* Pool of available connections */ int pool_mark; /* Amount of connections allocated */ } @@ -282,29 +282,42 @@ static const char* make_pgsql_connstring(const ha_request_t* rq, pgsql_context_t static PGconn* get_pgsql_connection(const ha_request_t* rq, pgsql_context_t* ctx) { - PGconn* pg; + PGconn* pg = NULL; const char* connstring; - int i; + int i, create = 1; ASSERT(ctx); - for(i = 0; i < ctx->pgsql_max; i++) - { - /* An open connection in the pool */ - if(ctx->pool[i]) + /* + * Note that below there maybe a race condition between the two locks + * but this will only allow a few extra connections to open at best + * and as such really isn't a big issue. + */ + + ha_lock(NULL); + + for(i = 0; i < ctx->pgsql_max; i++) { - ha_messagex(rq, LOG_DEBUG, "using cached pgsql connection"); - pg = ctx->pool[i]; - ctx->pool[i] = NULL; - return pg; + /* An open connection in the pool */ + if(ctx->pool[i]) + { + ha_messagex(rq, LOG_DEBUG, "using cached pgsql connection"); + pg = ctx->pool[i]; + ctx->pool[i] = NULL; + break; + } } - } - if(ctx->pool_mark >= ctx->pgsql_max) - { - ha_messagex(rq, LOG_ERR, "too many open pgsql connections"); - return NULL; - } + if(pg == NULL && ctx->pool_mark >= ctx->pgsql_max) + { + ha_messagex(rq, LOG_ERR, "too many open pgsql connections"); + create = 0; + } + + ha_unlock(NULL); + + if(pg != NULL || create == 0) + return pg; connstring = make_pgsql_connstring(rq, ctx); if(!connstring) @@ -326,16 +339,26 @@ static PGconn* get_pgsql_connection(const ha_request_t* rq, pgsql_context_t* ctx return NULL; } - ctx->pool_mark++; - ha_messagex(rq, LOG_DEBUG, "opened new pgsql connection (total %d)", ctx->pool_mark); + ha_lock(NULL); + + ctx->pool_mark++; + ha_messagex(rq, LOG_DEBUG, "opened new pgsql connection (total %d)", ctx->pool_mark); + + ha_unlock(NULL); + return pg; } static void discard_pgsql_connection(const ha_request_t* rq, pgsql_context_t* ctx, PGconn* pg) { PQfinish(pg); - ctx->pool_mark--; - ha_messagex(rq, LOG_DEBUG, "discarding pgsql connection (total %d)", ctx->pool_mark); + + ha_lock(NULL); + + ctx->pool_mark--; + ha_messagex(rq, LOG_DEBUG, "discarding pgsql connection (total %d)", ctx->pool_mark); + + ha_unlock(NULL); } static void save_pgsql_connection(const ha_request_t* rq, pgsql_context_t* ctx, PGconn* pg) @@ -350,17 +373,21 @@ static void save_pgsql_connection(const ha_request_t* rq, pgsql_context_t* ctx, /* Make sure it's worth saving */ if(PQstatus(pg) != CONNECTION_BAD) { - for(i = 0; i < ctx->pgsql_max; i++) - { - /* An open connection in the pool */ - if(!ctx->pool[i]) + ha_lock(NULL); + + for(i = 0; i < ctx->pgsql_max; i++) { - ha_messagex(rq, LOG_DEBUG, "caching pgsql connection for later use"); - ctx->pool[i] = pg; - pg = NULL; - break; + /* An open connection in the pool */ + if(!ctx->pool[i]) + { + ha_messagex(rq, LOG_DEBUG, "caching pgsql connection for later use"); + ctx->pool[i] = pg; + pg = NULL; + break; + } } - } + + ha_unlock(NULL); } if(pg != NULL) -- cgit v1.2.3