changeset 1327:1cc67fdac4d3

New argument to transactional free functions, to specify whether we are about to retry
author Adam Chlipala <adam@chlipala.net>
date Sat, 04 Dec 2010 11:15:20 -0500 (2010-12-04)
parents d91f84599693
children c5799b1e4c58
files include/types.h include/urweb.h src/c/request.c src/c/urweb.c tests/transact.ur tests/transact.urp tests/transact.urs tests/transactional.c tests/transactional.h tests/transactional.urp tests/transactional.urs
diffstat 11 files changed, 59 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/include/types.h	Thu Dec 02 14:11:18 2010 -0500
+++ b/include/types.h	Sat Dec 04 11:15:20 2010 -0500
@@ -51,6 +51,7 @@
 #define TIMES_MAX 100
 
 typedef void (*uw_callback)(void *);
+typedef void (*uw_callback_with_retry)(void *, int will_retry);
 typedef void (*uw_logger)(void*, const char *fmt, ...);
 
 typedef struct {
--- a/include/urweb.h	Thu Dec 02 14:11:18 2010 -0500
+++ b/include/urweb.h	Sat Dec 04 11:15:20 2010 -0500
@@ -39,7 +39,7 @@
 failure_kind uw_begin_onError(uw_context, char *msg);
 void uw_login(uw_context);
 void uw_commit(uw_context);
-int uw_rollback(uw_context);
+int uw_rollback(uw_context, int will_retry);
 
 __attribute__((noreturn)) void uw_error(uw_context, failure_kind, const char *fmt, ...);
 char *uw_error_message(uw_context);
@@ -228,7 +228,7 @@
 uw_Basis_time uw_Basis_minusSeconds(uw_context, uw_Basis_time, uw_Basis_int);
 extern const uw_Basis_time uw_Basis_minTime;
 
-void uw_register_transactional(uw_context, void *data, uw_callback commit, uw_callback rollback, uw_callback free);
+void uw_register_transactional(uw_context, void *data, uw_callback commit, uw_callback rollback, uw_callback_with_retry free);
 
 void uw_check_heap(uw_context, size_t extra);
 char *uw_heap_front(uw_context);
--- a/src/c/request.c	Thu Dec 02 14:11:18 2010 -0500
+++ b/src/c/request.c	Sat Dec 04 11:15:20 2010 -0500
@@ -19,8 +19,8 @@
 
 void *memmem(const void *b1, size_t len1, const void *b2, size_t len2);
 
-static int try_rollback(uw_context ctx, void *logger_data, uw_logger log_error) {
-  int r = uw_rollback(ctx);
+static int try_rollback(uw_context ctx, int will_retry, void *logger_data, uw_logger log_error) {
+  int r = uw_rollback(ctx, will_retry);
 
   if (r) {
     log_error(logger_data, "Error running SQL ROLLBACK\n");
@@ -102,13 +102,13 @@
 
   for (fk = uw_initialize(ctx); fk == UNLIMITED_RETRY; fk = uw_initialize(ctx)) {
     log_debug(logger_data, "Unlimited retry during init: %s\n", uw_error_message(ctx));
-    uw_rollback(ctx);
+    uw_rollback(ctx, 1);
     uw_reset(ctx);
   }
 
   if (fk != SUCCESS) {
     log_error(logger_data, "Failed to initialize database!  %s\n", uw_error_message(ctx));
-    uw_rollback(ctx);
+    uw_rollback(ctx, 0);
     exit(1);
   }
 
@@ -403,7 +403,7 @@
       else {
         log_error(logger_data, "Fatal error (out of retries): %s\n", uw_error_message(ctx));
 
-        try_rollback(ctx, logger_data, log_error);
+        try_rollback(ctx, 0, logger_data, log_error);
 
         if (!had_error && uw_get_app(ctx)->on_error) {
           had_error = 1;
@@ -424,7 +424,7 @@
     else if (fk == FATAL) {
       log_error(logger_data, "Fatal error: %s\n", uw_error_message(ctx));
 
-      try_rollback(ctx, logger_data, log_error);
+      try_rollback(ctx, 0, logger_data, log_error);
 
       if (uw_get_app(ctx)->on_error && !had_error) {
         had_error = 1;
@@ -443,7 +443,7 @@
     } else {
       log_error(logger_data, "Unknown uw_handle return code!\n");
 
-      try_rollback(ctx, logger_data, log_error);
+      try_rollback(ctx, 0, logger_data, log_error);
 
       if (uw_get_app(ctx)->on_error && !had_error) {
         had_error = 1;
@@ -458,7 +458,7 @@
       }
     }
 
-    if (try_rollback(ctx, logger_data, log_error))
+    if (try_rollback(ctx, 1, logger_data, log_error))
       return FAILED;
 
     uw_reset_keep_request(ctx);
--- a/src/c/urweb.c	Thu Dec 02 14:11:18 2010 -0500
+++ b/src/c/urweb.c	Sat Dec 04 11:15:20 2010 -0500
@@ -390,7 +390,8 @@
 
 typedef struct {
   void *data;
-  uw_callback commit, rollback, free;
+  uw_callback commit, rollback;
+  uw_callback_with_retry free;
 } transactional;
 
 typedef struct {
@@ -2902,7 +2903,7 @@
   return uw_unit_v;
 }
 
-int uw_rollback(uw_context ctx) {
+int uw_rollback(uw_context ctx, int will_retry) {
   int i;
   cleanup *cl;
 
@@ -2920,7 +2921,7 @@
 
   for (i = ctx->used_transactionals-1; i >= 0; --i)
     if (ctx->transactionals[i].free)
-      ctx->transactionals[i].free(ctx->transactionals[i].data);
+      ctx->transactionals[i].free(ctx->transactionals[i].data, will_retry);
 
   return ctx->app ? ctx->app->db_rollback(ctx) : 0;
 }
@@ -2929,7 +2930,7 @@
   int i;
 
   if (uw_has_error(ctx)) {
-    uw_rollback(ctx);
+    uw_rollback(ctx, 0);
     return;
   }
 
@@ -2938,7 +2939,7 @@
       if (ctx->transactionals[i].commit) {
         ctx->transactionals[i].commit(ctx->transactionals[i].data);
         if (uw_has_error(ctx)) {
-          uw_rollback(ctx);
+          uw_rollback(ctx, 0);
           return;
         }
       }
@@ -2948,7 +2949,7 @@
       if (ctx->transactionals[i].commit) {
         ctx->transactionals[i].commit(ctx->transactionals[i].data);
         if (uw_has_error(ctx)) {
-          uw_rollback(ctx);
+          uw_rollback(ctx, 0);
           return;
         }
       }
@@ -2972,7 +2973,7 @@
 
   for (i = ctx->used_transactionals-1; i >= 0; --i)
     if (ctx->transactionals[i].free)
-      ctx->transactionals[i].free(ctx->transactionals[i].data);
+      ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
 
   // Splice script data into appropriate part of page
   if (ctx->returning_indirectly || ctx->script_header[0] == 0) {
@@ -3012,7 +3013,7 @@
 size_t uw_transactionals_max = SIZE_MAX;
 
 void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback,
-                               uw_callback free) {
+                               uw_callback_with_retry free) {
   if (ctx->used_transactionals >= ctx->n_transactionals) {
     if (ctx->used_transactionals+1 > uw_transactionals_max)
       uw_error(ctx, FATAL, "Exceeded limit on number of transactionals");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/transact.ur	Sat Dec 04 11:15:20 2010 -0500
@@ -0,0 +1,13 @@
+fun listHell n =
+    if n <= 0 then
+        []
+    else
+        n :: List.append (listHell (n-1)) (listHell (n-1))
+
+fun doit r =
+    Transactional.foo;
+    return <xml>{[listHell (readError r.N)]}</xml>
+
+fun main () = return <xml><body>
+  <form> <textbox{#N}/> <submit action={doit}/> </form>
+</body></xml>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/transact.urp	Sat Dec 04 11:15:20 2010 -0500
@@ -0,0 +1,5 @@
+library transactional
+rewrite all Transact/*
+
+$/list
+transact
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/transact.urs	Sat Dec 04 11:15:20 2010 -0500
@@ -0,0 +1,1 @@
+val main : unit -> transaction page
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/transactional.c	Sat Dec 04 11:15:20 2010 -0500
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+#include "/usr/local/include/urweb/urweb.h"
+
+static void do_free(void *data, int will_retry) {
+  printf("will_retry = %d\n", will_retry);
+}
+
+uw_unit uw_Transactional_foo(uw_context ctx) {
+  printf("Registering....\n");
+  uw_register_transactional(ctx, NULL, NULL, NULL, do_free);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/transactional.h	Sat Dec 04 11:15:20 2010 -0500
@@ -0,0 +1,3 @@
+#include "/usr/local/include/urweb/types.h"
+
+uw_unit uw_Transactional_foo(uw_context);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/transactional.urp	Sat Dec 04 11:15:20 2010 -0500
@@ -0,0 +1,4 @@
+ffi transactional
+include transactional.h
+link transactional.o
+effectful Transactional.foo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/transactional.urs	Sat Dec 04 11:15:20 2010 -0500
@@ -0,0 +1,1 @@
+val foo : transaction {}