comparison src/c/urweb.c @ 2206:c1a62ce47083

Merge.
author Ziv Scully <ziv@mit.edu>
date Tue, 27 May 2014 21:38:01 -0400
parents 01c8aceac480 4a93f379c452
children cb74460f046a
comparison
equal deleted inserted replaced
2205:cdea39473c78 2206:c1a62ce47083
458 458
459 int deadline; 459 int deadline;
460 460
461 void *client_data; 461 void *client_data;
462 462
463 void *logger_data; 463 uw_loggers *loggers;
464 uw_logger log_debug;
465 464
466 int isPost, hasPostBody; 465 int isPost, hasPostBody;
467 uw_Basis_postBody postBody; 466 uw_Basis_postBody postBody;
468 uw_Basis_string queryString; 467 uw_Basis_string queryString;
469 468
485 size_t uw_headers_max = SIZE_MAX; 484 size_t uw_headers_max = SIZE_MAX;
486 size_t uw_page_max = SIZE_MAX; 485 size_t uw_page_max = SIZE_MAX;
487 size_t uw_heap_max = SIZE_MAX; 486 size_t uw_heap_max = SIZE_MAX;
488 size_t uw_script_max = SIZE_MAX; 487 size_t uw_script_max = SIZE_MAX;
489 488
490 uw_context uw_init(int id, void *logger_data, uw_logger log_debug) { 489 uw_context uw_init(int id, uw_loggers *lg) {
491 uw_context ctx = malloc(sizeof(struct uw_context)); 490 uw_context ctx = malloc(sizeof(struct uw_context));
492 491
493 ctx->app = NULL; 492 ctx->app = NULL;
494 ctx->id = id; 493 ctx->id = id;
495 494
544 543
545 ctx->deadline = INT_MAX; 544 ctx->deadline = INT_MAX;
546 545
547 ctx->client_data = uw_init_client_data(); 546 ctx->client_data = uw_init_client_data();
548 547
549 ctx->logger_data = logger_data; 548 ctx->loggers = lg;
550 ctx->log_debug = log_debug;
551 549
552 ctx->isPost = ctx->hasPostBody = 0; 550 ctx->isPost = ctx->hasPostBody = 0;
553 551
554 ctx->queryString = NULL; 552 ctx->queryString = NULL;
555 553
597 ctx->db = db; 595 ctx->db = db;
598 } 596 }
599 597
600 void *uw_get_db(uw_context ctx) { 598 void *uw_get_db(uw_context ctx) {
601 return ctx->db; 599 return ctx->db;
600 }
601
602
603 uw_loggers* uw_get_loggers(struct uw_context *ctx) {
604 return ctx->loggers;
602 } 605 }
603 606
604 void uw_free(uw_context ctx) { 607 void uw_free(uw_context ctx) {
605 size_t i; 608 size_t i;
606 609
1256 1259
1257 void uw_end_initializing(uw_context ctx) { 1260 void uw_end_initializing(uw_context ctx) {
1258 ctx->amInitializing = 0; 1261 ctx->amInitializing = 0;
1259 } 1262 }
1260 1263
1264 static void align_heap(uw_context ctx) {
1265 size_t posn = ctx->heap.front - ctx->heap.start;
1266
1267 if (posn % 4 != 0) {
1268 size_t bump = 4 - posn % 4;
1269 uw_check_heap(ctx, bump);
1270 ctx->heap.front += bump;
1271 }
1272 }
1273
1261 void *uw_malloc(uw_context ctx, size_t len) { 1274 void *uw_malloc(uw_context ctx, size_t len) {
1275 // On some architectures, it's important that all word-sized memory accesses
1276 // be to word-aligned addresses, so we'll do a little bit of extra work here
1277 // in anticipation of a possible word-aligned access to the address we'll
1278 // return.
1279
1262 void *result; 1280 void *result;
1263 1281
1264 if (ctx->amInitializing) { 1282 if (ctx->amInitializing) {
1265 result = malloc(len); 1283 int error = posix_memalign(&result, 4, len);
1266 1284
1267 if (result) 1285 if (!error)
1268 return result; 1286 return result;
1269 else 1287 else
1270 uw_error(ctx, FATAL, "uw_malloc: malloc() returns 0"); 1288 uw_error(ctx, FATAL, "uw_malloc: posix_memalign() returns %d", error);
1271 } else { 1289 } else {
1290 align_heap(ctx);
1291
1272 uw_check_heap(ctx, len); 1292 uw_check_heap(ctx, len);
1273 1293
1274 result = ctx->heap.front; 1294 result = ctx->heap.front;
1275 ctx->heap.front += len; 1295 ctx->heap.front += len;
1276 return result; 1296 return result;
1277 } 1297 }
1278 } 1298 }
1279 1299
1280 void uw_begin_region(uw_context ctx) { 1300 void uw_begin_region(uw_context ctx) {
1301 align_heap(ctx);
1302
1281 regions *r = (regions *) ctx->heap.front; 1303 regions *r = (regions *) ctx->heap.front;
1282 1304
1283 uw_check_heap(ctx, sizeof(regions)); 1305 uw_check_heap(ctx, sizeof(regions));
1284 1306
1285 ctx->heap.front += sizeof(regions); 1307 ctx->heap.front += sizeof(regions);
1585 } 1607 }
1586 1608
1587 uw_Basis_source uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) { 1609 uw_Basis_source uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
1588 int len; 1610 int len;
1589 size_t s_len = strlen(s); 1611 size_t s_len = strlen(s);
1612
1613 if(ctx->id < 0)
1614 uw_error(ctx, FATAL, "Attempt to create client source using inappropriate context");
1590 1615
1591 uw_check_script(ctx, 15 + 2 * INTS_MAX + s_len); 1616 uw_check_script(ctx, 15 + 2 * INTS_MAX + s_len);
1592 sprintf(ctx->script.front, "s%d_%llu=sc(exec(%n", ctx->id, ctx->source_count, &len); 1617 sprintf(ctx->script.front, "s%d_%llu=sc(exec(%n", ctx->id, ctx->source_count, &len);
1593 ctx->script.front += len; 1618 ctx->script.front += len;
1594 strcpy(ctx->script.front, s); 1619 strcpy(ctx->script.front, s);
3314 uw_rollback(ctx, 0); 3339 uw_rollback(ctx, 0);
3315 return 0; 3340 return 0;
3316 } 3341 }
3317 } 3342 }
3318 3343
3344 if (ctx->transaction_started) {
3345 int code = ctx->app->db_commit(ctx);
3346
3347 if (code) {
3348 if (ctx->client)
3349 release_client(ctx->client);
3350
3351 if (code == -1) {
3352 // This case is for a serialization failure, which is not really an "error."
3353 // The transaction will restart, so we should rollback any transactionals
3354 // that triggered above.
3355
3356 for (i = ctx->used_transactionals-1; i >= 0; --i)
3357 if (ctx->transactionals[i].rollback != NULL)
3358 ctx->transactionals[i].rollback(ctx->transactionals[i].data);
3359
3360 for (i = ctx->used_transactionals-1; i >= 0; --i)
3361 if (ctx->transactionals[i].free)
3362 ctx->transactionals[i].free(ctx->transactionals[i].data, 1);
3363
3364 return 1;
3365 }
3366
3367 for (i = ctx->used_transactionals-1; i >= 0; --i)
3368 if (ctx->transactionals[i].free)
3369 ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
3370
3371 uw_set_error_message(ctx, "Error running SQL COMMIT");
3372 return 0;
3373 }
3374 }
3375
3319 for (i = ctx->used_transactionals-1; i >= 0; --i) 3376 for (i = ctx->used_transactionals-1; i >= 0; --i)
3320 if (ctx->transactionals[i].rollback == NULL) 3377 if (ctx->transactionals[i].rollback == NULL)
3321 if (ctx->transactionals[i].commit) { 3378 if (ctx->transactionals[i].commit) {
3322 ctx->transactionals[i].commit(ctx->transactionals[i].data); 3379 ctx->transactionals[i].commit(ctx->transactionals[i].data);
3323 if (uw_has_error(ctx)) { 3380 if (uw_has_error(ctx)) {
3324 uw_rollback(ctx, 0); 3381 if (ctx->client)
3382 release_client(ctx->client);
3383
3384 for (i = ctx->used_transactionals-1; i >= 0; --i)
3385 if (ctx->transactionals[i].rollback != NULL)
3386 ctx->transactionals[i].rollback(ctx->transactionals[i].data);
3387
3388 for (i = ctx->used_transactionals-1; i >= 0; --i)
3389 if (ctx->transactionals[i].free)
3390 ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
3391
3325 return 0; 3392 return 0;
3326 } 3393 }
3327 } 3394 }
3328
3329 if (ctx->transaction_started) {
3330 int code = ctx->app->db_commit(ctx);
3331
3332 if (code) {
3333 if (code == -1)
3334 return 1;
3335
3336 for (i = ctx->used_transactionals-1; i >= 0; --i)
3337 if (ctx->transactionals[i].free)
3338 ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
3339
3340 uw_set_error_message(ctx, "Error running SQL COMMIT");
3341 return 0;
3342 }
3343 }
3344 3395
3345 for (i = 0; i < ctx->used_deltas; ++i) { 3396 for (i = 0; i < ctx->used_deltas; ++i) {
3346 delta *d = &ctx->deltas[i]; 3397 delta *d = &ctx->deltas[i];
3347 client *c = find_client(d->client); 3398 client *c = find_client(d->client);
3348 3399
3453 } 3504 }
3454 3505
3455 3506
3456 size_t uw_transactionals_max = SIZE_MAX; 3507 size_t uw_transactionals_max = SIZE_MAX;
3457 3508
3458 void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback, 3509 int uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback,
3459 uw_callback_with_retry free) { 3510 uw_callback_with_retry free) {
3460 if (ctx->used_transactionals >= ctx->n_transactionals) { 3511 if (ctx->used_transactionals >= ctx->n_transactionals) {
3461 if (ctx->used_transactionals+1 > uw_transactionals_max) 3512 if (ctx->used_transactionals+1 > uw_transactionals_max)
3462 uw_error(ctx, FATAL, "Exceeded limit on number of transactionals"); 3513 // Exceeded limit on number of transactionals.
3514 return -1;
3463 ctx->transactionals = realloc(ctx->transactionals, sizeof(transactional) * (ctx->used_transactionals+1)); 3515 ctx->transactionals = realloc(ctx->transactionals, sizeof(transactional) * (ctx->used_transactionals+1));
3464 ++ctx->n_transactionals; 3516 ++ctx->n_transactionals;
3465 } 3517 }
3466 3518
3467 ctx->transactionals[ctx->used_transactionals].data = data; 3519 ctx->transactionals[ctx->used_transactionals].data = data;
3468 ctx->transactionals[ctx->used_transactionals].commit = commit; 3520 ctx->transactionals[ctx->used_transactionals].commit = commit;
3469 ctx->transactionals[ctx->used_transactionals].rollback = rollback; 3521 ctx->transactionals[ctx->used_transactionals].rollback = rollback;
3470 ctx->transactionals[ctx->used_transactionals++].free = free; 3522 ctx->transactionals[ctx->used_transactionals++].free = free;
3523
3524 return 0;
3471 } 3525 }
3472 3526
3473 3527
3474 // "Garbage collection" 3528 // "Garbage collection"
3475 3529
3963 return tm.seconds; 4017 return tm.seconds;
3964 } 4018 }
3965 4019
3966 uw_Basis_time uw_Basis_fromDatetime(uw_context ctx, uw_Basis_int year, uw_Basis_int month, uw_Basis_int day, uw_Basis_int hour, uw_Basis_int minute, uw_Basis_int second) { 4020 uw_Basis_time uw_Basis_fromDatetime(uw_context ctx, uw_Basis_int year, uw_Basis_int month, uw_Basis_int day, uw_Basis_int hour, uw_Basis_int minute, uw_Basis_int second) {
3967 struct tm tm = { .tm_year = year - 1900, .tm_mon = month, .tm_mday = day, 4021 struct tm tm = { .tm_year = year - 1900, .tm_mon = month, .tm_mday = day,
3968 .tm_hour = hour, .tm_min = minute, .tm_sec = second }; 4022 .tm_hour = hour, .tm_min = minute, .tm_sec = second,
4023 .tm_isdst = -1 };
3969 uw_Basis_time r = { timelocal(&tm) }; 4024 uw_Basis_time r = { timelocal(&tm) };
3970 return r; 4025 return r;
3971 } 4026 }
3972 4027
3973 uw_Basis_int uw_Basis_datetimeYear(uw_context ctx, uw_Basis_time time) { 4028 uw_Basis_int uw_Basis_datetimeYear(uw_context ctx, uw_Basis_time time) {
4134 fprintf(stderr, "%s\n", s); 4189 fprintf(stderr, "%s\n", s);
4135 return 0; 4190 return 0;
4136 } 4191 }
4137 4192
4138 uw_Basis_unit uw_Basis_debug(uw_context ctx, uw_Basis_string s) { 4193 uw_Basis_unit uw_Basis_debug(uw_context ctx, uw_Basis_string s) {
4139 if (ctx->log_debug) 4194 if (ctx->loggers->log_debug)
4140 ctx->log_debug(ctx->logger_data, "%s\n", s); 4195 ctx->loggers->log_debug(ctx->loggers->logger_data, "%s\n", s);
4141 else 4196 else
4142 fprintf(stderr, "%s\n", s); 4197 fprintf(stderr, "%s\n", s);
4143 return uw_unit_v; 4198 return uw_unit_v;
4144 } 4199 }
4145 4200
4377 uw_error(ctx, FATAL, "firstFormField: Missing null terminator"); 4432 uw_error(ctx, FATAL, "firstFormField: Missing null terminator");
4378 f->remaining = s+1; 4433 f->remaining = s+1;
4379 4434
4380 return f; 4435 return f;
4381 } 4436 }
4437
4438 uw_Basis_string uw_Basis_blessData(uw_context ctx, uw_Basis_string s) {
4439 char *p = s;
4440
4441 for (; *p; ++p)
4442 if (!isalnum(*p) && *p != '-' && *p != '_')
4443 uw_error(ctx, FATAL, "Illegal HTML5 data-* attribute: %s", s);
4444
4445 return s;
4446 }