comparison src/c/urweb.c @ 2211:ef766ef6e242

Merge.
author Ziv Scully <ziv@mit.edu>
date Sat, 13 Sep 2014 19:16:07 -0400
parents 0ca11d57c175 a9159911c3ba
children 98b87d905601
comparison
equal deleted inserted replaced
2210:69c0f36255cb 2211:ef766ef6e242
439 439
440 cleanup *cleanup, *cleanup_front, *cleanup_back; 440 cleanup *cleanup, *cleanup_front, *cleanup_back;
441 441
442 const char *script_header; 442 const char *script_header;
443 443
444 int needs_push, needs_sig, could_write_db; 444 int needs_push, needs_sig, could_write_db, at_most_one_query;
445 445
446 size_t n_deltas, used_deltas; 446 size_t n_deltas, used_deltas;
447 delta *deltas; 447 delta *deltas;
448 448
449 client *client; 449 client *client;
521 521
522 ctx->script_header = ""; 522 ctx->script_header = "";
523 ctx->needs_push = 0; 523 ctx->needs_push = 0;
524 ctx->needs_sig = 0; 524 ctx->needs_sig = 0;
525 ctx->could_write_db = 1; 525 ctx->could_write_db = 1;
526 ctx->at_most_one_query = 0;
526 527
527 ctx->source_count = 0; 528 ctx->source_count = 0;
528 529
529 ctx->n_deltas = ctx->used_deltas = 0; 530 ctx->n_deltas = ctx->used_deltas = 0;
530 ctx->deltas = malloc(0); 531 ctx->deltas = malloc(0);
789 790
790 return r; 791 return r;
791 } 792 }
792 793
793 void uw_ensure_transaction(uw_context ctx) { 794 void uw_ensure_transaction(uw_context ctx) {
794 if (!ctx->transaction_started) { 795 if (!ctx->transaction_started && !ctx->at_most_one_query) {
795 if (ctx->app->db_begin(ctx, ctx->could_write_db)) 796 if (ctx->app->db_begin(ctx, ctx->could_write_db))
796 uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN"); 797 uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN");
797 ctx->transaction_started = 1; 798 ctx->transaction_started = 1;
798 } 799 }
799 } 800 }
1046 1047
1047 int uw_set_file_input(uw_context ctx, const char *name, uw_Basis_file f) { 1048 int uw_set_file_input(uw_context ctx, const char *name, uw_Basis_file f) {
1048 int n = ctx->app->input_num(name); 1049 int n = ctx->app->input_num(name);
1049 1050
1050 if (n < 0) { 1051 if (n < 0) {
1051 uw_set_error(ctx, "Bad file input name %s", uw_Basis_htmlifyString(ctx, name)); 1052 uw_set_error(ctx, "Bad file input name");
1052 return -1; 1053 return -1;
1053 } 1054 }
1054 1055
1055 if (n >= ctx->app->inputs_len) { 1056 if (n >= ctx->app->inputs_len) {
1056 uw_set_error(ctx, "For file input name %s, index %d is out of range", uw_Basis_htmlifyString(ctx, name), n); 1057 uw_set_error(ctx, "For file input name, index %d is out of range", n);
1057 return -1; 1058 return -1;
1058 } 1059 }
1059 1060
1060 ctx->inputs[n].kind = FIL; 1061 ctx->inputs[n].kind = FIL;
1061 ctx->inputs[n].data.file = f; 1062 ctx->inputs[n].data.file = f;
1206 ctx->needs_sig = n; 1207 ctx->needs_sig = n;
1207 } 1208 }
1208 1209
1209 void uw_set_could_write_db(uw_context ctx, int n) { 1210 void uw_set_could_write_db(uw_context ctx, int n) {
1210 ctx->could_write_db = n; 1211 ctx->could_write_db = n;
1212 }
1213
1214 void uw_set_at_most_one_query(uw_context ctx, int n) {
1215 ctx->at_most_one_query = n;
1211 } 1216 }
1212 1217
1213 1218
1214 static void uw_buffer_check_ctx(uw_context ctx, const char *kind, uw_buffer *b, size_t extra, const char *desc) { 1219 static void uw_buffer_check_ctx(uw_context ctx, const char *kind, uw_buffer *b, size_t extra, const char *desc) {
1215 if (b->back - b->front < extra) { 1220 if (b->back - b->front < extra) {
3315 return NULL; 3320 return NULL;
3316 3321
3317 return s; 3322 return s;
3318 } 3323 }
3319 3324
3325 static pthread_mutex_t message_send_mutex = PTHREAD_MUTEX_INITIALIZER;
3326
3320 int uw_commit(uw_context ctx) { 3327 int uw_commit(uw_context ctx) {
3321 int i; 3328 int i;
3322 char *sig; 3329 char *sig;
3323 3330
3324 if (uw_has_error(ctx)) { 3331 if (uw_has_error(ctx)) {
3334 uw_rollback(ctx, 0); 3341 uw_rollback(ctx, 0);
3335 return 0; 3342 return 0;
3336 } 3343 }
3337 } 3344 }
3338 3345
3346 // Here's an important lock to provide the abstraction that all messages from one transaction are sent as an atomic unit.
3347 if (ctx->used_deltas > 0)
3348 pthread_mutex_lock(&message_send_mutex);
3349
3339 if (ctx->transaction_started) { 3350 if (ctx->transaction_started) {
3340 int code = ctx->app->db_commit(ctx); 3351 int code = ctx->app->db_commit(ctx);
3341 3352
3342 if (code) { 3353 if (code) {
3354 if (ctx->used_deltas > 0)
3355 pthread_mutex_unlock(&message_send_mutex);
3356
3343 if (ctx->client) 3357 if (ctx->client)
3344 release_client(ctx->client); 3358 release_client(ctx->client);
3345 3359
3346 if (code == -1) { 3360 if (code == -1) {
3347 // This case is for a serialization failure, which is not really an "error." 3361 // This case is for a serialization failure, which is not really an "error."
3354 3368
3355 for (i = ctx->used_transactionals-1; i >= 0; --i) 3369 for (i = ctx->used_transactionals-1; i >= 0; --i)
3356 if (ctx->transactionals[i].free) 3370 if (ctx->transactionals[i].free)
3357 ctx->transactionals[i].free(ctx->transactionals[i].data, 1); 3371 ctx->transactionals[i].free(ctx->transactionals[i].data, 1);
3358 3372
3359 return 1; 3373 return 1;
3360 } 3374 }
3361 3375
3362 for (i = ctx->used_transactionals-1; i >= 0; --i) 3376 for (i = ctx->used_transactionals-1; i >= 0; --i)
3363 if (ctx->transactionals[i].free) 3377 if (ctx->transactionals[i].free)
3364 ctx->transactionals[i].free(ctx->transactionals[i].data, 0); 3378 ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
3371 for (i = ctx->used_transactionals-1; i >= 0; --i) 3385 for (i = ctx->used_transactionals-1; i >= 0; --i)
3372 if (ctx->transactionals[i].rollback == NULL) 3386 if (ctx->transactionals[i].rollback == NULL)
3373 if (ctx->transactionals[i].commit) { 3387 if (ctx->transactionals[i].commit) {
3374 ctx->transactionals[i].commit(ctx->transactionals[i].data); 3388 ctx->transactionals[i].commit(ctx->transactionals[i].data);
3375 if (uw_has_error(ctx)) { 3389 if (uw_has_error(ctx)) {
3376 if (ctx->client) 3390 if (ctx->used_deltas > 0)
3377 release_client(ctx->client); 3391 pthread_mutex_unlock(&message_send_mutex);
3378 3392
3379 for (i = ctx->used_transactionals-1; i >= 0; --i) 3393 if (ctx->client)
3380 if (ctx->transactionals[i].rollback != NULL) 3394 release_client(ctx->client);
3381 ctx->transactionals[i].rollback(ctx->transactionals[i].data); 3395
3382 3396 for (i = ctx->used_transactionals-1; i >= 0; --i)
3383 for (i = ctx->used_transactionals-1; i >= 0; --i) 3397 if (ctx->transactionals[i].rollback != NULL)
3384 if (ctx->transactionals[i].free) 3398 ctx->transactionals[i].rollback(ctx->transactionals[i].data);
3385 ctx->transactionals[i].free(ctx->transactionals[i].data, 0); 3399
3400 for (i = ctx->used_transactionals-1; i >= 0; --i)
3401 if (ctx->transactionals[i].free)
3402 ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
3386 3403
3387 return 0; 3404 return 0;
3388 } 3405 }
3389 } 3406 }
3390 3407
3395 assert (c != NULL); 3412 assert (c != NULL);
3396 assert(c->mode == USED); 3413 assert(c->mode == USED);
3397 3414
3398 client_send(c, &d->msgs, ctx->script.start, uw_buffer_used(&ctx->script)); 3415 client_send(c, &d->msgs, ctx->script.start, uw_buffer_used(&ctx->script));
3399 } 3416 }
3417
3418 if (ctx->used_deltas > 0)
3419 pthread_mutex_unlock(&message_send_mutex);
3400 3420
3401 if (ctx->client) 3421 if (ctx->client)
3402 release_client(ctx->client); 3422 release_client(ctx->client);
3403 3423
3404 for (i = ctx->used_transactionals-1; i >= 0; --i) 3424 for (i = ctx->used_transactionals-1; i >= 0; --i)
3615 return NULL; 3635 return NULL;
3616 } 3636 }
3617 3637
3618 static int mime_format(const char *s) { 3638 static int mime_format(const char *s) {
3619 for (; *s; ++s) 3639 for (; *s; ++s)
3620 if (!isalnum((int)*s) && *s != '/' && *s != '-' && *s != '.') 3640 if (!isalnum((int)*s) && *s != '/' && *s != '-' && *s != '.' && *s != '+')
3621 return 0; 3641 return 0;
3622 3642
3623 return 1; 3643 return 1;
3624 } 3644 }
3625 3645
3855 cl->func(cl->arg); 3875 cl->func(cl->arg);
3856 3876
3857 ctx->cleanup_front = ctx->cleanup; 3877 ctx->cleanup_front = ctx->cleanup;
3858 3878
3859 longjmp(ctx->jmp_buf, RETURN_INDIRECTLY); 3879 longjmp(ctx->jmp_buf, RETURN_INDIRECTLY);
3880 }
3881
3882 void uw_replace_page(uw_context ctx, const char *data, size_t size) {
3883 uw_buffer_reset(&ctx->page);
3884 ctx_uw_buffer_append(ctx, "page", &ctx->page, data, size);
3860 } 3885 }
3861 3886
3862 __attribute__((noreturn)) void uw_return_blob_from_page(uw_context ctx, uw_Basis_string mimeType) { 3887 __attribute__((noreturn)) void uw_return_blob_from_page(uw_context ctx, uw_Basis_string mimeType) {
3863 cleanup *cl; 3888 cleanup *cl;
3864 int len; 3889 int len;
4267 uw_Basis_bool uw_Basis_eq_time(uw_context ctx, uw_Basis_time t1, uw_Basis_time t2) { 4292 uw_Basis_bool uw_Basis_eq_time(uw_context ctx, uw_Basis_time t1, uw_Basis_time t2) {
4268 return !!(t1.seconds == t2.seconds && t1.microseconds == t2.microseconds); 4293 return !!(t1.seconds == t2.seconds && t1.microseconds == t2.microseconds);
4269 } 4294 }
4270 4295
4271 uw_Basis_bool uw_Basis_lt_time(uw_context ctx, uw_Basis_time t1, uw_Basis_time t2) { 4296 uw_Basis_bool uw_Basis_lt_time(uw_context ctx, uw_Basis_time t1, uw_Basis_time t2) {
4272 return !!(t1.seconds < t2.seconds || t1.microseconds < t2.microseconds); 4297 return !!(t1.seconds < t2.seconds || (t1.seconds == t2.seconds && t1.microseconds < t2.microseconds));
4273 } 4298 }
4274 4299
4275 uw_Basis_bool uw_Basis_le_time(uw_context ctx, uw_Basis_time t1, uw_Basis_time t2) { 4300 uw_Basis_bool uw_Basis_le_time(uw_context ctx, uw_Basis_time t1, uw_Basis_time t2) {
4276 return !!(uw_Basis_eq_time(ctx, t1, t2) || uw_Basis_lt_time(ctx, t1, t2)); 4301 return !!(uw_Basis_eq_time(ctx, t1, t2) || uw_Basis_lt_time(ctx, t1, t2));
4277 } 4302 }