diff options
author | Adam Chlipala <adamc@hcoop.net> | 2009-12-27 10:37:24 -0500 |
---|---|---|
committer | Adam Chlipala <adamc@hcoop.net> | 2009-12-27 10:37:24 -0500 |
commit | 129b1c431efebc77a7a0046c725380ba29b814cf (patch) | |
tree | 860e97379bc9422f4f7bd8fade58f9752afd92d9 | |
parent | c4120c8ddaa5340efad5f835ce4565f2a8ae2cbf (diff) |
All three current protocols work with move to using uw_app
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | include/request.h | 5 | ||||
-rw-r--r-- | include/types.h | 22 | ||||
-rw-r--r-- | include/urweb.h | 3 | ||||
-rw-r--r-- | src/c/cgi.c | 7 | ||||
-rw-r--r-- | src/c/fastcgi.c | 9 | ||||
-rw-r--r-- | src/c/http.c | 8 | ||||
-rw-r--r-- | src/c/request.c | 22 | ||||
-rw-r--r-- | src/c/urweb.c | 145 | ||||
-rw-r--r-- | src/cjr_print.sml | 50 | ||||
-rw-r--r-- | src/compiler.sml | 2 | ||||
-rw-r--r-- | src/mysql.sml | 12 | ||||
-rw-r--r-- | src/postgres.sml | 196 | ||||
-rw-r--r-- | src/sqlite.sml | 12 |
14 files changed, 257 insertions, 238 deletions
diff --git a/Makefile.in b/Makefile.in index 0d8b998a..ac72bb04 100644 --- a/Makefile.in +++ b/Makefile.in @@ -24,7 +24,7 @@ clean: rm -rf .cm src/.cm lib/c/%.o: src/c/%.c include/*.h - gcc -O3 -I include -c $< -o $@ $(CFLAGS) + gcc -Wimplicit -O3 -I include -c $< -o $@ $(CFLAGS) src/urweb.cm: src/prefix.cm src/sources cat src/prefix.cm src/sources \ diff --git a/include/request.h b/include/request.h index 73ee0468..d2385af7 100644 --- a/include/request.h +++ b/include/request.h @@ -7,7 +7,7 @@ typedef struct uw_rc *uw_request_context; -void uw_request_init(void *logger_data, uw_logger log_error, uw_logger log_debug); +void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug); void uw_sign(const char *in, char *out); uw_request_context uw_new_request_context(void); @@ -22,9 +22,10 @@ request_result uw_request(uw_request_context, uw_context, int (*send)(int sockfd, const void *buf, ssize_t len), int (*close)(int fd)); -uw_context uw_request_new_context(void *logger_data, uw_logger log_error, uw_logger log_debug); +uw_context uw_request_new_context(uw_app*, void *logger_data, uw_logger log_error, uw_logger log_debug); typedef struct { + uw_app *app; void *logger_data; uw_logger log_error, log_debug; } loggers; diff --git a/include/types.h b/include/types.h index 767b2345..1c52d460 100644 --- a/include/types.h +++ b/include/types.h @@ -52,4 +52,26 @@ typedef struct input *uw_input; typedef void (*uw_callback)(void *); typedef void (*uw_logger)(void*, const char *fmt, ...); +typedef struct { + int inputs_len, timeout; + char *url_prefix; + + void (*client_init)(); + void (*initializer)(uw_context); + void (*expunger)(uw_context, uw_Basis_client); + + void (*db_init)(uw_context); + int (*db_begin)(uw_context); + int (*db_commit)(uw_context); + int (*db_rollback)(uw_context); + void (*db_close)(uw_context); + + void (*handle)(uw_context, char *); + + int (*input_num)(const char*); + uw_Basis_string (*cookie_sig)(uw_context); + int (*check_url)(const char *); + int (*check_mime)(const char *); +} uw_app; + #endif diff --git a/include/urweb.h b/include/urweb.h index 69e94c9b..8d182978 100644 --- a/include/urweb.h +++ b/include/urweb.h @@ -11,6 +11,7 @@ int uw_really_write(int fd, const void *buf, size_t len); extern uw_unit uw_unit_v; void uw_global_init(void); +void uw_app_init(uw_app*); void uw_client_connect(unsigned id, int pass, int sock, int (*send)(int sockfd, const void *buf, size_t len), @@ -20,12 +21,14 @@ void uw_prune_clients(uw_context); failure_kind uw_initialize(uw_context); uw_context uw_init(void); +void uw_set_app(uw_context, uw_app*); void uw_set_db(uw_context, void*); void *uw_get_db(uw_context); void uw_free(uw_context); void uw_reset(uw_context); void uw_reset_keep_request(uw_context); void uw_reset_keep_error_message(uw_context); +const char *uw_get_url_prefix(uw_context); failure_kind uw_begin_init(uw_context); void uw_set_on_success(char *); diff --git a/src/c/cgi.c b/src/c/cgi.c index 38cb7da4..1d7d9810 100644 --- a/src/c/cgi.c +++ b/src/c/cgi.c @@ -5,8 +5,11 @@ #include <unistd.h> #include <stdarg.h> +#include "urweb.h" #include "request.h" +extern uw_app uw_application; + static char *uppercased; static size_t uppercased_len; @@ -51,7 +54,7 @@ static void log_debug(void *data, const char *fmt, ...) { } int main(int argc, char *argv[]) { - uw_context ctx = uw_request_new_context(NULL, log_error, log_debug); + uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug); uw_request_context rc = uw_new_request_context(); request_result rr; char *method = getenv("REQUEST_METHOD"), @@ -97,7 +100,7 @@ int main(int argc, char *argv[]) { uw_set_on_success(""); uw_set_headers(ctx, get_header, NULL); - uw_request_init(NULL, log_error, log_debug); + uw_request_init(&uw_application, NULL, log_error, log_debug); body[body_pos] = 0; rr = uw_request(rc, ctx, method, path, query_string, body, body_pos, diff --git a/src/c/fastcgi.c b/src/c/fastcgi.c index 1a8a8316..b6b6e9a8 100644 --- a/src/c/fastcgi.c +++ b/src/c/fastcgi.c @@ -10,6 +10,7 @@ #include <unistd.h> #include <signal.h> #include <stdarg.h> +#include <ctype.h> #include <pthread.h> @@ -19,6 +20,8 @@ #include "fastcgi.h" +extern uw_app uw_application; + typedef struct { unsigned char version; unsigned char type; @@ -300,7 +303,7 @@ static void *worker(void *data) { int me = *(int *)data; FCGI_Input *in = fastcgi_input(); FCGI_Output *out = fastcgi_output(); - uw_context ctx = uw_request_new_context(out, log_error, log_debug); + uw_context ctx = uw_request_new_context(&uw_application, out, log_error, log_debug); uw_request_context rc = uw_new_request_context(); headers hs; size_t body_size = 0; @@ -489,7 +492,7 @@ static void sigint(int signum) { exit(0); } -static loggers ls = {NULL, log_error, log_debug}; +static loggers ls = {&uw_application, NULL, log_error, log_debug}; int main(int argc, char *argv[]) { // The skeleton for this function comes from Beej's sockets tutorial. @@ -538,7 +541,7 @@ int main(int argc, char *argv[]) { } uw_set_on_success(""); - uw_request_init(NULL, log_error, log_debug); + uw_request_init(&uw_application, NULL, log_error, log_debug); names = calloc(nthreads, sizeof(int)); diff --git a/src/c/http.c b/src/c/http.c index 9550bd4f..70001961 100644 --- a/src/c/http.c +++ b/src/c/http.c @@ -16,6 +16,8 @@ #include "request.h" #include "queue.h" +extern uw_app uw_application; + int uw_backlog = 10; static char *get_header(void *data, const char *h) { @@ -61,7 +63,7 @@ static void log_debug(void *data, const char *fmt, ...) { static void *worker(void *data) { int me = *(int *)data; - uw_context ctx = uw_request_new_context(NULL, log_error, log_debug); + uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug); size_t buf_size = 2; char *buf = malloc(buf_size); uw_request_context rc = uw_new_request_context(); @@ -214,7 +216,7 @@ static void sigint(int signum) { exit(0); } -static loggers ls = {NULL, log_error, log_debug}; +static loggers ls = {&uw_application, NULL, log_error, log_debug}; int main(int argc, char *argv[]) { // The skeleton for this function comes from Beej's sockets tutorial. @@ -262,7 +264,7 @@ int main(int argc, char *argv[]) { } } - uw_request_init(NULL, log_error, log_debug); + uw_request_init(&uw_application, NULL, log_error, log_debug); names = calloc(nthreads, sizeof(int)); diff --git a/src/c/request.c b/src/c/request.c index a314bb19..5c8159cc 100644 --- a/src/c/request.c +++ b/src/c/request.c @@ -31,9 +31,10 @@ static int try_rollback(uw_context ctx, void *logger_data, uw_logger log_error) return r; } -uw_context uw_request_new_context(void *logger_data, uw_logger log_error, uw_logger log_debug) { +uw_context uw_request_new_context(uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) { uw_context ctx = uw_init(); int retries_left = MAX_RETRIES; + uw_set_app(ctx, app); while (1) { failure_kind fk = uw_begin_init(ctx); @@ -95,26 +96,27 @@ static void init_crypto(void *logger_data, uw_logger log_error) { } } -void uw_request_init(void *logger_data, uw_logger log_error, uw_logger log_debug) { +void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) { uw_context ctx; failure_kind fk; uw_global_init(); + uw_app_init(app); - ctx = uw_request_new_context(logger_data, log_error, log_debug); + ctx = uw_request_new_context(app, logger_data, log_error, log_debug); if (!ctx) exit(1); for (fk = uw_initialize(ctx); fk == UNLIMITED_RETRY; fk = uw_initialize(ctx)) { log_debug(logger_data, "Unlimited retry during init: %s\n", uw_error_message(ctx)); - uw_db_rollback(ctx); + uw_rollback(ctx); uw_reset(ctx); } if (fk != SUCCESS) { log_error(logger_data, "Failed to initialize database! %s\n", uw_error_message(ctx)); - uw_db_rollback(ctx); + uw_rollback(ctx); exit(1); } @@ -151,8 +153,6 @@ void uw_free_request_context(uw_request_context r) { free(r); } -extern char *uw_url_prefix; - request_result uw_request(uw_request_context rc, uw_context ctx, char *method, char *path, char *query_string, char *body, size_t body_len, @@ -168,6 +168,7 @@ request_result uw_request(uw_request_context rc, uw_context ctx, char *boundary = NULL; size_t boundary_len; char *inputs; + const char *prefix = uw_get_url_prefix(ctx); uw_set_currentUrl(ctx, path); @@ -208,8 +209,8 @@ request_result uw_request(uw_request_context rc, uw_context ctx, return FAILED; } - if (!strncmp(path, uw_url_prefix, strlen(uw_url_prefix)) - && !strcmp(path + strlen(uw_url_prefix), ".msgs")) { + if (!strncmp(path, prefix, strlen(prefix)) + && !strcmp(path + strlen(prefix), ".msgs")) { char *id = uw_Basis_requestHeader(ctx, "UrWeb-Client"); char *pass = uw_Basis_requestHeader(ctx, "UrWeb-Pass"); @@ -435,13 +436,14 @@ request_result uw_request(uw_request_context rc, uw_context ctx, } typedef struct { + uw_app *app; void *logger_data; uw_logger log_error, log_debug; } loggers; void *client_pruner(void *data) { loggers *ls = (loggers *)data; - uw_context ctx = uw_request_new_context(ls->logger_data, ls->log_error, ls->log_debug); + uw_context ctx = uw_request_new_context(ls->app, ls->logger_data, ls->log_error, ls->log_debug); if (!ctx) exit(1); diff --git a/src/c/urweb.c b/src/c/urweb.c index 4a0306e0..455b3e1e 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 600 #include <stdlib.h> #include <stdio.h> @@ -9,6 +9,8 @@ #include <stdarg.h> #include <assert.h> #include <ctype.h> +#include <sys/types.h> +#include <sys/socket.h> #include <pthread.h> @@ -287,14 +289,14 @@ static void client_send(client *c, buf *msg) { // Global entry points -extern void uw_client_init(); - void uw_global_init() { srand(time(NULL) ^ getpid()); clients = malloc(0); +} - uw_client_init(); +void uw_app_init(uw_app *app) { + app->client_init(); } @@ -349,13 +351,15 @@ typedef struct { } global; struct uw_context { + uw_app *app; + char *(*get_header)(void *, const char *); void *get_header_data; buf outHeaders, page, heap, script; int returning_indirectly; input *inputs, *subinputs, *cur_container; - size_t n_subinputs, used_subinputs; + size_t sz_inputs, n_subinputs, used_subinputs; int source_count; @@ -367,15 +371,13 @@ struct uw_context { cleanup *cleanup, *cleanup_front, *cleanup_back; - const char *script_header, *url_prefix; + const char *script_header; int needs_push, needs_sig; size_t n_deltas, used_deltas; delta *deltas; - int timeout; - client *client; transactional *transactionals; @@ -389,11 +391,11 @@ struct uw_context { char error_message[ERROR_BUF_LEN]; }; -extern int uw_inputs_len, uw_timeout; - uw_context uw_init() { uw_context ctx = malloc(sizeof(struct uw_context)); + ctx->app = NULL; + ctx->get_header = NULL; ctx->get_header_data = NULL; @@ -404,10 +406,10 @@ uw_context uw_init() { buf_init(&ctx->script, 1); ctx->script.start[0] = 0; - ctx->inputs = calloc(uw_inputs_len, sizeof(input)); + ctx->inputs = malloc(0); ctx->cur_container = NULL; ctx->subinputs = malloc(0); - ctx->n_subinputs = ctx->used_subinputs = 0; + ctx->sz_inputs = ctx->n_subinputs = ctx->used_subinputs = 0; ctx->db = NULL; @@ -416,7 +418,6 @@ uw_context uw_init() { ctx->cleanup_front = ctx->cleanup_back = ctx->cleanup = malloc(0); ctx->script_header = ""; - ctx->url_prefix = "/"; ctx->needs_push = 0; ctx->needs_sig = 0; @@ -427,8 +428,6 @@ uw_context uw_init() { ctx->n_deltas = ctx->used_deltas = 0; ctx->deltas = malloc(0); - ctx->timeout = uw_timeout; - ctx->client = NULL; ctx->error_message[0] = 0; @@ -444,6 +443,16 @@ uw_context uw_init() { return ctx; } +void uw_set_app(uw_context ctx, uw_app *app) { + ctx->app = app; + + if (app->inputs_len > ctx->sz_inputs) { + ctx->sz_inputs = app->inputs_len; + ctx->inputs = realloc(ctx->inputs, ctx->sz_inputs * sizeof(input)); + memset(ctx->inputs, 0, ctx->sz_inputs * sizeof(input)); + } +} + void uw_set_db(uw_context ctx, void *db) { ctx->db = db; } @@ -499,19 +508,16 @@ void uw_reset_keep_request(uw_context ctx) { void uw_reset(uw_context ctx) { uw_reset_keep_request(ctx); - memset(ctx->inputs, 0, uw_inputs_len * sizeof(input)); + memset(ctx->inputs, 0, ctx->app->inputs_len * sizeof(input)); memset(ctx->subinputs, 0, ctx->n_subinputs * sizeof(input)); ctx->used_subinputs = 0; } -void uw_db_init(uw_context); -void uw_handle(uw_context, char *); - failure_kind uw_begin_init(uw_context ctx) { int r = setjmp(ctx->jmp_buf); if (r == 0) - uw_db_init(ctx); + ctx->app->db_init(ctx); return r; } @@ -521,8 +527,6 @@ void uw_set_headers(uw_context ctx, char *(*get_header)(void *, const char *), v ctx->get_header_data = get_header_data; } -int uw_db_begin(uw_context); - static void uw_set_error(uw_context ctx, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -600,10 +604,10 @@ failure_kind uw_begin(uw_context ctx, char *path) { int r = setjmp(ctx->jmp_buf); if (r == 0) { - if (uw_db_begin(ctx)) + if (ctx->app->db_begin(ctx)) uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN"); - uw_handle(ctx, path); + ctx->app->handle(ctx, path); } return r; @@ -628,8 +632,6 @@ char *uw_error_message(uw_context ctx) { return ctx->error_message; } -extern int uw_input_num(const char*); - static input *INP(uw_context ctx) { if (ctx->cur_container == NULL) return ctx->inputs; @@ -674,7 +676,7 @@ static input *check_input_space(uw_context ctx, size_t len) { if (ctx->subinputs != new_subinputs) { for (i = 0; i < ctx->used_subinputs; ++i) adjust_input(&new_subinputs[i], ctx->subinputs, new_subinputs, ctx->used_subinputs); - for (i = 0; i < uw_inputs_len; ++i) + for (i = 0; i < ctx->app->inputs_len; ++i) adjust_input(&ctx->inputs[i], ctx->subinputs, new_subinputs, ctx->used_subinputs); adjust_pointer(&ctx->cur_container, ctx->subinputs, new_subinputs, ctx->used_subinputs); @@ -696,7 +698,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) { //printf("Input name %s\n", name); if (!strcasecmp(name, ".b")) { - int n = uw_input_num(value); + int n = ctx->app->input_num(value); input *inps; if (n < 0) { @@ -704,12 +706,12 @@ int uw_set_input(uw_context ctx, const char *name, char *value) { return -1; } - if (n >= uw_inputs_len) { + if (n >= ctx->app->inputs_len) { uw_set_error(ctx, "For subform name %s, index %d is out of range", value, n); return -1; } - inps = check_input_space(ctx, uw_inputs_len); + inps = check_input_space(ctx, ctx->app->inputs_len); INP(ctx)[n].kind = SUBFORM; INP(ctx)[n].data.subform.parent = ctx->cur_container; @@ -741,14 +743,14 @@ int uw_set_input(uw_context ctx, const char *name, char *value) { return -1; } } else if (!strcasecmp(name, ".s")) { - int n = uw_input_num(value); + int n = ctx->app->input_num(value); if (n < 0) { uw_set_error(ctx, "Bad subforms name %s", value); return -1; } - if (n >= uw_inputs_len) { + if (n >= ctx->app->inputs_len) { uw_set_error(ctx, "For subforms name %s, index %d is out of range", value, n); return -1; } @@ -770,7 +772,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) { return -1; } - inps = check_input_space(ctx, uw_inputs_len + 1); + inps = check_input_space(ctx, ctx->app->inputs_len + 1); inps->kind = ENTRY; inps->data.entry.parent = ctx->cur_container; @@ -780,7 +782,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) { inps->data.entry.fields = inps+1; ctx->cur_container = inps; } else { - int n = uw_input_num(name); + int n = ctx->app->input_num(name); if (n < 0) { if (!strcmp(name, "null")) @@ -789,7 +791,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) { return -1; } - if (n >= uw_inputs_len) { + if (n >= ctx->app->inputs_len) { uw_set_error(ctx, "For input name %s, index %d is out of range", name, n); return -1; } @@ -804,7 +806,7 @@ int uw_set_input(uw_context ctx, const char *name, char *value) { char *uw_get_input(uw_context ctx, int n) { if (n < 0) uw_error(ctx, FATAL, "Negative input index %d", n); - if (n >= uw_inputs_len) + if (n >= ctx->app->inputs_len) uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); switch (INP(ctx)[n].kind) { @@ -828,7 +830,7 @@ char *uw_get_input(uw_context ctx, int n) { char *uw_get_optional_input(uw_context ctx, int n) { if (n < 0) uw_error(ctx, FATAL, "Negative input index %d", n); - if (n >= uw_inputs_len) + if (n >= ctx->app->inputs_len) uw_error(ctx, FATAL, "Out-of-bounds input index %d", n); switch (INP(ctx)[n].kind) { @@ -850,14 +852,14 @@ char *uw_get_optional_input(uw_context ctx, int n) { } int uw_set_file_input(uw_context ctx, const char *name, uw_Basis_file f) { - int n = uw_input_num(name); + int n = ctx->app->input_num(name); if (n < 0) { uw_set_error(ctx, "Bad file input name %s", name); return -1; } - if (n >= uw_inputs_len) { + if (n >= ctx->app->inputs_len) { uw_set_error(ctx, "For file input name %s, index %d is out of range", name, n); return -1; } @@ -870,7 +872,6 @@ int uw_set_file_input(uw_context ctx, const char *name, uw_Basis_file f) { void *uw_malloc(uw_context ctx, size_t len); - static void parents(input *inp) { printf("Stack: %p\n", inp); while (inp) { @@ -902,7 +903,7 @@ static void parents(input *inp) { uw_Basis_file uw_get_file_input(uw_context ctx, int n) { if (n < 0) uw_error(ctx, FATAL, "Negative file input index %d", n); - if (n >= uw_inputs_len) + if (n >= ctx->app->inputs_len) uw_error(ctx, FATAL, "Out-of-bounds file input index %d", n); switch (INP(ctx)[n].kind) { @@ -930,7 +931,7 @@ uw_Basis_file uw_get_file_input(uw_context ctx, int n) { void uw_enter_subform(uw_context ctx, int n) { if (n < 0) uw_error(ctx, FATAL, "Negative subform index %d", n); - if (n >= uw_inputs_len) + if (n >= ctx->app->inputs_len) uw_error(ctx, FATAL, "Out-of-bounds subform index %d", n); switch (INP(ctx)[n].kind) { @@ -969,7 +970,7 @@ int uw_enter_subforms(uw_context ctx, int n) { if (n < 0) uw_error(ctx, FATAL, "Negative subforms index %d", n); - if (n >= uw_inputs_len) + if (n >= ctx->app->inputs_len) uw_error(ctx, FATAL, "Out-of-bounds subforms index %d", n); switch (INP(ctx)[n].kind) { @@ -1028,8 +1029,8 @@ void uw_set_script_header(uw_context ctx, const char *s) { ctx->script_header = s; } -void uw_set_url_prefix(uw_context ctx, const char *s) { - ctx->url_prefix = s; +const char *uw_get_url_prefix(uw_context ctx) { + return ctx->app->url_prefix; } void uw_set_needs_push(uw_context ctx, int n) { @@ -1204,12 +1205,10 @@ uw_Basis_string uw_Basis_maybe_onunload(uw_context ctx, uw_Basis_string s) { } } -extern uw_Basis_string uw_cookie_sig(uw_context); - const char *uw_Basis_get_settings(uw_context ctx, uw_unit u) { if (ctx->client == NULL) { if (ctx->needs_sig) { - char *sig = uw_cookie_sig(ctx); + char *sig = ctx->app->cookie_sig(ctx); char *r = uw_malloc(ctx, strlen(sig) + 8); sprintf(r, "sig=\"%s\";", sig); return r; @@ -1217,14 +1216,14 @@ const char *uw_Basis_get_settings(uw_context ctx, uw_unit u) { else return ""; } else { - char *sig = ctx->needs_sig ? uw_cookie_sig(ctx) : ""; - char *r = uw_malloc(ctx, 59 + 3 * INTS_MAX + strlen(ctx->url_prefix) + char *sig = ctx->needs_sig ? ctx->app->cookie_sig(ctx) : ""; + char *r = uw_malloc(ctx, 59 + 3 * INTS_MAX + strlen(ctx->app->url_prefix) + (ctx->needs_sig ? strlen(sig) + 7 : 0)); sprintf(r, "client_id=%u;client_pass=%d;url_prefix=\"%s\";timeout=%d;%s%s%slistener();", ctx->client->id, ctx->client->pass, - ctx->url_prefix, - ctx->timeout, + ctx->app->url_prefix, + ctx->app->timeout, ctx->needs_sig ? "sig=\"" : "", sig, ctx->needs_sig ? "\";" : ""); @@ -2766,9 +2765,6 @@ uw_unit uw_Basis_send(uw_context ctx, uw_Basis_channel chn, uw_Basis_string msg) return uw_unit_v; } -int uw_db_commit(uw_context); -int uw_db_rollback(uw_context); - void uw_commit(uw_context ctx) { unsigned i; @@ -2782,7 +2778,7 @@ void uw_commit(uw_context ctx) { if (ctx->transactionals[i].commit) ctx->transactionals[i].commit(ctx->transactionals[i].data); - if (uw_db_commit(ctx)) + if (ctx->app->db_commit(ctx)) uw_error(ctx, FATAL, "Error running SQL COMMIT"); for (i = 0; i < ctx->used_deltas; ++i) { @@ -2855,7 +2851,7 @@ int uw_rollback(uw_context ctx) { if (ctx->transactionals[i].free) ctx->transactionals[i].free(ctx->transactionals[i].data); - return uw_db_rollback(ctx); + return ctx->app->db_rollback(ctx); } void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback, @@ -2874,16 +2870,14 @@ void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, u // "Garbage collection" -void uw_expunger(uw_context ctx, uw_Basis_client cli); - static failure_kind uw_expunge(uw_context ctx, uw_Basis_client cli) { int r = setjmp(ctx->jmp_buf); if (r == 0) { - if (uw_db_begin(ctx)) + if (ctx->app->db_begin(ctx)) uw_error(ctx, FATAL, "Error running SQL BEGIN"); - uw_expunger(ctx, cli); - if (uw_db_commit(ctx)) + ctx->app->expunger(ctx, cli); + if (ctx->app->db_commit(ctx)) uw_error(ctx, FATAL, "Error running SQL COMMIT"); } @@ -2894,7 +2888,7 @@ void uw_prune_clients(uw_context ctx) { client *c, *next, *prev = NULL; time_t cutoff; - cutoff = time(NULL) - uw_timeout; + cutoff = time(NULL) - ctx->app->timeout; pthread_mutex_lock(&clients_mutex); @@ -2911,14 +2905,14 @@ void uw_prune_clients(uw_context ctx) { while (fk == UNLIMITED_RETRY) { fk = uw_expunge(ctx, c->id); if (fk == UNLIMITED_RETRY) { - uw_db_rollback(ctx); + ctx->app->db_rollback(ctx); printf("Unlimited retry during expunge: %s\n", uw_error_message(ctx)); } } if (fk == SUCCESS) free_client(c); else { - uw_db_rollback(ctx); + ctx->app->db_rollback(ctx); fprintf(stderr, "Expunge blocked by error: %s\n", uw_error_message(ctx)); } } @@ -2930,25 +2924,20 @@ void uw_prune_clients(uw_context ctx) { pthread_mutex_unlock(&clients_mutex); } -void uw_initializer(uw_context ctx); - failure_kind uw_initialize(uw_context ctx) { int r = setjmp(ctx->jmp_buf); if (r == 0) { - if (uw_db_begin(ctx)) + if (ctx->app->db_begin(ctx)) uw_error(ctx, FATAL, "Error running SQL BEGIN"); - uw_initializer(ctx); - if (uw_db_commit(ctx)) + ctx->app->initializer(ctx); + if (ctx->app->db_commit(ctx)) uw_error(ctx, FATAL, "Error running SQL COMMIT"); } return r; } -extern int uw_check_url(const char *); -extern int uw_check_mime(const char *); - static int url_bad(uw_Basis_string s) { for (; *s; ++s) if (!isgraph(*s)) @@ -2960,7 +2949,7 @@ static int url_bad(uw_Basis_string s) { uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) { if (url_bad(s)) uw_error(ctx, FATAL, "Invalid URL %s", uw_Basis_htmlifyString(ctx, s)); - if (uw_check_url(s)) + if (ctx->app->check_url(s)) return s; else uw_error(ctx, FATAL, "Disallowed URL %s", uw_Basis_htmlifyString(ctx, s)); @@ -2969,7 +2958,7 @@ uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) { uw_Basis_string uw_Basis_checkUrl(uw_context ctx, uw_Basis_string s) { if (url_bad(s)) return NULL; - if (uw_check_url(s)) + if (ctx->app->check_url(s)) return s; else return NULL; @@ -2987,7 +2976,7 @@ uw_Basis_string uw_Basis_blessMime(uw_context ctx, uw_Basis_string s) { if (!mime_format(s)) uw_error(ctx, FATAL, "MIME type \"%s\" contains invalid character", uw_Basis_htmlifyString(ctx, s)); - if (uw_check_mime(s)) + if (ctx->app->check_mime(s)) return s; else uw_error(ctx, FATAL, "Disallowed MIME type %s", uw_Basis_htmlifyString(ctx, s)); @@ -2997,7 +2986,7 @@ uw_Basis_string uw_Basis_checkMime(uw_context ctx, uw_Basis_string s) { if (!mime_format(s)) return NULL; - if (uw_check_mime(s)) + if (ctx->app->check_mime(s)) return s; else return NULL; @@ -3020,7 +3009,7 @@ uw_Basis_string uw_Basis_makeSigString(uw_context ctx, uw_Basis_string sig) { } uw_Basis_string uw_Basis_sigString(uw_context ctx, uw_unit u) { - return uw_cookie_sig(ctx); + return ctx->app->cookie_sig(ctx); } uw_Basis_string uw_Basis_fileName(uw_context ctx, uw_Basis_file f) { diff --git a/src/cjr_print.sml b/src/cjr_print.sml index 2d547519..30e34fad 100644 --- a/src/cjr_print.sml +++ b/src/cjr_print.sml @@ -2604,10 +2604,6 @@ fun p_file env (ds, ps) = string scripts end, string "\");", - newline, - string "uw_set_url_prefix(ctx, \"", - string (Settings.getUrlPrefix ()), - string "\");", newline]), string "uw_set_needs_push(ctx, ", string (case side of @@ -2706,7 +2702,7 @@ fun p_file env (ds, ps) = NONE cookies fun makeChecker (name, rules : Settings.rule list) = - box [string "int ", + box [string "static int ", string name, string "(const char *s) {", newline, @@ -2772,34 +2768,22 @@ fun p_file env (ds, ps) = newline, string "int uw_db_begin(uw_context ctx) { return 0; };", newline, + string "void uw_db_close(uw_context ctx) { };", + newline, string "int uw_db_commit(uw_context ctx) { return 0; };", newline, string "int uw_db_rollback(uw_context ctx) { return 0; };"], newline, newline, - string "const char *uw_url_prefix = \"", - string (Settings.getUrlPrefix ()), - string "\";", - newline, - newline, - string "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\\\">\";", newline, newline, p_list_sep newline (fn x => x) pds, newline, - string "int uw_inputs_len = ", - string (Int.toString (SM.foldl Int.max 0 fnums + 1)), - string ";", - newline, - string "int uw_timeout = ", - string (Int.toString (Settings.getTimeout ())), - string ";", - newline, newline, - string "int uw_input_num(char *name) {", + string "static int uw_input_num(const char *name) {", newline, makeSwitch (fnums, 0), string "}", @@ -2816,7 +2800,7 @@ fun p_file env (ds, ps) = newline, string "extern int uw_hash_blocksize;", newline, - string "uw_Basis_string uw_cookie_sig(uw_context ctx) {", + string "static uw_Basis_string uw_cookie_sig(uw_context ctx) {", newline, box [string "uw_Basis_string r = uw_malloc(ctx, uw_hash_blocksize);", newline, @@ -2832,7 +2816,7 @@ fun p_file env (ds, ps) = newline, newline, - string "void uw_handle(uw_context ctx, char *request) {", + string "static void uw_handle(uw_context ctx, char *request) {", newline, string "if (!strcmp(request, \"", string (OS.Path.joinDirFile {dir = Settings.getUrlPrefix (), @@ -2856,7 +2840,7 @@ fun p_file env (ds, ps) = newline, if hasDb then - box [string "void uw_expunger(uw_context ctx, uw_Basis_client cli) {", + box [string "static void uw_expunger(uw_context ctx, uw_Basis_client cli) {", newline, box [p_enamed env (!expunge), string "(ctx, cli);", @@ -2865,7 +2849,7 @@ fun p_file env (ds, ps) = newline, newline, - string "void uw_initializer(uw_context ctx) {", + string "static void uw_initializer(uw_context ctx) {", newline, box [p_list_sep (box []) (fn e => box [p_exp env e, string ";", @@ -2876,10 +2860,22 @@ fun p_file env (ds, ps) = string "}", newline] else - box [string "void uw_expunger(uw_context ctx, uw_Basis_client cli) { };", + box [string "static void uw_expunger(uw_context ctx, uw_Basis_client cli) { };", newline, - string "void uw_initializer(uw_context ctx) { };", - newline]] + string "static void uw_initializer(uw_context ctx) { };", + newline], + + string "uw_app uw_application = {", + p_list_sep (box [string ",", newline]) string + [Int.toString (SM.foldl Int.max 0 fnums + 1), + Int.toString (Settings.getTimeout ()), + "\"" ^ Settings.getUrlPrefix () ^ "\"", + "uw_client_init", "uw_initializer", "uw_expunger", + "uw_db_init", "uw_db_begin", "uw_db_commit", "uw_db_rollback", "uw_db_close", + "uw_handle", + "uw_input_num", "uw_cookie_sig", "uw_check_url", "uw_check_mime"], + string "};", + newline] end fun p_sql env (ds, _) = diff --git a/src/compiler.sml b/src/compiler.sml index 10fc66f0..a596a21d 100644 --- a/src/compiler.sml +++ b/src/compiler.sml @@ -1028,7 +1028,7 @@ fun compileC {cname, oname, ename, libs, profile, debug, link = link'} = val urweb_o = clibFile "urweb.o" val memmem_o = clibFile "memmem.o" - val compile = "gcc " ^ Config.gccArgs ^ " -Wstrict-prototypes -Werror -O3 -fno-inline -I " ^ Config.includ + val compile = "gcc " ^ Config.gccArgs ^ " -Wimplicit -Werror -O3 -fno-inline -I " ^ Config.includ ^ " -c " ^ cname ^ " -o " ^ oname val link = "gcc -Werror -O3 -lm -lmhash -pthread " ^ Config.gccArgs ^ " " ^ libs ^ " " ^ urweb_o ^ " " ^ oname ^ " " ^ memmem_o ^ " " ^ #link proto ^ " -o " ^ ename diff --git a/src/mysql.sml b/src/mysql.sml index 40409ff0..b894bfac 100644 --- a/src/mysql.sml +++ b/src/mysql.sml @@ -379,7 +379,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "void uw_client_init(void) {", + string "static void uw_client_init(void) {", newline, box [string "uw_sqlfmtInt = \"%lld%n\";", newline, @@ -502,7 +502,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "void uw_db_init(uw_context ctx) {", + string "static void uw_db_init(uw_context ctx) {", newline, string "MYSQL *mysql = mysql_init(NULL);", newline, @@ -554,7 +554,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "void uw_db_close(uw_context ctx) {", + string "static void uw_db_close(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, @@ -573,7 +573,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "int uw_db_begin(uw_context ctx) {", + string "static int uw_db_begin(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, @@ -586,7 +586,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "int uw_db_commit(uw_context ctx) {", + string "static int uw_db_commit(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, @@ -596,7 +596,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "int uw_db_rollback(uw_context ctx) {", + string "static int uw_db_rollback(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, diff --git a/src/postgres.sml b/src/postgres.sml index c4bbb067..59fa3330 100644 --- a/src/postgres.sml +++ b/src/postgres.sml @@ -249,27 +249,7 @@ fun checkRel (table, checkNullable) (s, xts) = fun init {dbstring, prepared = ss, tables, views, sequences} = box [if #persistent (currentProtocol ()) then - box [string "void uw_client_init(void) {", - newline, - box [string "uw_sqlfmtInt = \"%lld::int8%n\";", - newline, - string "uw_sqlfmtFloat = \"%g::float8%n\";", - newline, - string "uw_Estrings = 1;", - newline, - string "uw_sqlsuffixString = \"::text\";", - newline, - string "uw_sqlsuffixChar = \"::char\";", - newline, - string "uw_sqlsuffixBlob = \"::bytea\";", - newline, - string "uw_sqlfmtUint4 = \"%u::int4%n\";", - newline], - string "}", - newline, - newline, - - string "static void uw_db_validate(uw_context ctx) {", + box [string "static void uw_db_validate(uw_context ctx) {", newline, string "PGconn *conn = uw_get_db(ctx);", newline, @@ -380,93 +360,111 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = string "}", newline, - newline, - - string "void uw_db_close(uw_context ctx) {", - newline, - 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 ISOLATION LEVEL SERIALIZABLE\");", - 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, newline] else box [string "static void uw_db_validate(uw_context ctx) { }", newline, string "static void uw_db_prepare(uw_context ctx) { }"], + string "static void uw_client_init(void) {", + newline, + box [string "uw_sqlfmtInt = \"%lld::int8%n\";", + newline, + string "uw_sqlfmtFloat = \"%g::float8%n\";", + newline, + string "uw_Estrings = 1;", + newline, + string "uw_sqlsuffixString = \"::text\";", + newline, + string "uw_sqlsuffixChar = \"::char\";", + newline, + string "uw_sqlsuffixBlob = \"::bytea\";", + newline, + string "uw_sqlfmtUint4 = \"%u::int4%n\";", + newline], + string "}", + newline, + newline, + + string "static void uw_db_close(uw_context ctx) {", + newline, + string "PQfinish(uw_get_db(ctx));", + newline, + string "}", + newline, + newline, + + string "static int uw_db_begin(uw_context ctx) {", + newline, + string "PGconn *conn = uw_get_db(ctx);", + newline, + string "PGresult *res = PQexec(conn, \"BEGIN ISOLATION LEVEL SERIALIZABLE\");", + 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 "static 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 "static 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, newline, - string "void uw_db_init(uw_context ctx) {", + string "static void uw_db_init(uw_context ctx) {", newline, string "PGconn *conn = PQconnectdb(\"", string (String.toString dbstring), diff --git a/src/sqlite.sml b/src/sqlite.sml index 440c7c28..485e43b4 100644 --- a/src/sqlite.sml +++ b/src/sqlite.sml @@ -156,7 +156,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "void uw_client_init(void) {", + string "static void uw_client_init(void) {", newline, box [string "uw_sqlfmtInt = \"%lld%n\";", newline, @@ -256,7 +256,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "void uw_db_init(uw_context ctx) {", + string "static void uw_db_init(uw_context ctx) {", newline, string "sqlite3 *sqlite;", newline, @@ -283,7 +283,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "void uw_db_close(uw_context ctx) {", + string "static void uw_db_close(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, @@ -302,7 +302,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "int uw_db_begin(uw_context ctx) {", + string "static int uw_db_begin(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, @@ -321,7 +321,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, string "}", newline, - string "int uw_db_commit(uw_context ctx) {", + string "static int uw_db_commit(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, @@ -341,7 +341,7 @@ fun init {dbstring, prepared = ss, tables, views, sequences} = newline, newline, - string "int uw_db_rollback(uw_context ctx) {", + string "static int uw_db_rollback(uw_context ctx) {", newline, string "uw_conn *conn = uw_get_db(ctx);", newline, |