changeset 1446:36f7d1debb37

Each context gets its own non-repeating sequence of source numbers
author Adam Chlipala <adam@chlipala.net>
date Sat, 09 Apr 2011 14:36:47 -0400
parents 6e6f1643c4e9
children 17393c5e2b90
files include/request.h include/types.h include/urweb.h lib/js/urweb.js src/c/cgi.c src/c/fastcgi.c src/c/http.c src/c/request.c src/c/urweb.c src/cjr_print.sml src/cjrize.sml src/jscomp.sml src/mono_opt.sml tests/rs.ur tests/rs.urs
diffstat 15 files changed, 104 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/include/request.h	Mon Mar 28 10:37:49 2011 -0400
+++ b/include/request.h	Sat Apr 09 14:36:47 2011 -0400
@@ -22,7 +22,7 @@
                           int (*send)(int sockfd, const void *buf, ssize_t len),
                           int (*close)(int fd));
 
-uw_context uw_request_new_context(uw_app*, void *logger_data, uw_logger log_error, uw_logger log_debug);
+uw_context uw_request_new_context(int id, uw_app*, void *logger_data, uw_logger log_error, uw_logger log_debug);
 
 typedef struct {
   uw_app *app;
--- a/include/types.h	Mon Mar 28 10:37:49 2011 -0400
+++ b/include/types.h	Sat Apr 09 14:36:47 2011 -0400
@@ -35,6 +35,11 @@
   unsigned cli, chn;
 } uw_Basis_channel;
 
+typedef struct {
+  int context;
+  unsigned long long source;
+} uw_Basis_source;
+
 typedef struct uw_Basis_file {
   uw_Basis_string name, type;
   uw_Basis_blob data;
--- a/include/urweb.h	Mon Mar 28 10:37:49 2011 -0400
+++ b/include/urweb.h	Sat Apr 09 14:36:47 2011 -0400
@@ -20,7 +20,7 @@
 void uw_prune_clients(uw_context);
 failure_kind uw_initialize(uw_context);
 
-uw_context uw_init(void *logger_data, uw_logger log_debug);
+uw_context uw_init(int id, void *logger_data, uw_logger log_debug);
 void uw_close(uw_context);
 int uw_set_app(uw_context, uw_app*);
 uw_app *uw_get_app(uw_context);
@@ -71,12 +71,13 @@
 
 void uw_write(uw_context, const char*);
 
-uw_Basis_int uw_Basis_new_client_source(uw_context, uw_Basis_string);
-uw_unit uw_Basis_set_client_source(uw_context, uw_Basis_int, uw_Basis_string);
+uw_Basis_source uw_Basis_new_client_source(uw_context, uw_Basis_string);
+uw_unit uw_Basis_set_client_source(uw_context, uw_Basis_source, uw_Basis_string);
 
 void uw_set_script_header(uw_context, const char*);
 const char *uw_Basis_get_settings(uw_context, uw_unit);
 const char *uw_Basis_get_script(uw_context, uw_unit);
+const char *uw_get_real_script(uw_context);
 
 uw_Basis_string uw_Basis_maybe_onload(uw_context, uw_Basis_string);
 uw_Basis_string uw_Basis_maybe_onunload(uw_context, uw_Basis_string);
@@ -90,6 +91,7 @@
 char *uw_Basis_htmlifyBool(uw_context, uw_Basis_bool);
 char *uw_Basis_htmlifyTime(uw_context, uw_Basis_time);
 char *uw_Basis_htmlifySpecialChar(uw_context, unsigned char);
+char *uw_Basis_htmlifySource(uw_context, uw_Basis_source);
 
 uw_unit uw_Basis_htmlifyInt_w(uw_context, uw_Basis_int);
 uw_unit uw_Basis_htmlifyFloat_w(uw_context, uw_Basis_float);
@@ -97,6 +99,7 @@
 uw_unit uw_Basis_htmlifyBool_w(uw_context, uw_Basis_bool);
 uw_unit uw_Basis_htmlifyTime_w(uw_context, uw_Basis_time);
 uw_unit uw_Basis_htmlifySpecialChar_w(uw_context, unsigned char);
+uw_unit uw_Basis_htmlifySource_w(uw_context, uw_Basis_source);
 
 char *uw_Basis_attrifyInt(uw_context, uw_Basis_int);
 char *uw_Basis_attrifyFloat(uw_context, uw_Basis_float);
--- a/lib/js/urweb.js	Mon Mar 28 10:37:49 2011 -0400
+++ b/lib/js/urweb.js	Sat Apr 09 14:36:47 2011 -0400
@@ -734,8 +734,14 @@
             } catch (e) { }
 
             if (isok) {
+                var lines = xhr.responseText.split("\n");
+                if (lines.length != 2)
+                    whine("Bad RPC response lines");
+
+                eval(lines[0]);
+
                 try {
-                    k(parse(xhr.responseText));
+                    k(parse(lines[1]));
                 } catch (v) {
                     doExn(v);
                 }
--- a/src/c/cgi.c	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/c/cgi.c	Sat Apr 09 14:36:47 2011 -0400
@@ -56,7 +56,7 @@
 }
 
 int main(int argc, char *argv[]) {
-  uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug);
+  uw_context ctx = uw_request_new_context(0, &uw_application, NULL, log_error, log_debug);
   uw_request_context rc = uw_new_request_context();
   request_result rr;
   char *method = getenv("REQUEST_METHOD"),
--- a/src/c/fastcgi.c	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/c/fastcgi.c	Sat Apr 09 14:36:47 2011 -0400
@@ -322,7 +322,7 @@
 static void *worker(void *data) {
   FCGI_Input *in = fastcgi_input();
   FCGI_Output *out = fastcgi_output();
-  uw_context ctx = uw_request_new_context(&uw_application, out, log_error, log_debug);
+  uw_context ctx = uw_request_new_context(*(int *)data, &uw_application, out, log_error, log_debug);
   uw_request_context rc = uw_new_request_context();
   headers hs;
   size_t body_size = 0;
--- a/src/c/http.c	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/c/http.c	Sat Apr 09 14:36:47 2011 -0400
@@ -63,7 +63,7 @@
 
 static void *worker(void *data) {
   int me = *(int *)data;
-  uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug);
+  uw_context ctx = uw_request_new_context(me, &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();
--- a/src/c/request.c	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/c/request.c	Sat Apr 09 14:36:47 2011 -0400
@@ -32,8 +32,8 @@
   return r;
 }
 
-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(logger_data, log_debug);
+uw_context uw_request_new_context(int id, uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) {
+  uw_context ctx = uw_init(id, logger_data, log_debug);
   int retries_left = MAX_RETRIES;
   uw_set_app(ctx, app);
 
@@ -84,13 +84,14 @@
 } loggers;
 
 typedef struct {
+  int id;
   loggers *ls;
   uw_periodic pdic;
 } periodic;
 
 static void *periodic_loop(void *data) {
   periodic *p = (periodic *)data;
-  uw_context ctx = uw_request_new_context(p->ls->app, p->ls->logger_data, p->ls->log_error, p->ls->log_debug);
+  uw_context ctx = uw_request_new_context(p->id, p->ls->app, p->ls->logger_data, p->ls->log_error, p->ls->log_debug);
 
   if (!ctx)
     exit(1);
@@ -127,6 +128,7 @@
   failure_kind fk;
   uw_periodic *ps;
   loggers *ls = malloc(sizeof(loggers));
+  int id;
 
   ls->app = app;
   ls->logger_data = logger_data;
@@ -145,7 +147,7 @@
     }
   }
 
-  ctx = uw_request_new_context(app, logger_data, log_error, log_debug);
+  ctx = uw_request_new_context(0, app, logger_data, log_error, log_debug);
 
   if (!ctx)
     exit(1);
@@ -164,9 +166,11 @@
 
   uw_free(ctx);
 
+  id = 1;
   for (ps = app->periodics; ps->callback; ++ps) {
     pthread_t thread;
     periodic *arg = malloc(sizeof(periodic));
+    arg->id = id++;
     arg->ls = ls;
     arg->pdic = *ps;
     
@@ -218,6 +222,7 @@
   char errmsg[ERROR_BUF_LEN];
 
   uw_reset(ctx);
+
   rc->queryString[0] = 0;
 
   for (s = path; *s; ++s) {
@@ -546,7 +551,7 @@
 
 void *client_pruner(void *data) {
   loggers *ls = (loggers *)data;
-  uw_context ctx = uw_request_new_context(ls->app, ls->logger_data, ls->log_error, ls->log_debug);
+  uw_context ctx = uw_request_new_context(0, ls->app, ls->logger_data, ls->log_error, ls->log_debug);
 
   if (!ctx)
     exit(1);
--- a/src/c/urweb.c	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/c/urweb.c	Sat Apr 09 14:36:47 2011 -0400
@@ -399,6 +399,7 @@
 
 struct uw_context {
   uw_app *app;
+  int id;
 
   char *(*get_header)(void *, const char *);
   void *get_header_data;
@@ -408,7 +409,7 @@
   input *inputs, *subinputs, *cur_container;
   size_t sz_inputs, n_subinputs, used_subinputs;
 
-  int source_count;
+  unsigned long long source_count;
 
   void *db;
 
@@ -454,10 +455,11 @@
 size_t uw_heap_max = SIZE_MAX;
 size_t uw_script_max = SIZE_MAX;
 
-uw_context uw_init(void *logger_data, uw_logger log_debug) {
+uw_context uw_init(int id, void *logger_data, uw_logger log_debug) {
   uw_context ctx = malloc(sizeof(struct uw_context));
 
   ctx->app = NULL;
+  ctx->id = id;
 
   ctx->get_header = NULL;
   ctx->get_header_data = NULL;
@@ -584,7 +586,6 @@
   uw_buffer_reset(&ctx->heap);
   ctx->regions = NULL;
   ctx->cleanup_front = ctx->cleanup;
-  ctx->source_count = 0;
   ctx->used_deltas = 0;
   ctx->client = NULL;
   ctx->cur_container = NULL;
@@ -621,6 +622,10 @@
   ctx->app->db_close(ctx);
 }
 
+uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
+  return ctx->get_header(ctx->get_header_data, h);
+}
+
 void uw_set_headers(uw_context ctx, char *(*get_header)(void *, const char *), void *get_header_data) {
   ctx->get_header = get_header;
   ctx->get_header_data = get_header_data;
@@ -680,10 +685,6 @@
   ++ctx->cleanup_front;
 }
 
-uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
-  return ctx->get_header(ctx->get_header_data, h);
-}
-
 char *uw_Basis_htmlifyString(uw_context, const char *);
 
 void uw_login(uw_context ctx) {
@@ -1296,6 +1297,10 @@
   return "<sc>";
 }
 
+const char *uw_get_real_script(uw_context ctx) {
+  return ctx->script.start;
+}
+
 uw_Basis_string uw_Basis_maybe_onload(uw_context ctx, uw_Basis_string s) {
   if (s[0] == 0)
     return "";
@@ -1345,7 +1350,7 @@
 uw_Basis_string uw_Basis_jsifyString(uw_context ctx, uw_Basis_string s) {
   char *r, *s2;
 
-  uw_check_heap(ctx, strlen(s) * 4 + 2);
+  uw_check_heap(ctx, strlen(s) * 4 + 3);
 
   r = s2 = ctx->heap.front;
   *s2++ = '"';
@@ -1385,7 +1390,7 @@
   unsigned char c = c1;
   char *r, *s2;
 
-  uw_check_heap(ctx, 6);
+  uw_check_heap(ctx, 7);
 
   r = s2 = ctx->heap.front;
   *s2++ = '"';
@@ -1420,7 +1425,7 @@
 uw_Basis_string uw_Basis_jsifyString_ws(uw_context ctx, uw_Basis_string s) {
   char *r, *s2;
 
-  uw_check_script(ctx, strlen(s) * 4 + 2);
+  uw_check_script(ctx, strlen(s) * 4 + 3);
 
   r = s2 = ctx->script.front;
   *s2++ = '"';
@@ -1467,27 +1472,28 @@
   }
 }
 
-uw_Basis_int uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
+uw_Basis_source uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
   int len;
   size_t s_len = strlen(s);
 
-  uw_check_script(ctx, 18 + INTS_MAX + s_len);
-  sprintf(ctx->script.front, "var s%d=sc(exec(%n", ctx->source_count, &len);
+  uw_check_script(ctx, 15 + 2 * INTS_MAX + s_len);
+  sprintf(ctx->script.front, "s%d_%llu=sc(exec(%n", ctx->id, ctx->source_count, &len);
   ctx->script.front += len;
   strcpy(ctx->script.front, s);
   ctx->script.front += s_len;
   strcpy(ctx->script.front, "));");
   ctx->script.front += 3;
 
-  return ctx->source_count++;
-}
-
-uw_unit uw_Basis_set_client_source(uw_context ctx, uw_Basis_int n, uw_Basis_string s) {
+  uw_Basis_source r = {ctx->id, ctx->source_count++};
+  return r;
+}
+
+uw_unit uw_Basis_set_client_source(uw_context ctx, uw_Basis_source src, uw_Basis_string s) {
   int len;
   size_t s_len = strlen(s);
 
-  uw_check_script(ctx, 12 + INTS_MAX + s_len);
-  sprintf(ctx->script.front, "sv(s%d,exec(%n", (int)n, &len);
+  uw_check_script(ctx, 15 + 2 * INTS_MAX + s_len);
+  sprintf(ctx->script.front, "sv(s%d_%llu,exec(%n", src.context, src.source, &len);
   ctx->script.front += len;
   strcpy(ctx->script.front, s);
   ctx->script.front += s_len;
@@ -2128,6 +2134,27 @@
   return uw_unit_v;
 }
 
+char *uw_Basis_htmlifySource(uw_context ctx, uw_Basis_source src) {
+  int len;
+  char *r;
+
+  uw_check_heap(ctx, 2 * INTS_MAX + 2);
+  r = ctx->heap.front;
+  sprintf(r, "s%d_%llu%n", src.context, src.source, &len);
+  ctx->heap.front += len+1;
+  return r;
+}
+
+uw_unit uw_Basis_htmlifySource_w(uw_context ctx, uw_Basis_source src) {
+  int len;
+
+  uw_check(ctx, 2 * INTS_MAX + 1);
+  sprintf(ctx->page.front, "s%d_%llu%n", src.context, src.source, &len);
+  ctx->page.front += len;
+  
+  return uw_unit_v;
+}
+
 uw_Basis_char uw_Basis_strsub(uw_context ctx, uw_Basis_string s, uw_Basis_int n) {
   while (n >= 0) {
     if (*s == 0)
--- a/src/cjr_print.sml	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/cjr_print.sml	Sat Apr 09 14:36:47 2011 -0400
@@ -2723,7 +2723,11 @@
                           string ", 0);",
                           newline,
                           box (case ek of
-                                   Core.Rpc _ => [urlify env ran]
+                                   Core.Rpc _ => [string "uw_write(ctx, uw_get_real_script(ctx));",
+                                                  newline,
+                                                  string "uw_write(ctx, \"\\n\");",
+                                                  newline,
+                                                  urlify env ran]
                                  | _ => [string "uw_write(ctx, \"</html>\");",
                                          newline]),
                           string "return;",
--- a/src/cjrize.sml	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/cjrize.sml	Sat Apr 09 14:36:47 2011 -0400
@@ -161,7 +161,7 @@
                 in
                     ((L'.TList (t', si), loc), sm)
                 end
-              | L.TSource => ((L'.TFfi ("Basis", "int"), loc), sm)
+              | L.TSource => ((L'.TFfi ("Basis", "source"), loc), sm)
               | L.TSignal _ => raise Fail "Cjrize: TSignal remains"
     in
         cify IM.empty x
--- a/src/jscomp.sml	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/jscomp.sml	Sat Apr 09 14:36:47 2011 -0400
@@ -91,8 +91,7 @@
 
         fun quoteExp loc (t : typ) (e, st) =
             case #1 t of
-                TSource => (strcat loc [str loc "s",
-                                        (EFfiApp ("Basis", "htmlifyInt", [e]), loc)], st)
+                TSource => ((EFfiApp ("Basis", "htmlifySource", [e]), loc), st)
 
               | TRecord [] => (str loc "null", st)
               | TRecord [(x, t)] =>
--- a/src/mono_opt.sml	Mon Mar 28 10:37:49 2011 -0400
+++ b/src/mono_opt.sml	Sat Apr 09 14:36:47 2011 -0400
@@ -249,6 +249,9 @@
       | EFfiApp ("Basis", "htmlifyString_w", [(EPrim (Prim.String s), loc)]) =>
         EWrite (EPrim (Prim.String (htmlifyString s)), loc)
 
+      | EWrite (EFfiApp ("Basis", "htmlifySource", [e]), _) =>
+        EFfiApp ("Basis", "htmlifySource_w", [e])
+
       | EFfiApp ("Basis", "attrifyInt", [(EPrim (Prim.Int n), _)]) =>
         EPrim (Prim.String (attrifyInt n))
       | EWrite (EFfiApp ("Basis", "attrifyInt", [(EPrim (Prim.Int n), _)]), loc) =>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/rs.ur	Sat Apr 09 14:36:47 2011 -0400
@@ -0,0 +1,15 @@
+fun bobo () =
+    n1 <- source 0;
+    n2 <- source 1;
+    return <xml>
+      <dyn signal={n1 <- signal n1; n2 <- signal n2; return <xml>{[n1 + n2]}</xml>}/>
+      <button value="Increment1" onclick={v <- get n1; set n1 (v + 1)}/>
+      <button value="Increment2" onclick={v <- get n2; set n2 (v + 1)}/>
+    </xml>
+
+fun main () =
+    x <- source <xml/>;
+    return <xml><body>
+      <dyn signal={signal x}/>
+      <button value="Grab" onclick={y <- rpc (bobo ()); set x y}/>
+    </body></xml>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/rs.urs	Sat Apr 09 14:36:47 2011 -0400
@@ -0,0 +1,1 @@
+val main : unit -> transaction page