comparison src/c/urweb.c @ 1131:94e83c5533d2

Handling errors during commit
author Adam Chlipala <adamc@hcoop.net>
date Tue, 26 Jan 2010 14:59:19 -0500
parents e1cf925e2074
children b08b73591d2c
comparison
equal deleted inserted replaced
1130:67d875c8ac71 1131:94e83c5533d2
609 static void uw_set_error(uw_context ctx, const char *fmt, ...) { 609 static void uw_set_error(uw_context ctx, const char *fmt, ...) {
610 va_list ap; 610 va_list ap;
611 va_start(ap, fmt); 611 va_start(ap, fmt);
612 612
613 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap); 613 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
614 }
615
616 int uw_has_error(uw_context ctx) {
617 return ctx->error_message[0] != 0;
614 } 618 }
615 619
616 __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) { 620 __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) {
617 cleanup *cl; 621 cleanup *cl;
618 622
2886 ctx_buf_append(ctx, "messages", &d->msgs, "\n", 1); 2890 ctx_buf_append(ctx, "messages", &d->msgs, "\n", 1);
2887 2891
2888 return uw_unit_v; 2892 return uw_unit_v;
2889 } 2893 }
2890 2894
2895 int uw_rollback(uw_context ctx) {
2896 int i;
2897 cleanup *cl;
2898
2899 if (ctx->client)
2900 release_client(ctx->client);
2901
2902 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
2903 cl->func(cl->arg);
2904
2905 ctx->cleanup_front = ctx->cleanup;
2906
2907 for (i = ctx->used_transactionals-1; i >= 0; --i)
2908 if (ctx->transactionals[i].rollback != NULL)
2909 ctx->transactionals[i].rollback(ctx->transactionals[i].data);
2910
2911 for (i = ctx->used_transactionals-1; i >= 0; --i)
2912 if (ctx->transactionals[i].free)
2913 ctx->transactionals[i].free(ctx->transactionals[i].data);
2914
2915 return ctx->app->db_rollback(ctx);
2916 }
2917
2891 void uw_commit(uw_context ctx) { 2918 void uw_commit(uw_context ctx) {
2892 int i; 2919 int i;
2893 2920
2921 if (uw_has_error(ctx)) {
2922 uw_rollback(ctx);
2923 return;
2924 }
2925
2894 for (i = ctx->used_transactionals-1; i >= 0; --i) 2926 for (i = ctx->used_transactionals-1; i >= 0; --i)
2895 if (ctx->transactionals[i].rollback != NULL) 2927 if (ctx->transactionals[i].rollback != NULL)
2896 if (ctx->transactionals[i].commit) 2928 if (ctx->transactionals[i].commit) {
2897 ctx->transactionals[i].commit(ctx->transactionals[i].data); 2929 ctx->transactionals[i].commit(ctx->transactionals[i].data);
2930 if (uw_has_error(ctx)) {
2931 uw_rollback(ctx);
2932 return;
2933 }
2934 }
2898 2935
2899 for (i = ctx->used_transactionals-1; i >= 0; --i) 2936 for (i = ctx->used_transactionals-1; i >= 0; --i)
2900 if (ctx->transactionals[i].rollback == NULL) 2937 if (ctx->transactionals[i].rollback == NULL)
2901 if (ctx->transactionals[i].commit) 2938 if (ctx->transactionals[i].commit) {
2902 ctx->transactionals[i].commit(ctx->transactionals[i].data); 2939 ctx->transactionals[i].commit(ctx->transactionals[i].data);
2903 2940 if (uw_has_error(ctx)) {
2904 if (ctx->app->db_commit(ctx)) 2941 uw_rollback(ctx);
2905 uw_error(ctx, FATAL, "Error running SQL COMMIT"); 2942 return;
2943 }
2944 }
2945
2946 if (ctx->app->db_commit(ctx)) {
2947 uw_set_error_message(ctx, "Error running SQL COMMIT");
2948 return;
2949 }
2906 2950
2907 for (i = 0; i < ctx->used_deltas; ++i) { 2951 for (i = 0; i < ctx->used_deltas; ++i) {
2908 delta *d = &ctx->deltas[i]; 2952 delta *d = &ctx->deltas[i];
2909 client *c = find_client(d->client); 2953 client *c = find_client(d->client);
2910 2954
2952 memcpy(start + lenH + 31 + len, "</script>", 9); 2996 memcpy(start + lenH + 31 + len, "</script>", 9);
2953 } 2997 }
2954 } 2998 }
2955 } 2999 }
2956 3000
2957 int uw_rollback(uw_context ctx) {
2958 int i;
2959 cleanup *cl;
2960
2961 if (ctx->client)
2962 release_client(ctx->client);
2963
2964 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
2965 cl->func(cl->arg);
2966
2967 ctx->cleanup_front = ctx->cleanup;
2968
2969 for (i = ctx->used_transactionals-1; i >= 0; --i)
2970 if (ctx->transactionals[i].rollback != NULL)
2971 ctx->transactionals[i].rollback(ctx->transactionals[i].data);
2972
2973 for (i = ctx->used_transactionals-1; i >= 0; --i)
2974 if (ctx->transactionals[i].free)
2975 ctx->transactionals[i].free(ctx->transactionals[i].data);
2976
2977 return ctx->app->db_rollback(ctx);
2978 }
2979 3001
2980 size_t uw_transactionals_max = SIZE_MAX; 3002 size_t uw_transactionals_max = SIZE_MAX;
2981 3003
2982 void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback, 3004 void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback,
2983 uw_callback free) { 3005 uw_callback free) {