diff src/c/urweb.c @ 1121:0cee0c8d8c37

Support for protocol-specific expunger dispatch
author Adam Chlipala <adamc@hcoop.net>
date Sun, 10 Jan 2010 10:40:57 -0500
parents 74f2eb3b0606
children e1cf925e2074
line wrap: on
line diff
--- a/src/c/urweb.c	Thu Jan 07 14:02:58 2010 -0500
+++ b/src/c/urweb.c	Sun Jan 10 10:40:57 2010 -0500
@@ -150,6 +150,7 @@
   time_t last_contact;
   unsigned n_channels;
   unsigned refcount;
+  void *data;
 } client;
 
 
@@ -163,6 +164,10 @@
 size_t uw_messages_max = SIZE_MAX;
 size_t uw_clients_max = SIZE_MAX;
 
+void *uw_init_client_data();
+void uw_free_client_data(void *);
+void uw_copy_client_data(void *dst, void *src);
+
 static client *new_client() {
   client *c;
 
@@ -193,6 +198,7 @@
   buf_reset(&c->msgs);
   c->n_channels = 0;
   c->refcount = 0;
+  c->data = uw_init_client_data();
   pthread_mutex_unlock(&c->lock);
 
   c->next = clients_used;
@@ -432,6 +438,8 @@
 
   int deadline;
 
+  void *client_data;
+
   char error_message[ERROR_BUF_LEN];
 };
 
@@ -489,11 +497,17 @@
 
   ctx->deadline = INT_MAX;
 
+  ctx->client_data = uw_init_client_data();
+
   return ctx;
 }
 
 size_t uw_inputs_max = SIZE_MAX;
 
+uw_app *uw_get_app(uw_context ctx) {
+  return ctx->app;
+}
+
 int uw_set_app(uw_context ctx, uw_app *app) {
   ctx->app = app;
 
@@ -507,6 +521,10 @@
   }
 }
 
+void uw_set_client_data(uw_context ctx, void *data) {
+  uw_copy_client_data(ctx->client_data, data);
+}
+
 void uw_set_db(uw_context ctx, void *db) {
   ctx->db = db;
 }
@@ -526,6 +544,7 @@
   free(ctx->subinputs);
   free(ctx->cleanup);
   free(ctx->transactionals);
+  uw_free_client_data(ctx->client_data);
 
   for (i = 0; i < ctx->n_deltas; ++i)
     buf_free(&ctx->deltas[i].msgs);
@@ -668,6 +687,7 @@
         uw_error(ctx, FATAL, "Limit exceeded on number of message-passing clients");
 
       use_client(c);
+      uw_copy_client_data(c->data, ctx->client_data);
       ctx->client = c;
     }
   }
@@ -2977,16 +2997,18 @@
 
 // "Garbage collection"
 
-static failure_kind uw_expunge(uw_context ctx, uw_Basis_client cli) {
+void uw_do_expunge(uw_context ctx, uw_Basis_client cli, void *data);
+void uw_post_expunge(uw_context ctx, void *data);
+
+static failure_kind uw_expunge(uw_context ctx, uw_Basis_client cli, void *data) {
   int r = setjmp(ctx->jmp_buf);
 
-  if (r == 0) {
-    if (ctx->app->db_begin(ctx))
-      uw_error(ctx, FATAL, "Error running SQL BEGIN");
-    ctx->app->expunger(ctx, cli);
-    if (ctx->app->db_commit(ctx))
-      uw_error(ctx, FATAL, "Error running SQL COMMIT");
-  }
+  if (r == 0)
+    uw_do_expunge(ctx, cli, data);
+  else
+    ctx->app->db_rollback(ctx);
+
+  uw_post_expunge(ctx, data);
 
   return r;
 }
@@ -3010,18 +3032,14 @@
         clients_used = next;
       uw_reset(ctx);
       while (fk == UNLIMITED_RETRY) {
-        fk = uw_expunge(ctx, c->id);
-        if (fk == UNLIMITED_RETRY) {
-          ctx->app->db_rollback(ctx);
+        fk = uw_expunge(ctx, c->id, c->data);
+        if (fk == UNLIMITED_RETRY)
           printf("Unlimited retry during expunge: %s\n", uw_error_message(ctx));
-        }
       }
       if (fk == SUCCESS)
         free_client(c);
-      else {
-        ctx->app->db_rollback(ctx);
+      else
         fprintf(stderr, "Expunge blocked by error: %s\n", uw_error_message(ctx));
-      }
     }
     else
       prev = c;