diff src/c/urweb.c @ 683:9a2c18dab11d

Expunging non-nullable rows
author Adam Chlipala <adamc@hcoop.net>
date Sun, 29 Mar 2009 13:30:01 -0400
parents 5bbb542243e8
children f0224c7f12bb
line wrap: on
line diff
--- a/src/c/urweb.c	Sun Mar 29 11:37:29 2009 -0400
+++ b/src/c/urweb.c	Sun Mar 29 13:30:01 2009 -0400
@@ -208,7 +208,7 @@
 }
 
 static void free_client(client *c) {
-  printf("Freeing client %d\n", c->id);
+  printf("Freeing client %u\n", c->id);
 
   c->mode = UNUSED;
   c->pass = -1;
@@ -217,34 +217,6 @@
   clients_free = c;
 }
 
-extern int uw_timeout;
-
-void uw_prune_clients() {
-  client *c, *next, *prev = NULL;
-  time_t cutoff;
-
-  cutoff = time(NULL) - uw_timeout;
-
-  pthread_mutex_lock(&clients_mutex);
-
-  for (c = clients_used; c; c = next) {
-    next = c->next;
-    pthread_mutex_lock(&c->lock);
-    if (c->last_contact < cutoff) {
-      if (prev)
-        prev->next = next;
-      else
-        clients_used = next;
-      free_client(c);
-    }
-    else
-      prev = c;
-    pthread_mutex_unlock(&c->lock);
-  }
-
-  pthread_mutex_unlock(&clients_mutex);
-}
-
 static uw_Basis_channel new_channel(client *c) {
   uw_Basis_channel ch = {c->id, c->n_channels++};
   return ch;
@@ -322,7 +294,7 @@
   char error_message[ERROR_BUF_LEN];
 };
 
-extern int uw_inputs_len;
+extern int uw_inputs_len, uw_timeout;
 
 uw_context uw_init(size_t outHeaders_len, size_t script_len, size_t page_len, size_t heap_len) {
   uw_context ctx = malloc(sizeof(struct uw_context));
@@ -1888,3 +1860,53 @@
 
   return uw_db_rollback(ctx);
 }
+
+
+// "Garbage collection"
+
+void uw_expunger(uw_context ctx, uw_Basis_client cli);
+
+static failure_kind uw_expunge(uw_context ctx, uw_Basis_client cli) {
+  int r = setjmp(ctx->jmp_buf);
+
+  if (r == 0)
+    uw_expunger(ctx, cli);
+
+  return r;
+}
+
+void uw_prune_clients(uw_context ctx) {
+  client *c, *next, *prev = NULL;
+  time_t cutoff;
+
+  cutoff = time(NULL) - uw_timeout;
+
+  pthread_mutex_lock(&clients_mutex);
+
+  for (c = clients_used; c; c = next) {
+    next = c->next;
+    pthread_mutex_lock(&c->lock);
+    if (c->last_contact < cutoff) {
+      failure_kind fk = UNLIMITED_RETRY;
+      if (prev)
+        prev->next = next;
+      else
+        clients_used = next;
+      while (fk == UNLIMITED_RETRY) {
+        uw_reset(ctx);
+        fk = uw_expunge(ctx, c->id);
+        if (fk == SUCCESS) {
+          free_client(c);
+          break;
+        }
+      }
+      if (fk != SUCCESS)
+        printf("Expunge blocked by error: %s\n", uw_error_message(ctx));
+    }
+    else
+      prev = c;
+    pthread_mutex_unlock(&c->lock);
+  }
+
+  pthread_mutex_unlock(&clients_mutex);
+}