changeset 2270:1e3ba868f8bf

Merge.
author Ziv Scully <ziv@mit.edu>
date Mon, 19 Oct 2015 14:42:22 -0400
parents f7bc7c11a656 74c762002352
children 85f91c7452b0
files include/urweb/urweb_cpp.h src/c/urweb.c src/settings.sml
diffstat 8 files changed, 117 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG	Thu Oct 15 00:52:04 2015 -0400
+++ b/CHANGELOG	Mon Oct 19 14:42:22 2015 -0400
@@ -1,3 +1,10 @@
+========
+20151018
+========
+
+- Applications now reconnect to database server automatically after losing connection.
+- Bug fixes and improvements to compatibility, documentation, and error messages
+
 ========
 20150819
 ========
--- a/configure.ac	Thu Oct 15 00:52:04 2015 -0400
+++ b/configure.ac	Mon Oct 19 14:42:22 2015 -0400
@@ -1,4 +1,4 @@
-AC_INIT([urweb], [20150819])
+AC_INIT([urweb], [20151018])
 WORKING_VERSION=1
 AC_USE_SYSTEM_EXTENSIONS
 
--- a/include/urweb/urweb_cpp.h	Thu Oct 15 00:52:04 2015 -0400
+++ b/include/urweb/urweb_cpp.h	Mon Oct 19 14:42:22 2015 -0400
@@ -40,6 +40,7 @@
 uw_loggers* uw_get_loggers(struct uw_context *ctx);
 failure_kind uw_begin(struct uw_context *, char *path);
 void uw_ensure_transaction(struct uw_context *);
+void uw_try_reconnecting_and_restarting(struct uw_context *);
 failure_kind uw_begin_onError(struct uw_context *, char *msg);
 void uw_login(struct uw_context *);
 int uw_commit(struct uw_context *);
--- a/src/c/urweb.c	Thu Oct 15 00:52:04 2015 -0400
+++ b/src/c/urweb.c	Mon Oct 19 14:42:22 2015 -0400
@@ -809,12 +809,37 @@
   return r;
 }
 
+static void uw_try_reconnecting(uw_context ctx) {
+  // Hm, error starting transaction.
+  // Maybe the database server died but has since come back up.
+  // Let's try starting from scratch.
+  if (ctx->db) {
+    ctx->app->db_close(ctx);
+    ctx->db = NULL;
+  }
+  ctx->app->db_init(ctx);
+
+  if (!ctx->db)
+    uw_error(ctx, FATAL, "Error reopening database connection");
+}
+
+void uw_try_reconnecting_and_restarting(uw_context ctx) {
+  uw_try_reconnecting(ctx);
+  uw_error(ctx, BOUNDED_RETRY, "Restarting transaction after fixing database connection");
+}
+
 void uw_ensure_transaction(uw_context ctx) {
   if (!ctx->transaction_started && !ctx->at_most_one_query) {
-    if (ctx->app->db_begin(ctx, ctx->could_write_db))
-      uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN");
+    if (!ctx->db || ctx->app->db_begin(ctx, ctx->could_write_db)) {
+      uw_try_reconnecting(ctx);
+
+      if (ctx->app->db_begin(ctx, ctx->could_write_db))
+        uw_error(ctx, FATAL, "Error running SQL BEGIN");
+    }
+
     ctx->transaction_started = 1;
-  }
+  } else if (ctx->at_most_one_query && !ctx->db)
+    uw_try_reconnecting(ctx);
 }
 
 uw_Basis_client uw_Basis_self(uw_context ctx) {
--- a/src/elisp/urweb-mode.el	Thu Oct 15 00:52:04 2015 -0400
+++ b/src/elisp/urweb-mode.el	Mon Oct 19 14:42:22 2015 -0400
@@ -246,7 +246,7 @@
     ("\\<\\(signature\\)\\s-+\\(\\sw+\\)"
      (1 font-lock-keyword-face)
      (2 (amAttribute font-lock-interface-def-face)))
-    
+
     (,urweb-keywords-regexp . font-lock-keyword-face)
     (,urweb-sql-keywords-regexp . font-lock-sql-face)
     (,urweb-cident-regexp . font-lock-cvariable-face))
@@ -377,7 +377,11 @@
 (add-to-list 'auto-mode-alist '("\\.urs?\\'" . urweb-mode))
 
 ;;;###autoload
-(define-derived-mode urweb-mode fundamental-mode "Ur/Web"
+(defalias 'urweb-mode-derived-from
+  (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
+
+;;;###autoload
+(define-derived-mode urweb-mode urweb-mode-derived-from "Ur/Web"
   "\\<urweb-mode-map>Major mode for editing Ur/Web code.
 This mode runs `urweb-mode-hook' just before exiting.
 \\{urweb-mode-map}"
@@ -409,7 +413,7 @@
   (set-syntax-table urweb-mode-syntax-table)
   (setq local-abbrev-table urweb-mode-abbrev-table)
   ;; A paragraph is separated by blank lines or ^L only.
-  
+
   (set (make-local-variable 'indent-line-function) 'urweb-indent-line)
   (set (make-local-variable 'comment-start) "(* ")
   (set (make-local-variable 'comment-end) " *)")
--- a/src/mysql.sml	Thu Oct 15 00:52:04 2015 -0400
+++ b/src/mysql.sml	Mon Oct 19 14:42:22 2015 -0400
@@ -1,4 +1,4 @@
-(* Copyright (c) 2009-2010, Adam Chlipala
+(* Copyright (c) 2009-2010, 2015, Adam Chlipala
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -546,7 +546,7 @@
                   newline,
                   string "mysql_close(mysql);",
                   newline,
-                  string "uw_error(ctx, BOUNDED_RETRY, ",
+                  string "uw_error(ctx, FATAL, ",
                   string "\"Connection to MySQL server failed: %s\", msg);"],
              newline,
              string "}",
@@ -861,11 +861,17 @@
                                           end) cols,
          newline,
 
-         string "if (mysql_stmt_reset(stmt)) uw_error(ctx, FATAL, \"",
-         string (ErrorMsg.spanToString loc),
-         string ": Error reseting statement: %s\\n%s\", ",
-         query,
-         string ", mysql_error(conn->conn));",
+         string "if (mysql_stmt_reset(stmt)) {",
+         box [newline,
+              string "if (mysql_errno(conn->conn) == 2006) uw_try_reconnecting_and_restarting(ctx);",
+              newline,
+              string "uw_error(ctx, FATAL, \"",
+              string (ErrorMsg.spanToString loc),
+              string ": Error reseting statement: %s\\n%s\", ",
+              query,
+              string ", mysql_error(conn->conn));",
+              newline],
+         string "}",
          newline,
          newline,
 
@@ -1233,7 +1239,9 @@
 
 fun dmlCommon {loc, dml, mode} =
     box [string "if (mysql_stmt_execute(stmt)) {",
-         box [string "if (mysql_errno(conn->conn) == 1213)",
+         box [string "if (mysql_errno(conn->conn) == 2006) uw_try_reconnecting_and_restarting(ctx);",
+              newline,
+              string "if (mysql_errno(conn->conn) == 1213)",
               newline,
               box [string "uw_error(ctx, UNLIMITED_RETRY, \"Deadlock detected\");",
                    newline],
@@ -1540,7 +1548,13 @@
          newline,
          newline,
 
-         string "if (mysql_query(conn->conn, insert)) uw_error(ctx, FATAL, \"'nextval' INSERT failed\");",
+         string "if (mysql_query(conn->conn, insert)) {",
+         box [newline,
+              string "if (mysql_errno(conn->conn) == 2006) uw_try_reconnecting_and_restarting(ctx);",
+              newline,
+              string "uw_error(ctx, FATAL, \"'nextval' INSERT failed\");",
+              newline],
+         string "}",
          newline,
          string "n = mysql_insert_id(conn->conn);",
          newline,
--- a/src/postgres.sml	Thu Oct 15 00:52:04 2015 -0400
+++ b/src/postgres.sml	Mon Oct 19 14:42:22 2015 -0400
@@ -617,7 +617,13 @@
          newline,
          newline,
 
-         string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating query result.\");",
+         string "if (res == NULL) {",
+         box [newline,
+              string "uw_try_reconnecting_and_restarting(ctx);",
+              newline,
+              string "uw_error(ctx, FATAL, \"Can't allocate query result; database server may be down.\");",
+              newline],
+         string "}",
          newline,
          newline,
 
@@ -782,7 +788,13 @@
                                                                             string "\""]}]
 
 fun dmlCommon {loc, dml, mode} =
-    box [string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating DML result.\");",
+    box [string "if (res == NULL) {",
+         box [newline,
+              string "uw_try_reconnecting_and_restarting(ctx);",
+              newline,
+              string "uw_error(ctx, FATAL, \"Can't allocate DML result; database server may be down.\");",
+              newline],
+         string "}",
          newline,
          newline,
 
@@ -818,7 +830,13 @@
 
                                         string "res = PQexec(conn, \"ROLLBACK TO s\");",
                                         newline,
-                                        string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating DML result.\");",
+                                        string "if (res == NULL) {",
+                                        box [newline,
+                                             string "uw_try_reconnecting_and_restarting(ctx);",
+                                             newline,
+                                             string "uw_error(ctx, FATAL, \"Can't allocate DML ROLLBACK result; database server may be down.\");",
+                                             newline],
+                                        string "}",
                                         newline,
                                         newline,
 
@@ -851,7 +869,13 @@
                               newline,
                               string "res = PQexec(conn, \"RELEASE s\");",
                               newline,
-                              string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating DML result.\");",
+                              string "if (res == NULL) {",
+                              box [newline,
+                                   string "uw_try_reconnecting_and_restarting(ctx);",
+                                   newline,
+                                   string "uw_error(ctx, FATAL, \"Can't allocate DML RELEASE result; database server may be down.\");",
+                                   newline],
+                              string "}",
                               newline,
                               newline,
 
@@ -877,7 +901,13 @@
         Error => box []
       | None => box [string "res = PQexec(conn, \"SAVEPOINT s\");",
                      newline,
-                     string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating DML result.\");",
+                     string "if (res == NULL) {",
+                     box [newline,
+                          string "uw_try_reconnecting_and_restarting(ctx);",
+                          newline,
+                          string "uw_error(ctx, FATAL, \"Can't allocate DML SAVEPOINT result; database server may be down.\");",
+                          newline],
+                     string "}",
                      newline,
                      newline,
                      string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
@@ -938,7 +968,13 @@
                                           string "\""], mode = mode}]
 
 fun nextvalCommon {loc, query} =
-    box [string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating nextval result.\");",
+    box [string "if (res == NULL) {",
+         box [newline,
+              string "uw_try_reconnecting_and_restarting(ctx);",
+              newline,
+              string "uw_error(ctx, FATAL, \"Can't allocate NEXTVAL result; database server may be down.\");",
+              newline],
+         string "}",
          newline,
          newline,
 
@@ -1020,7 +1056,13 @@
                                                 string "\""]}]
 
 fun setvalCommon {loc, query} =
-    box [string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating setval result.\");",
+    box [string "if (res == NULL) {",
+         box [newline,
+              string "uw_try_reconnecting_and_restarting(ctx);",
+              newline,
+              string "uw_error(ctx, FATAL, \"Can't allocate SETVAL result; database server may be down.\");",
+              newline],
+         string "}",
          newline,
          newline,
 
--- a/src/settings.sml	Thu Oct 15 00:52:04 2015 -0400
+++ b/src/settings.sml	Mon Oct 19 14:42:22 2015 -0400
@@ -885,7 +885,7 @@
     in
         case SM.find (!files, Uri) of
             SOME (path', _) =>
-            if path' = path then
+            if OS.Path.mkCanonical path' = OS.Path.mkCanonical path then
                 ()
             else
                 ErrorMsg.error ("Two different files requested for URI " ^ Uri ^ " ( " ^ path' ^ " vs. " ^ path ^ ")")