Mercurial > urweb
comparison src/c/urweb.c @ 771:eac1974924bb
FFI transactionals
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 02 May 2009 18:41:21 -0400 |
parents | c125df6fabfc |
children | 8ed1261f838c |
comparison
equal
deleted
inserted
replaced
770:c125df6fabfc | 771:eac1974924bb |
---|---|
302 struct input *fields, *next, *parent; | 302 struct input *fields, *next, *parent; |
303 } entry; | 303 } entry; |
304 } data; | 304 } data; |
305 } input; | 305 } input; |
306 | 306 |
307 typedef struct { | |
308 void *data; | |
309 uw_callback commit, rollback, free; | |
310 } transactional; | |
311 | |
307 struct uw_context { | 312 struct uw_context { |
308 char *headers, *headers_end; | 313 char *headers, *headers_end; |
309 | 314 |
310 buf outHeaders, page, heap, script; | 315 buf outHeaders, page, heap, script; |
311 input *inputs, *subinputs, *cur_container; | 316 input *inputs, *subinputs, *cur_container; |
329 delta *deltas; | 334 delta *deltas; |
330 | 335 |
331 int timeout; | 336 int timeout; |
332 | 337 |
333 client *client; | 338 client *client; |
339 | |
340 transactional *transactionals; | |
341 size_t n_transactionals, used_transactionals; | |
334 | 342 |
335 char error_message[ERROR_BUF_LEN]; | 343 char error_message[ERROR_BUF_LEN]; |
336 }; | 344 }; |
337 | 345 |
338 extern int uw_inputs_len, uw_timeout; | 346 extern int uw_inputs_len, uw_timeout; |
374 ctx->timeout = uw_timeout; | 382 ctx->timeout = uw_timeout; |
375 | 383 |
376 ctx->client = NULL; | 384 ctx->client = NULL; |
377 | 385 |
378 ctx->error_message[0] = 0; | 386 ctx->error_message[0] = 0; |
387 | |
388 ctx->transactionals = malloc(0); | |
389 ctx->n_transactionals = ctx->used_transactionals = 0; | |
379 | 390 |
380 return ctx; | 391 return ctx; |
381 } | 392 } |
382 | 393 |
383 void uw_set_db(uw_context ctx, void *db) { | 394 void uw_set_db(uw_context ctx, void *db) { |
396 buf_free(&ctx->page); | 407 buf_free(&ctx->page); |
397 buf_free(&ctx->heap); | 408 buf_free(&ctx->heap); |
398 free(ctx->inputs); | 409 free(ctx->inputs); |
399 free(ctx->subinputs); | 410 free(ctx->subinputs); |
400 free(ctx->cleanup); | 411 free(ctx->cleanup); |
412 free(ctx->transactionals); | |
401 | 413 |
402 for (i = 0; i < ctx->n_deltas; ++i) | 414 for (i = 0; i < ctx->n_deltas; ++i) |
403 buf_free(&ctx->deltas[i].msgs); | 415 buf_free(&ctx->deltas[i].msgs); |
404 | 416 |
405 free(ctx); | 417 free(ctx); |
417 ctx->cleanup_front = ctx->cleanup; | 429 ctx->cleanup_front = ctx->cleanup; |
418 ctx->source_count = 0; | 430 ctx->source_count = 0; |
419 ctx->used_deltas = 0; | 431 ctx->used_deltas = 0; |
420 ctx->client = NULL; | 432 ctx->client = NULL; |
421 ctx->cur_container = NULL; | 433 ctx->cur_container = NULL; |
434 ctx->used_transactionals = 0; | |
422 } | 435 } |
423 | 436 |
424 void uw_reset_keep_request(uw_context ctx) { | 437 void uw_reset_keep_request(uw_context ctx) { |
425 uw_reset_keep_error_message(ctx); | 438 uw_reset_keep_error_message(ctx); |
426 ctx->error_message[0] = 0; | 439 ctx->error_message[0] = 0; |
2337 int uw_db_rollback(uw_context); | 2350 int uw_db_rollback(uw_context); |
2338 | 2351 |
2339 void uw_commit(uw_context ctx) { | 2352 void uw_commit(uw_context ctx) { |
2340 unsigned i; | 2353 unsigned i; |
2341 | 2354 |
2342 if (uw_db_commit(ctx)) | 2355 for (i = 0; i < ctx->used_transactionals; ++i) |
2356 if (ctx->transactionals[i].rollback != NULL) | |
2357 ctx->transactionals[i].commit(ctx->transactionals[i].data); | |
2358 | |
2359 for (i = 0; i < ctx->used_transactionals; ++i) | |
2360 if (ctx->transactionals[i].rollback == NULL) | |
2361 ctx->transactionals[i].commit(ctx->transactionals[i].data); | |
2362 | |
2363 if (uw_db_commit(ctx)) | |
2343 uw_error(ctx, FATAL, "Error running SQL COMMIT"); | 2364 uw_error(ctx, FATAL, "Error running SQL COMMIT"); |
2344 | 2365 |
2345 for (i = 0; i < ctx->used_deltas; ++i) { | 2366 for (i = 0; i < ctx->used_deltas; ++i) { |
2346 delta *d = &ctx->deltas[i]; | 2367 delta *d = &ctx->deltas[i]; |
2347 client *c = find_client(d->client); | 2368 client *c = find_client(d->client); |
2351 client_send(c, &d->msgs); | 2372 client_send(c, &d->msgs); |
2352 } | 2373 } |
2353 | 2374 |
2354 if (ctx->client) | 2375 if (ctx->client) |
2355 release_client(ctx->client); | 2376 release_client(ctx->client); |
2377 | |
2378 for (i = 0; i < ctx->used_transactionals; ++i) | |
2379 ctx->transactionals[i].free(ctx->transactionals[i].data); | |
2356 } | 2380 } |
2357 | 2381 |
2358 int uw_rollback(uw_context ctx) { | 2382 int uw_rollback(uw_context ctx) { |
2383 size_t i; | |
2384 | |
2359 if (ctx->client) | 2385 if (ctx->client) |
2360 release_client(ctx->client); | 2386 release_client(ctx->client); |
2361 | 2387 |
2388 for (i = 0; i < ctx->used_transactionals; ++i) | |
2389 if (ctx->transactionals[i].rollback != NULL) | |
2390 ctx->transactionals[i].rollback(ctx->transactionals[i].data); | |
2391 | |
2392 for (i = 0; i < ctx->used_transactionals; ++i) | |
2393 ctx->transactionals[i].free(ctx->transactionals[i].data); | |
2394 | |
2362 return uw_db_rollback(ctx); | 2395 return uw_db_rollback(ctx); |
2396 } | |
2397 | |
2398 void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback, | |
2399 uw_callback free) { | |
2400 if (commit == NULL) | |
2401 uw_error(ctx, FATAL, "uw_register_transactional: NULL commit callback"); | |
2402 | |
2403 if (ctx->used_transactionals >= ctx->n_transactionals) { | |
2404 ctx->transactionals = realloc(ctx->transactionals, ctx->used_transactionals+1); | |
2405 ++ctx->n_transactionals; | |
2406 } | |
2407 | |
2408 ctx->transactionals[ctx->used_transactionals].data = data; | |
2409 ctx->transactionals[ctx->used_transactionals].commit = commit; | |
2410 ctx->transactionals[ctx->used_transactionals].rollback = rollback; | |
2411 ctx->transactionals[ctx->used_transactionals++].free = free; | |
2363 } | 2412 } |
2364 | 2413 |
2365 | 2414 |
2366 // "Garbage collection" | 2415 // "Garbage collection" |
2367 | 2416 |