summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adam@chlipala.net>2013-12-11 14:57:54 -0500
committerGravatar Adam Chlipala <adam@chlipala.net>2013-12-11 14:57:54 -0500
commita8459c0104ca36fd058ea527890116c7a1bca8fd (patch)
tree00c51911af9b45c7c29ef1ba89f02a3d49f0fd69
parenta22814f0ea7501eba5dc86413ba9851e97deed2e (diff)
Fix regression in http.c for long-polling connections; add lazy initialization of database connections, to avoid the overhead in handlers that don't use SQL
-rw-r--r--include/urweb/urweb_cpp.h1
-rw-r--r--src/c/http.c4
-rw-r--r--src/c/urweb.c24
-rw-r--r--src/cjr_print.sml12
4 files changed, 32 insertions, 9 deletions
diff --git a/include/urweb/urweb_cpp.h b/include/urweb/urweb_cpp.h
index 4779b95a..fb3c83a2 100644
--- a/include/urweb/urweb_cpp.h
+++ b/include/urweb/urweb_cpp.h
@@ -37,6 +37,7 @@ void uw_set_on_success(char *);
void uw_set_headers(struct uw_context *, char *(*get_header)(void *, const char *), void *get_header_data);
void uw_set_env(struct uw_context *, char *(*get_env)(void *, const char *), void *get_env_data);
failure_kind uw_begin(struct uw_context *, char *path);
+void uw_ensure_transaction(struct uw_context *);
failure_kind uw_begin_onError(struct uw_context *, char *msg);
void uw_login(struct uw_context *);
void uw_commit(struct uw_context *);
diff --git a/src/c/http.c b/src/c/http.c
index 5ceca059..d19ce350 100644
--- a/src/c/http.c
+++ b/src/c/http.c
@@ -260,7 +260,9 @@ static void *worker(void *data) {
close(sock);
sock = 0;
}
- } else if (rr != KEEP_OPEN)
+ } else if (rr == KEEP_OPEN)
+ sock = 0;
+ else
fprintf(stderr, "Illegal uw_request return code: %d\n", rr);
break;
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 8bd5ada9..cd724cbf 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -431,6 +431,7 @@ struct uw_context {
unsigned long long source_count;
void *db;
+ int transaction_started;
jmp_buf jmp_buf;
@@ -507,6 +508,7 @@ uw_context uw_init(int id, void *logger_data, uw_logger log_debug) {
ctx->sz_inputs = ctx->n_subinputs = ctx->used_subinputs = 0;
ctx->db = NULL;
+ ctx->transaction_started = 0;
ctx->regions = NULL;
@@ -631,6 +633,7 @@ void uw_reset_keep_error_message(uw_context ctx) {
ctx->amInitializing = 0;
ctx->usedSig = 0;
ctx->needsResig = 0;
+ ctx->transaction_started = 0;
}
void uw_reset_keep_request(uw_context ctx) {
@@ -766,16 +769,20 @@ void uw_login(uw_context ctx) {
failure_kind uw_begin(uw_context ctx, char *path) {
int r = setjmp(ctx->jmp_buf);
- if (r == 0) {
- if (ctx->app->db_begin(ctx))
- uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN");
-
+ if (r == 0)
ctx->app->handle(ctx, path);
- }
return r;
}
+void uw_ensure_transaction(uw_context ctx) {
+ if (!ctx->transaction_started) {
+ if (ctx->app->db_begin(ctx))
+ uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN");
+ ctx->transaction_started = 1;
+ }
+}
+
uw_Basis_client uw_Basis_self(uw_context ctx) {
if (ctx->client == NULL)
uw_error(ctx, FATAL, "Call to Basis.self() from page that has only server-side code");
@@ -3205,7 +3212,7 @@ int uw_rollback(uw_context ctx, int will_retry) {
if (ctx->transactionals[i].free)
ctx->transactionals[i].free(ctx->transactionals[i].data, will_retry);
- return ctx->app ? ctx->app->db_rollback(ctx) : 0;
+ return (ctx->app && ctx->transaction_started) ? ctx->app->db_rollback(ctx) : 0;
}
static const char begin_xhtml[] = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">";
@@ -3262,7 +3269,7 @@ void uw_commit(uw_context ctx) {
}
}
- if (ctx->app->db_commit(ctx)) {
+ if (ctx->transaction_started && ctx->app->db_commit(ctx)) {
uw_set_error_message(ctx, "Error running SQL COMMIT");
return;
}
@@ -3453,6 +3460,7 @@ failure_kind uw_initialize(uw_context ctx) {
if (r == 0) {
if (ctx->app->db_begin(ctx))
uw_error(ctx, FATAL, "Error running SQL BEGIN");
+ ctx->transaction_started = 1;
ctx->app->initializer(ctx);
if (ctx->app->db_commit(ctx))
uw_error(ctx, FATAL, "Error running SQL COMMIT");
@@ -4037,6 +4045,7 @@ failure_kind uw_runCallback(uw_context ctx, void (*callback)(uw_context)) {
if (r == 0) {
if (ctx->app->db_begin(ctx))
uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN");
+ ctx->transaction_started = 1;
callback(ctx);
}
@@ -4085,6 +4094,7 @@ failure_kind uw_begin_onError(uw_context ctx, char *msg) {
if (r == 0) {
if (ctx->app->db_begin(ctx))
uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN");
+ ctx->transaction_started = 1;
uw_buffer_reset(&ctx->outHeaders);
if (on_success[0])
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index bc8f1be6..e98918e6 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -2079,6 +2079,8 @@ and p_exp' par tail env (e, loc) =
newline,
string "int dummy = (uw_begin_region(ctx), 0);",
newline,
+ string "uw_ensure_transaction(ctx);",
+ newline,
case prepared of
NONE =>
@@ -2140,6 +2142,8 @@ and p_exp' par tail env (e, loc) =
p_exp' false false env dml,
string ";",
newline,
+ string "uw_ensure_transaction(ctx);",
+ newline,
newline,
#dml (Settings.currentDbms ()) (loc, mode)]
| SOME {id, dml = dml'} =>
@@ -2159,8 +2163,10 @@ and p_exp' par tail env (e, loc) =
string ";"])
inputs,
newline,
+ string "uw_ensure_transaction(ctx);",
newline,
-
+ newline,
+
#dmlPrepared (Settings.currentDbms ()) {loc = loc,
id = id,
dml = dml',
@@ -2184,6 +2190,8 @@ and p_exp' par tail env (e, loc) =
newline,
string "uw_Basis_int n;",
newline,
+ string "uw_ensure_transaction(ctx);",
+ newline,
case prepared of
NONE => #nextval (Settings.currentDbms ()) {loc = loc,
@@ -2204,6 +2212,8 @@ and p_exp' par tail env (e, loc) =
| ESetval {seq, count} =>
box [string "({",
newline,
+ string "uw_ensure_transaction(ctx);",
+ newline,
#setval (Settings.currentDbms ()) {loc = loc,
seqE = p_exp' false false env seq,