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