diff options
author | Adam Chlipala <adamc@hcoop.net> | 2008-10-24 16:47:18 -0400 |
---|---|---|
committer | Adam Chlipala <adamc@hcoop.net> | 2008-10-24 16:47:18 -0400 |
commit | 6dbd6e0786f8ab1b5b35883dca6695cf58272b5b (patch) | |
tree | e31ecf97ee6f1ea13fec2933c85e987d660e0871 | |
parent | bb640a6174757adb8693d25c831728699e23d68b (diff) |
Transactions seem to be working
-rw-r--r-- | .hgignore | 2 | ||||
-rw-r--r-- | src/c/driver.c | 56 | ||||
-rw-r--r-- | src/cjr_print.sml | 75 | ||||
-rw-r--r-- | tests/aborter.sql | 3 | ||||
-rw-r--r-- | tests/aborter.ur | 5 | ||||
-rw-r--r-- | tests/aborter.urp | 4 |
6 files changed, 144 insertions, 1 deletions
@@ -24,3 +24,5 @@ src/config.sml demo/out/*.html demo/demo.* + +*.sql diff --git a/src/c/driver.c b/src/c/driver.c index 09478270..db982d96 100644 --- a/src/c/driver.c +++ b/src/c/driver.c @@ -51,6 +51,24 @@ static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER; #define MAX_RETRIES 5 +int uw_db_begin(uw_context); +int uw_db_commit(uw_context); +int uw_db_rollback(uw_context); + +static int try_rollback(uw_context ctx) { + int r = uw_db_rollback(ctx); + + if (r) { + printf("Error running SQL ROLLBACK\n"); + uw_reset(ctx); + uw_write(ctx, "HTTP/1.1 500 Internal Server Error\n\r"); + uw_write(ctx, "Content-type: text/plain\r\n\r\n"); + uw_write(ctx, "Error running SQL ROLLBACK\n"); + } + + return r; +} + static void *worker(void *data) { int me = *(int *)data, retries_left = MAX_RETRIES; uw_context ctx = uw_init(1024, 0); @@ -116,6 +134,7 @@ static void *worker(void *data) { *back = 0; if (s = strstr(buf, "\r\n\r\n")) { + failure_kind fk; char *cmd, *path, path_copy[uw_bufsize+1], *inputs; *s = 0; @@ -169,7 +188,20 @@ static void *worker(void *data) { printf("Serving URI %s....\n", path); while (1) { - failure_kind fk; + if (uw_db_begin(ctx)) { + printf("Error running SQL BEGIN\n"); + if (retries_left) + --retries_left; + else { + fk = FATAL; + uw_reset(ctx); + uw_write(ctx, "HTTP/1.1 500 Internal Server Error\n\r"); + uw_write(ctx, "Content-type: text/plain\r\n\r\n"); + uw_write(ctx, "Error running SQL BEGIN\n"); + + break; + } + } uw_write(ctx, "HTTP/1.1 200 OK\r\n"); uw_write(ctx, "Content-type: text/html\r\n\r\n"); @@ -179,6 +211,17 @@ static void *worker(void *data) { fk = uw_begin(ctx, path_copy); if (fk == SUCCESS) { uw_write(ctx, "</html>"); + + if (uw_db_commit(ctx)) { + fk = FATAL; + + printf("Error running SQL COMMIT\n"); + uw_reset(ctx); + uw_write(ctx, "HTTP/1.1 500 Internal Server Error\n\r"); + uw_write(ctx, "Content-type: text/plain\r\n\r\n"); + uw_write(ctx, "Error running SQL COMMIT\n"); + } + break; } else if (fk == BOUNDED_RETRY) { if (retries_left) { @@ -194,6 +237,10 @@ static void *worker(void *data) { uw_write(ctx, "Fatal error (out of retries): "); uw_write(ctx, uw_error_message(ctx)); uw_write(ctx, "\n"); + + try_rollback(ctx); + + break; } } else if (fk == UNLIMITED_RETRY) printf("Error triggers unlimited retry: %s\n", uw_error_message(ctx)); @@ -207,6 +254,8 @@ static void *worker(void *data) { uw_write(ctx, uw_error_message(ctx)); uw_write(ctx, "\n"); + try_rollback(ctx); + break; } else { printf("Unknown uw_handle return code!\n"); @@ -216,10 +265,15 @@ static void *worker(void *data) { uw_write(ctx, "Content-type: text/plain\r\n\r\n"); uw_write(ctx, "Unknown uw_handle return code!\n"); + try_rollback(ctx); + break; } uw_reset_keep_request(ctx); + + if (try_rollback(ctx)) + break; } uw_send(ctx, sock); diff --git a/src/cjr_print.sml b/src/cjr_print.sml index 089f98a1..7d74376e 100644 --- a/src/cjr_print.sml +++ b/src/cjr_print.sml @@ -1268,6 +1268,75 @@ fun p_decl env (dAll as (d, _) : decl) = string "PQfinish(uw_get_db(ctx));", newline, string "}", + newline, + newline, + + string "int uw_db_begin(uw_context ctx) {", + newline, + string "PGconn *conn = uw_get_db(ctx);", + newline, + string "PGresult *res = PQexec(conn, \"BEGIN\");", + newline, + newline, + string "if (res == NULL) return 1;", + newline, + newline, + string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {", + box [string "PQclear(res);", + newline, + string "return 1;", + newline], + string "}", + newline, + string "return 0;", + newline, + string "}", + newline, + newline, + + string "int uw_db_commit(uw_context ctx) {", + newline, + string "PGconn *conn = uw_get_db(ctx);", + newline, + string "PGresult *res = PQexec(conn, \"COMMIT\");", + newline, + newline, + string "if (res == NULL) return 1;", + newline, + newline, + string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {", + box [string "PQclear(res);", + newline, + string "return 1;", + newline], + string "}", + newline, + string "return 0;", + newline, + string "}", + newline, + newline, + + string "int uw_db_rollback(uw_context ctx) {", + newline, + string "PGconn *conn = uw_get_db(ctx);", + newline, + string "PGresult *res = PQexec(conn, \"ROLLBACK\");", + newline, + newline, + string "if (res == NULL) return 1;", + newline, + newline, + string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {", + box [string "PQclear(res);", + newline, + string "return 1;", + newline], + string "}", + newline, + string "return 0;", + newline, + string "}", newline] | DPreparedStatements ss => @@ -2158,6 +2227,12 @@ fun p_file env (ds, ps) = else box [newline, string "void uw_db_init(uw_context ctx) { };", + newline, + string "int uw_db_begin(uw_context ctx) { return 0; };", + newline, + string "int uw_db_commit(uw_context ctx) { return 0; };", + newline, + string "int uw_db_rollback(uw_context ctx) { return 0; };", newline]] end diff --git a/tests/aborter.sql b/tests/aborter.sql new file mode 100644 index 00000000..ab6110fc --- /dev/null +++ b/tests/aborter.sql @@ -0,0 +1,3 @@ +CREATE TABLE uw_Aborter_t(uw_a int8 NOT NULL); + +
\ No newline at end of file diff --git a/tests/aborter.ur b/tests/aborter.ur new file mode 100644 index 00000000..0921bdfc --- /dev/null +++ b/tests/aborter.ur @@ -0,0 +1,5 @@ +table t : {A : int} + +fun main () : transaction page = + () <- dml (INSERT INTO t (A) VALUES (0)); + return (error <xml>No way, Jose!</xml>) diff --git a/tests/aborter.urp b/tests/aborter.urp new file mode 100644 index 00000000..fc1925ae --- /dev/null +++ b/tests/aborter.urp @@ -0,0 +1,4 @@ +database dbname=aborter +sql aborter.sql + +aborter |