# HG changeset patch # User Adam Chlipala # Date 1291479320 18000 # Node ID 1cc67fdac4d3c44de91c86a7f16c29c930b8d1fa # Parent d91f845996933ee1843af3e4c1e244f0bf223bea New argument to transactional free functions, to specify whether we are about to retry diff -r d91f84599693 -r 1cc67fdac4d3 include/types.h --- 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 { diff -r d91f84599693 -r 1cc67fdac4d3 include/urweb.h --- 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); diff -r d91f84599693 -r 1cc67fdac4d3 src/c/request.c --- 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); diff -r d91f84599693 -r 1cc67fdac4d3 src/c/urweb.c --- 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"); diff -r d91f84599693 -r 1cc67fdac4d3 tests/transact.ur --- /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 {[listHell (readError r.N)]} + +fun main () = return +
+
diff -r d91f84599693 -r 1cc67fdac4d3 tests/transact.urp --- /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 diff -r d91f84599693 -r 1cc67fdac4d3 tests/transact.urs --- /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 diff -r d91f84599693 -r 1cc67fdac4d3 tests/transactional.c --- /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 + +#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); +} diff -r d91f84599693 -r 1cc67fdac4d3 tests/transactional.h --- /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); diff -r d91f84599693 -r 1cc67fdac4d3 tests/transactional.urp --- /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 diff -r d91f84599693 -r 1cc67fdac4d3 tests/transactional.urs --- /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 {}