changeset 685:c73c5fe72388

Stop holding client locks throughout request processing
author Adam Chlipala <adamc@hcoop.net>
date Thu, 02 Apr 2009 10:55:00 -0400
parents f0224c7f12bb
children 3b46548f701b
files src/c/urweb.c
diffstat 1 files changed, 23 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/c/urweb.c	Sun Mar 29 14:13:50 2009 -0400
+++ b/src/c/urweb.c	Thu Apr 02 10:55:00 2009 -0400
@@ -99,6 +99,7 @@
   int sock;
   time_t last_contact;
   unsigned n_channels;
+  unsigned refcount;
 } client;
 
 
@@ -135,6 +136,7 @@
   c->last_contact = time(NULL);
   buf_reset(&c->msgs);
   c->n_channels = 0;
+  c->refcount = 0;
   pthread_mutex_unlock(&c->lock);
 
   c->next = clients_used;
@@ -145,6 +147,18 @@
   return c;
 }
 
+static void use_client(client *c) {
+  pthread_mutex_lock(&c->lock);
+  ++c->refcount;
+  pthread_mutex_unlock(&c->lock);
+}
+
+static void release_client(client *c) {
+  pthread_mutex_lock(&c->lock);
+  --c->refcount;
+  pthread_mutex_unlock(&c->lock);
+}
+
 static const char begin_msgs[] = "HTTP/1.1 200 OK\r\nContent-type: text/plain\r\n\r\n";
 
 static client *find_client(unsigned id) {
@@ -222,9 +236,8 @@
   return ch;
 }
 
-static void client_send(int already_locked, client *c, buf *msg) {
-  if (!already_locked)
-    pthread_mutex_lock(&c->lock);
+static void client_send(client *c, buf *msg) {
+  pthread_mutex_lock(&c->lock);
 
   if (c->sock != -1) {
     uw_really_send(c->sock, begin_msgs, sizeof(begin_msgs) - 1);
@@ -234,8 +247,7 @@
   } else
     buf_append(&c->msgs, msg->start, buf_used(msg));
 
-  if (!already_locked)
-    pthread_mutex_unlock(&c->lock);
+  pthread_mutex_unlock(&c->lock);
 }
 
 
@@ -472,7 +484,7 @@
       if (c == NULL)
         uw_error(ctx, FATAL, "Unknown client ID in HTTP headers (%s, %s)", id_s, pass_s);
       else {
-        pthread_mutex_lock(&c->lock);
+        use_client(c);
         ctx->client = c;
 
         if (c->mode != USED)
@@ -482,7 +494,7 @@
       }
     } else {
       client *c = new_client();
-      pthread_mutex_lock(&c->lock);
+      use_client(c);
       ctx->client = c;
     }  
   }
@@ -1847,16 +1859,16 @@
 
     assert (c != NULL && c->mode == USED);
 
-    client_send(c == ctx->client, c, &d->msgs);
+    client_send(c, &d->msgs);
   }
 
   if (ctx->client)
-    pthread_mutex_unlock(&ctx->client->lock);
+    release_client(ctx->client);
 }
 
 int uw_rollback(uw_context ctx) {
   if (ctx->client)
-    pthread_mutex_unlock(&ctx->client->lock);
+    release_client(ctx->client);
 
   return uw_db_rollback(ctx);
 }
@@ -1891,7 +1903,7 @@
   for (c = clients_used; c; c = next) {
     next = c->next;
     pthread_mutex_lock(&c->lock);
-    if (c->last_contact < cutoff) {
+    if (c->last_contact < cutoff && c->refcount == 0) {
       failure_kind fk = UNLIMITED_RETRY;
       if (prev)
         prev->next = next;