comparison src/c/urweb.c @ 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
parents 714e8b84221b
children 452b14d88a10
comparison
equal deleted inserted replaced
1326:d91f84599693 1327:1cc67fdac4d3
388 } data; 388 } data;
389 } input; 389 } input;
390 390
391 typedef struct { 391 typedef struct {
392 void *data; 392 void *data;
393 uw_callback commit, rollback, free; 393 uw_callback commit, rollback;
394 uw_callback_with_retry free;
394 } transactional; 395 } transactional;
395 396
396 typedef struct { 397 typedef struct {
397 char *name; 398 char *name;
398 void *data; 399 void *data;
2900 ctx_buf_append(ctx, "messages", &d->msgs, "\n", 1); 2901 ctx_buf_append(ctx, "messages", &d->msgs, "\n", 1);
2901 2902
2902 return uw_unit_v; 2903 return uw_unit_v;
2903 } 2904 }
2904 2905
2905 int uw_rollback(uw_context ctx) { 2906 int uw_rollback(uw_context ctx, int will_retry) {
2906 int i; 2907 int i;
2907 cleanup *cl; 2908 cleanup *cl;
2908 2909
2909 if (ctx->client) 2910 if (ctx->client)
2910 release_client(ctx->client); 2911 release_client(ctx->client);
2918 if (ctx->transactionals[i].rollback != NULL) 2919 if (ctx->transactionals[i].rollback != NULL)
2919 ctx->transactionals[i].rollback(ctx->transactionals[i].data); 2920 ctx->transactionals[i].rollback(ctx->transactionals[i].data);
2920 2921
2921 for (i = ctx->used_transactionals-1; i >= 0; --i) 2922 for (i = ctx->used_transactionals-1; i >= 0; --i)
2922 if (ctx->transactionals[i].free) 2923 if (ctx->transactionals[i].free)
2923 ctx->transactionals[i].free(ctx->transactionals[i].data); 2924 ctx->transactionals[i].free(ctx->transactionals[i].data, will_retry);
2924 2925
2925 return ctx->app ? ctx->app->db_rollback(ctx) : 0; 2926 return ctx->app ? ctx->app->db_rollback(ctx) : 0;
2926 } 2927 }
2927 2928
2928 void uw_commit(uw_context ctx) { 2929 void uw_commit(uw_context ctx) {
2929 int i; 2930 int i;
2930 2931
2931 if (uw_has_error(ctx)) { 2932 if (uw_has_error(ctx)) {
2932 uw_rollback(ctx); 2933 uw_rollback(ctx, 0);
2933 return; 2934 return;
2934 } 2935 }
2935 2936
2936 for (i = ctx->used_transactionals-1; i >= 0; --i) 2937 for (i = ctx->used_transactionals-1; i >= 0; --i)
2937 if (ctx->transactionals[i].rollback != NULL) 2938 if (ctx->transactionals[i].rollback != NULL)
2938 if (ctx->transactionals[i].commit) { 2939 if (ctx->transactionals[i].commit) {
2939 ctx->transactionals[i].commit(ctx->transactionals[i].data); 2940 ctx->transactionals[i].commit(ctx->transactionals[i].data);
2940 if (uw_has_error(ctx)) { 2941 if (uw_has_error(ctx)) {
2941 uw_rollback(ctx); 2942 uw_rollback(ctx, 0);
2942 return; 2943 return;
2943 } 2944 }
2944 } 2945 }
2945 2946
2946 for (i = ctx->used_transactionals-1; i >= 0; --i) 2947 for (i = ctx->used_transactionals-1; i >= 0; --i)
2947 if (ctx->transactionals[i].rollback == NULL) 2948 if (ctx->transactionals[i].rollback == NULL)
2948 if (ctx->transactionals[i].commit) { 2949 if (ctx->transactionals[i].commit) {
2949 ctx->transactionals[i].commit(ctx->transactionals[i].data); 2950 ctx->transactionals[i].commit(ctx->transactionals[i].data);
2950 if (uw_has_error(ctx)) { 2951 if (uw_has_error(ctx)) {
2951 uw_rollback(ctx); 2952 uw_rollback(ctx, 0);
2952 return; 2953 return;
2953 } 2954 }
2954 } 2955 }
2955 2956
2956 if (ctx->app->db_commit(ctx)) { 2957 if (ctx->app->db_commit(ctx)) {
2970 if (ctx->client) 2971 if (ctx->client)
2971 release_client(ctx->client); 2972 release_client(ctx->client);
2972 2973
2973 for (i = ctx->used_transactionals-1; i >= 0; --i) 2974 for (i = ctx->used_transactionals-1; i >= 0; --i)
2974 if (ctx->transactionals[i].free) 2975 if (ctx->transactionals[i].free)
2975 ctx->transactionals[i].free(ctx->transactionals[i].data); 2976 ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
2976 2977
2977 // Splice script data into appropriate part of page 2978 // Splice script data into appropriate part of page
2978 if (ctx->returning_indirectly || ctx->script_header[0] == 0) { 2979 if (ctx->returning_indirectly || ctx->script_header[0] == 0) {
2979 char *start = strstr(ctx->page.start, "<sc>"); 2980 char *start = strstr(ctx->page.start, "<sc>");
2980 if (start) { 2981 if (start) {
3010 3011
3011 3012
3012 size_t uw_transactionals_max = SIZE_MAX; 3013 size_t uw_transactionals_max = SIZE_MAX;
3013 3014
3014 void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback, 3015 void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback,
3015 uw_callback free) { 3016 uw_callback_with_retry free) {
3016 if (ctx->used_transactionals >= ctx->n_transactionals) { 3017 if (ctx->used_transactionals >= ctx->n_transactionals) {
3017 if (ctx->used_transactionals+1 > uw_transactionals_max) 3018 if (ctx->used_transactionals+1 > uw_transactionals_max)
3018 uw_error(ctx, FATAL, "Exceeded limit on number of transactionals"); 3019 uw_error(ctx, FATAL, "Exceeded limit on number of transactionals");
3019 ctx->transactionals = realloc(ctx->transactionals, sizeof(transactional) * (ctx->used_transactionals+1)); 3020 ctx->transactionals = realloc(ctx->transactionals, sizeof(transactional) * (ctx->used_transactionals+1));
3020 ++ctx->n_transactionals; 3021 ++ctx->n_transactionals;