# HG changeset patch # User Adam Chlipala # Date 1220371045 14400 # Node ID 4d80d6122df1dae4b98c2ee133f3e73b9847bba7 # Parent 42dfb0d61cf06714ccfd542a72f12367fa2d9d44 Initializing database connection diff -r 42dfb0d61cf0 -r 4d80d6122df1 include/urweb.h --- a/include/urweb.h Tue Sep 02 10:51:41 2008 -0400 +++ b/include/urweb.h Tue Sep 02 11:57:25 2008 -0400 @@ -7,10 +7,14 @@ extern lw_unit lw_unit_v; lw_context lw_init(size_t page_len, size_t heap_len); +void lw_set_db(lw_context, void*); +void *lw_get_db(lw_context); void lw_free(lw_context); void lw_reset(lw_context); void lw_reset_keep_request(lw_context); void lw_reset_keep_error_message(lw_context); + +failure_kind lw_begin_init(lw_context); failure_kind lw_begin(lw_context, char *path); void lw_error(lw_context, failure_kind, const char *fmt, ...); diff -r 42dfb0d61cf0 -r 4d80d6122df1 src/c/driver.c --- a/src/c/driver.c Tue Sep 02 10:51:41 2008 -0400 +++ b/src/c/driver.c Tue Sep 02 11:57:25 2008 -0400 @@ -52,8 +52,37 @@ #define MAX_RETRIES 5 static void *worker(void *data) { - int me = *(int *)data; + int me = *(int *)data, retries_left = MAX_RETRIES;; lw_context ctx = lw_init(1024, 1024); + + while (1) { + failure_kind fk = lw_begin_init(ctx); + + if (fk == SUCCESS) { + lw_db_init(ctx); + printf("Database connection initialized.\n"); + break; + } else if (fk == BOUNDED_RETRY) { + if (retries_left) { + printf("Initialization error triggers bounded retry: %s\n", lw_error_message(ctx)); + --retries_left; + } else { + printf("Fatal initialization error (out of retries): %s\n", lw_error_message(ctx)); + lw_free(ctx); + return NULL; + } + } else if (fk == UNLIMITED_RETRY) + printf("Initialization error triggers unlimited retry: %s\n", lw_error_message(ctx)); + else if (fk == FATAL) { + printf("Fatal initialization error: %s\n", lw_error_message(ctx)); + lw_free(ctx); + return NULL; + } else { + printf("Unknown lw_handle return code!\n"); + lw_free(ctx); + return NULL; + } + } while (1) { char buf[lw_bufsize+1], *back = buf, *s; diff -r 42dfb0d61cf0 -r 4d80d6122df1 src/c/urweb.c --- a/src/c/urweb.c Tue Sep 02 10:51:41 2008 -0400 +++ b/src/c/urweb.c Tue Sep 02 11:57:25 2008 -0400 @@ -16,6 +16,8 @@ char *heap, *heap_front, *heap_back; char **inputs; + void *db; + jmp_buf jmp_buf; char error_message[ERROR_BUF_LEN]; @@ -34,11 +36,21 @@ ctx->inputs = calloc(lw_inputs_len, sizeof(char *)); + ctx->db = NULL; + ctx->error_message[0] = 0; return ctx; } +void lw_set_db(lw_context ctx, void *db) { + ctx->db = db; +} + +void *lw_get_db(lw_context ctx) { + return ctx->db; +} + void lw_free(lw_context ctx) { free(ctx->page); free(ctx->heap); @@ -63,8 +75,18 @@ memset(ctx->inputs, 0, lw_inputs_len * sizeof(char *)); } +void lw_db_init(lw_context); void lw_handle(lw_context, char *); +failure_kind lw_begin_init(lw_context ctx) { + int r = setjmp(ctx->jmp_buf); + + if (r == 0) + lw_db_init(ctx); + + return r; +} + failure_kind lw_begin(lw_context ctx, char *path) { int r = setjmp(ctx->jmp_buf); diff -r 42dfb0d61cf0 -r 4d80d6122df1 src/cjr_print.sml --- a/src/cjr_print.sml Tue Sep 02 10:51:41 2008 -0400 +++ b/src/cjr_print.sml Tue Sep 02 11:57:25 2008 -0400 @@ -533,7 +533,10 @@ newline, p_typ env t, space, - p_rel env 0, + string "__lwr_", + string x, + string "_", + string (Int.toString (E.countERels env)), space, string "=", space, @@ -546,31 +549,7 @@ string "})"] | EQuery {exps, tables, rnum, state, query, body, initial} => - box [string "query[", - p_list (fn (x, t) => box [string x, space, string ":", space, p_typ env t]) exps, - string "] [", - p_list (fn (x, xts) => box [string x, - space, - string ":", - space, - string "{", - p_list (fn (x, t) => box [string x, space, string ":", space, p_typ env t]) xts, - string "}"]) tables, - string "] [", - p_typ env state, - string "] [", - string (Int.toString rnum), - string "]", - space, - p_exp env query, - space, - string "initial", - space, - p_exp env initial, - space, - string "in", - space, - p_exp (E.pushERel (E.pushERel env "r" dummyt) "acc" dummyt) body] + string "(lw_error(ctx, FATAL, \"I would have run a query.\"), NULL)" and p_exp env = p_exp' false env @@ -709,9 +688,41 @@ p_list_sep newline (p_fun env) vis, newline] end - | DDatabase s => box [string "database", - space, - string s] + | DDatabase s => box [string "void lw_db_init(lw_context ctx) {", + newline, + string "PGconn *conn = PQconnectdb(\"", + string (String.toString s), + string "\");", + newline, + string "if (conn == NULL) lw_error(ctx, BOUNDED_RETRY, ", + string "\"libpq can't allocate a connection.\");", + newline, + string "if (PQstatus(conn) != CONNECTION_OK) {", + newline, + box [string "char msg[1024];", + newline, + string "strncpy(msg, PQerrorMessage(conn), 1024);", + newline, + string "msg[1023] = 0;", + newline, + string "PQfinish(conn);", + newline, + string "lw_error(ctx, BOUNDED_RETRY, ", + string "\"Connection to Postgres server failed: %s\", msg);"], + newline, + string "}", + newline, + string "lw_set_db(ctx, conn);", + newline, + string "}", + newline, + newline, + string "void lw_db_close(lw_context ctx) {", + newline, + string "PQfinish(lw_get_db(ctx));", + newline, + string "}", + newline] datatype 'a search = Found of 'a @@ -1172,7 +1183,9 @@ string "(", p_list_sep (box [string ",", space]) (fn x => x) - (string "ctx" :: ListUtil.mapi (fn (i, _) => string ("arg" ^ Int.toString i)) ts), + (string "ctx" + :: ListUtil.mapi (fn (i, _) => string ("arg" ^ Int.toString i)) ts + @ [string "lw_unit_v"]), inputsVar, string ");", newline, @@ -1190,6 +1203,10 @@ newline, string "#include ", newline, + string "#include ", + newline, + string "#include ", + newline, newline, string "#include \"urweb.h\"", newline, diff -r 42dfb0d61cf0 -r 4d80d6122df1 src/compiler.sml --- a/src/compiler.sml Tue Sep 02 10:51:41 2008 -0400 +++ b/src/compiler.sml Tue Sep 02 11:57:25 2008 -0400 @@ -417,7 +417,7 @@ fun compileC {cname, oname, ename} = let val compile = "gcc -O3 -I include -c " ^ cname ^ " -o " ^ oname - val link = "gcc -pthread -O3 clib/urweb.o " ^ oname ^ " clib/driver.o -o " ^ ename + val link = "gcc -O3 -pthread -lpq clib/urweb.o " ^ oname ^ " clib/driver.o -o " ^ ename in if not (OS.Process.isSuccess (OS.Process.system compile)) then print "C compilation failed\n"