summaryrefslogtreecommitdiff
path: root/daemon/mysql.c
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2004-08-18 22:47:38 +0000
committerStef Walter <stef@memberwebs.com>2004-08-18 22:47:38 +0000
commit53e4b851883571c92073c87986759bd98dab9c7e (patch)
tree436748a52788e2f0434ec9beef8768f881dbcd07 /daemon/mysql.c
parent59099b09a63f200147fc506e75f3052469d69fe9 (diff)
Thread safety and locking checks.
Diffstat (limited to 'daemon/mysql.c')
-rw-r--r--daemon/mysql.c127
1 files changed, 89 insertions, 38 deletions
diff --git a/daemon/mysql.c b/daemon/mysql.c
index 0ed8f35..1a75374 100644
--- a/daemon/mysql.c
+++ b/daemon/mysql.c
@@ -26,7 +26,7 @@ typedef struct mysql_context
/* Base Handler ------------------------------------------------------ */
bd_context_t bd;
- /* Settings ---------------------------------------------------------- */
+ /* Readonly Settings ------------------------------------------------- */
const char* host; /* The connection host or path */
unsigned int port; /* The connection port */
const char* user; /* The pgsql user name */
@@ -41,7 +41,7 @@ typedef struct mysql_context
int mysql_timeout; /* Maximum amount of time to dedicate to a query */
int use_unix_socket;
- /* Context ----------------------------------------------------------- */
+ /* Require Locking --------------------------------------------------- */
MYSQL** pool; /* Pool of available connections */
int pool_mark; /* Amount of connections allocated */
}
@@ -73,6 +73,11 @@ static const mysql_context_t mysql_defaults =
0 /* pool_mark */
};
+/* mysql_real_connect is not always thread-safe :( */
+static pthread_mutex_t g_mysql_mutex;
+static pthread_mutexattr_t g_mysql_mutexattr;
+
+
/* -------------------------------------------------------------------------------
* Internal Functions
@@ -235,27 +240,40 @@ static MYSQL* get_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx)
{
MYSQL* my;
MYSQL* r;
- int i;
+ int i, create = 1;
ASSERT(ctx);
- for(i = 0; i < ctx->mysql_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(&g_mysql_mutex);
+
+ for(i = 0; i < ctx->mysql_max; i++)
{
- ha_messagex(rq, LOG_DEBUG, "using cached mysql connection");
- my = ctx->pool[i];
- ctx->pool[i] = NULL;
- return my;
+ /* An open connection in the pool */
+ if(ctx->pool[i])
+ {
+ ha_messagex(rq, LOG_DEBUG, "using cached mysql connection");
+ my = ctx->pool[i];
+ ctx->pool[i] = NULL;
+ }
}
- }
- if(ctx->pool_mark >= ctx->mysql_max)
- {
- ha_messagex(rq, LOG_ERR, "too many open mysql connections");
- return NULL;
- }
+
+ if(my == NULL && ctx->pool_mark >= ctx->mysql_max)
+ {
+ ha_messagex(rq, LOG_ERR, "too many open mysql connections");
+ create = 0;
+ }
+
+ ha_unlock(&g_mysql_mutex);
+
+ if(my != NULL || create == 0)
+ return my;
my = mysql_init(NULL);
if(!my)
@@ -269,29 +287,39 @@ static MYSQL* get_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx)
mysql_options(my, MYSQL_OPT_WRITE_TIMEOUT, (char*)&(ctx->mysql_timeout)); */
/* Apparently mysql_real_connect is not thread safe :( */
- ha_lock(NULL);
+ ha_lock(&g_mysql_mutex);
+
r = mysql_real_connect(my, ctx->use_unix_socket ? NULL : ctx->host,
ctx->user, ctx->password, ctx->database, ctx->port,
ctx->use_unix_socket ? ctx->host : NULL, 0);
- ha_unlock(NULL);
- if(!r)
- {
- ha_messagex(rq, LOG_ERR, "error opening mysql connection: %s", mysql_error(my));
- mysql_close(my);
- return NULL;
- }
+ if(!r)
+ {
+ ha_messagex(rq, LOG_ERR, "error opening mysql connection: %s", mysql_error(my));
+ mysql_close(my);
+ my = NULL;
+ }
+ else
+ {
+ ctx->pool_mark++;
+ ha_messagex(rq, LOG_DEBUG, "opened new mysql connection (total %d)", ctx->pool_mark);
+ }
+
+ ha_unlock(&g_mysql_mutex);
- ctx->pool_mark++;
- ha_messagex(rq, LOG_DEBUG, "opened new mysql connection (total %d)", ctx->pool_mark);
return my;
}
static void discard_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx, MYSQL* my)
{
mysql_close(my);
- ctx->pool_mark--;
- ha_messagex(rq, LOG_DEBUG, "discarding mysql connection (total %d)", ctx->pool_mark);
+
+ ha_lock(&g_mysql_mutex);
+
+ ctx->pool_mark--;
+ ha_messagex(rq, LOG_DEBUG, "discarding mysql connection (total %d)", ctx->pool_mark);
+
+ ha_unlock(&g_mysql_mutex);
}
static void save_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx, MYSQL* my)
@@ -322,17 +350,21 @@ static void save_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx,
/* Make sure it's worth saving */
default:
- for(i = 0; i < ctx->mysql_max; i++)
- {
- /* An open connection in the pool */
- if(!ctx->pool[i])
+ ha_lock(&g_mysql_mutex);
+
+ for(i = 0; i < ctx->mysql_max; i++)
{
- ha_messagex(rq, LOG_DEBUG, "caching mysql connection for later use");
- ctx->pool[i] = my;
- my = NULL;
- break;
+ /* An open connection in the pool */
+ if(!ctx->pool[i])
+ {
+ ha_messagex(rq, LOG_DEBUG, "caching mysql connection for later use");
+ ctx->pool[i] = my;
+ my = NULL;
+ break;
+ }
}
- }
+
+ ha_unlock(&g_mysql_mutex);
break;
};
@@ -701,6 +733,19 @@ int mysql_initialize(ha_context_t* context)
ha_messagex(NULL, LOG_INFO, "initialized mysql handler");
}
+ /* Global Initialization */
+ else
+ {
+ /* Create the smblib mutex */
+ if(pthread_mutexattr_init(&g_mysql_mutexattr) != 0 ||
+ pthread_mutexattr_settype(&g_mysql_mutexattr, HA_MUTEX_TYPE) ||
+ pthread_mutex_init(&g_mysql_mutex, &g_mysql_mutexattr) != 0)
+ {
+ ha_messagex(NULL, LOG_CRIT, "threading problem. can't create mutex");
+ return HA_CRITERROR;
+ }
+ }
+
return HA_OK;
}
@@ -727,6 +772,12 @@ void mysql_destroy(ha_context_t* context)
free(ctx->pool);
}
}
+ else
+ {
+ /* Close the mutex */
+ pthread_mutex_destroy(&g_mysql_mutex);
+ pthread_mutexattr_destroy(&g_mysql_mutexattr);
+ }
bd_destroy(context);
ha_messagex(NULL, LOG_INFO, "uninitialized mysql handler");