diff options
-rw-r--r-- | include/types.h | 1 | ||||
-rw-r--r-- | include/urweb.h | 4 | ||||
-rw-r--r-- | src/c/request.c | 16 | ||||
-rw-r--r-- | src/c/urweb.c | 17 | ||||
-rw-r--r-- | tests/transact.ur | 13 | ||||
-rw-r--r-- | tests/transact.urp | 5 | ||||
-rw-r--r-- | tests/transact.urs | 1 | ||||
-rw-r--r-- | tests/transactional.c | 12 | ||||
-rw-r--r-- | tests/transactional.h | 3 | ||||
-rw-r--r-- | tests/transactional.urp | 4 | ||||
-rw-r--r-- | tests/transactional.urs | 1 |
11 files changed, 59 insertions, 18 deletions
diff --git a/include/types.h b/include/types.h index ac70c34f..e5edab96 100644 --- a/include/types.h +++ b/include/types.h @@ -51,6 +51,7 @@ typedef struct input *uw_input; #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 --git a/include/urweb.h b/include/urweb.h index 4816537a..f63b3f4c 100644 --- a/include/urweb.h +++ b/include/urweb.h @@ -39,7 +39,7 @@ failure_kind uw_begin(uw_context, char *path); 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_now(uw_context); 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 --git a/src/c/request.c b/src/c/request.c index 52006e85..ae46326d 100644 --- a/src/c/request.c +++ b/src/c/request.c @@ -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 @@ void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_log 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 @@ request_result uw_request(uw_request_context rc, uw_context ctx, 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 @@ request_result uw_request(uw_request_context rc, uw_context ctx, 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 @@ request_result uw_request(uw_request_context rc, uw_context ctx, } 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 @@ request_result uw_request(uw_request_context rc, uw_context ctx, } } - 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 --git a/src/c/urweb.c b/src/c/urweb.c index bdaa877f..91c6f6b3 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -390,7 +390,8 @@ typedef struct input { 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 @@ uw_unit uw_Basis_send(uw_context ctx, uw_Basis_channel chn, uw_Basis_string msg) 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 @@ int uw_rollback(uw_context ctx) { 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 @@ void uw_commit(uw_context ctx) { int i; if (uw_has_error(ctx)) { - uw_rollback(ctx); + uw_rollback(ctx, 0); return; } @@ -2938,7 +2939,7 @@ void uw_commit(uw_context ctx) { 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 @@ void uw_commit(uw_context ctx) { 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 @@ void uw_commit(uw_context ctx) { 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 @@ void uw_commit(uw_context ctx) { 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 --git a/tests/transact.ur b/tests/transact.ur new file mode 100644 index 00000000..baf8ab94 --- /dev/null +++ b/tests/transact.ur @@ -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> diff --git a/tests/transact.urp b/tests/transact.urp new file mode 100644 index 00000000..dcd84854 --- /dev/null +++ b/tests/transact.urp @@ -0,0 +1,5 @@ +library transactional +rewrite all Transact/* + +$/list +transact diff --git a/tests/transact.urs b/tests/transact.urs new file mode 100644 index 00000000..6ac44e0b --- /dev/null +++ b/tests/transact.urs @@ -0,0 +1 @@ +val main : unit -> transaction page diff --git a/tests/transactional.c b/tests/transactional.c new file mode 100644 index 00000000..54e26874 --- /dev/null +++ b/tests/transactional.c @@ -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); +} diff --git a/tests/transactional.h b/tests/transactional.h new file mode 100644 index 00000000..afb15327 --- /dev/null +++ b/tests/transactional.h @@ -0,0 +1,3 @@ +#include "/usr/local/include/urweb/types.h" + +uw_unit uw_Transactional_foo(uw_context); diff --git a/tests/transactional.urp b/tests/transactional.urp new file mode 100644 index 00000000..4ff1fea7 --- /dev/null +++ b/tests/transactional.urp @@ -0,0 +1,4 @@ +ffi transactional +include transactional.h +link transactional.o +effectful Transactional.foo diff --git a/tests/transactional.urs b/tests/transactional.urs new file mode 100644 index 00000000..8dea9bca --- /dev/null +++ b/tests/transactional.urs @@ -0,0 +1 @@ +val foo : transaction {} |