You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/11/27 09:19:51 UTC

svn commit: r1545958 [11/15] - in /subversion/branches/log-addressing: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/server-side/ contrib/server-side/svncutter/ notes/ subversion/bindings/javahl/native/ sub...

Modified: subversion/branches/log-addressing/subversion/svnlook/svnlook.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnlook/svnlook.c?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnlook/svnlook.c (original)
+++ subversion/branches/log-addressing/subversion/svnlook/svnlook.c Wed Nov 27 08:19:45 2013
@@ -1875,7 +1875,8 @@ do_plist(svnlook_ctxt_t *c,
       svn_xml_make_header2(&sb, "UTF-8", pool);
 
       /* "<properties>" */
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "properties", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "properties",
+                            SVN_VA_NULL);
     }
 
   if (inherited_props)
@@ -1894,7 +1895,7 @@ do_plist(svnlook_ctxt_t *c,
               svn_xml_make_open_tag(
                 &sb, pool, svn_xml_normal, "target", "path",
                 svn_fspath__canonicalize(elt->path_or_url, pool),
-                NULL);
+                SVN_VA_NULL);
               SVN_ERR(svn_cmdline__print_xml_prop_hash(&sb, elt->prop_hash,
                                                        !verbose, TRUE,
                                                        pool));
@@ -1921,19 +1922,19 @@ do_plist(svnlook_ctxt_t *c,
               char *revstr = apr_psprintf(pool, "%ld", c->rev_id);
 
               svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops",
-                                    "rev", revstr, NULL);
+                                    "rev", revstr, SVN_VA_NULL);
             }
           else
             {
               svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops",
-                                    "txn", c->txn_name, NULL);
+                                    "txn", c->txn_name, SVN_VA_NULL);
             }
         }
       else
         {
           /* "<target ...>" */
           svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target",
-                                "path", path, NULL);
+                                "path", path, SVN_VA_NULL);
         }
     }
 
@@ -1980,7 +1981,7 @@ do_plist(svnlook_ctxt_t *c,
         }
       else if (xml)
         svn_xml_make_open_tag(&sb, pool, svn_xml_self_closing, "property",
-                              "name", pname, NULL);
+                              "name", pname, SVN_VA_NULL);
       else
         printf("  %s\n", pname);
     }
@@ -2432,12 +2433,16 @@ subcommand_uuid(apr_getopt_t *os, void *
 
 /*** Main. ***/
 
-int
-main(int argc, const char *argv[])
+/*
+ * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
+ * either return an error to be displayed, or set *EXIT_CODE to non-zero and
+ * return SVN_NO_ERROR.
+ */
+static svn_error_t *
+sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
 {
   svn_error_t *err;
   apr_status_t apr_err;
-  apr_pool_t *pool;
 
   const svn_opt_subcommand_desc2_t *subcommand = NULL;
   struct svnlook_opt_state opt_state;
@@ -2446,32 +2451,19 @@ main(int argc, const char *argv[])
   apr_array_header_t *received_opts;
   int i;
 
-  /* Initialize the app. */
-  if (svn_cmdline_init("svnlook", stderr) != EXIT_SUCCESS)
-    return EXIT_FAILURE;
-
-  /* Create our top-level pool.  Use a separate mutexless allocator,
-   * given this application is single threaded.
-   */
-  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
-
   received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
 
   /* Check library versions */
-  err = check_lib_versions();
-  if (err)
-    return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
+  SVN_ERR(check_lib_versions());
 
   /* Initialize the FS library. */
-  err = svn_fs_initialize(pool);
-  if (err)
-    return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
+  SVN_ERR(svn_fs_initialize(pool));
 
   if (argc <= 1)
     {
-      SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
-      svn_pool_destroy(pool);
-      return EXIT_FAILURE;
+      SVN_ERR(subcommand_help(NULL, NULL, pool));
+      *exit_code = EXIT_FAILURE;
+      return SVN_NO_ERROR;
     }
 
   /* Initialize opt_state. */
@@ -2479,9 +2471,7 @@ main(int argc, const char *argv[])
   opt_state.rev = SVN_INVALID_REVNUM;
 
   /* Parse options. */
-  err = svn_cmdline__getopt_init(&os, argc, argv, pool);
-  if (err)
-    return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
+  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
 
   os->interleave = 1;
   while (1)
@@ -2494,9 +2484,9 @@ main(int argc, const char *argv[])
         break;
       else if (apr_err)
         {
-          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
-          svn_pool_destroy(pool);
-          return EXIT_FAILURE;
+          SVN_ERR(subcommand_help(NULL, NULL, pool));
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
 
       /* Stash the option code in an array before parsing it. */
@@ -2511,9 +2501,8 @@ main(int argc, const char *argv[])
             if ((! SVN_IS_VALID_REVNUM(opt_state.rev))
                 || (! digits_end)
                 || *digits_end)
-              SVN_INT_ERR(svn_error_create
-                          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                           _("Invalid revision number supplied")));
+              return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                      _("Invalid revision number supplied"));
           }
           break;
 
@@ -2560,15 +2549,13 @@ main(int argc, const char *argv[])
             opt_state.limit = strtol(opt_arg, &end, 10);
             if (end == opt_arg || *end != '\0')
               {
-                err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                       _("Non-numeric limit argument given"));
-                return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
+                return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                        _("Non-numeric limit argument given"));
               }
             if (opt_state.limit <= 0)
               {
-                err = svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
                                     _("Argument to --limit must be positive"));
-                return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
               }
           }
           break;
@@ -2614,26 +2601,26 @@ main(int argc, const char *argv[])
           break;
 
         default:
-          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
-          svn_pool_destroy(pool);
-          return EXIT_FAILURE;
+          SVN_ERR(subcommand_help(NULL, NULL, pool));
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
 
         }
     }
 
   /* The --transaction and --revision options may not co-exist. */
   if ((opt_state.rev != SVN_INVALID_REVNUM) && opt_state.txn)
-    SVN_INT_ERR(svn_error_create
+    return svn_error_create
                 (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
                  _("The '--transaction' (-t) and '--revision' (-r) arguments "
-                   "cannot co-exist")));
+                   "cannot co-exist"));
 
   /* The --show-inherited-props and --revprop options may not co-exist. */
   if (opt_state.show_inherited_props && opt_state.revprop)
-    SVN_INT_ERR(svn_error_create
+    return svn_error_create
                 (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
                  _("Cannot use the '--show-inherited-props' option with the "
-                   "'--revprop' option")));
+                   "'--revprop' option"));
 
   /* If the user asked for help, then the rest of the arguments are
      the names of subcommands to get help on (if any), or else they're
@@ -2664,9 +2651,9 @@ main(int argc, const char *argv[])
               svn_error_clear
                 (svn_cmdline_fprintf(stderr, pool,
                                      _("Subcommand argument required\n")));
-              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
-              svn_pool_destroy(pool);
-              return EXIT_FAILURE;
+              SVN_ERR(subcommand_help(NULL, NULL, pool));
+              *exit_code = EXIT_FAILURE;
+              return SVN_NO_ERROR;
             }
         }
       else
@@ -2676,15 +2663,13 @@ main(int argc, const char *argv[])
           if (subcommand == NULL)
             {
               const char *first_arg_utf8;
-              err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg,
-                                            pool);
-              if (err)
-                return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
+              SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg,
+                                              pool));
               svn_error_clear(
                 svn_cmdline_fprintf(stderr, pool,
                                     _("Unknown subcommand: '%s'\n"),
                                     first_arg_utf8));
-              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
+              SVN_ERR(subcommand_help(NULL, NULL, pool));
 
               /* Be kind to people who try 'svnlook verify'. */
               if (strcmp(first_arg_utf8, "verify") == 0)
@@ -2694,9 +2679,8 @@ main(int argc, const char *argv[])
                                         _("Try 'svnadmin verify' instead.\n")));
                 }
 
-
-              svn_pool_destroy(pool);
-              return EXIT_FAILURE;
+              *exit_code = EXIT_FAILURE;
+              return SVN_NO_ERROR;
             }
         }
     }
@@ -2715,9 +2699,9 @@ main(int argc, const char *argv[])
       /* Get the repository. */
       if (os->ind < os->argc)
         {
-          SVN_INT_ERR(svn_utf_cstring_to_utf8(&repos_path,
-                                              os->argv[os->ind++],
-                                              pool));
+          SVN_ERR(svn_utf_cstring_to_utf8(&repos_path,
+                                          os->argv[os->ind++],
+                                          pool));
           repos_path = svn_dirent_internal_style(repos_path, pool);
         }
 
@@ -2726,9 +2710,9 @@ main(int argc, const char *argv[])
           svn_error_clear
             (svn_cmdline_fprintf(stderr, pool,
                                  _("Repository argument required\n")));
-          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
-          svn_pool_destroy(pool);
-          return EXIT_FAILURE;
+          SVN_ERR(subcommand_help(NULL, NULL, pool));
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
       else if (svn_path_is_url(repos_path))
         {
@@ -2736,8 +2720,8 @@ main(int argc, const char *argv[])
             (svn_cmdline_fprintf(stderr, pool,
                                  _("'%s' is a URL when it should be a path\n"),
                                  repos_path));
-          svn_pool_destroy(pool);
-          return EXIT_FAILURE;
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
 
       opt_state.repos_path = repos_path;
@@ -2745,8 +2729,7 @@ main(int argc, const char *argv[])
       /* Get next arg (arg1), if any. */
       if (os->ind < os->argc)
         {
-          SVN_INT_ERR(svn_utf_cstring_to_utf8
-                      (&arg1, os->argv[os->ind++], pool));
+          SVN_ERR(svn_utf_cstring_to_utf8(&arg1, os->argv[os->ind++], pool));
           arg1 = svn_dirent_internal_style(arg1, pool);
         }
       opt_state.arg1 = arg1;
@@ -2754,8 +2737,7 @@ main(int argc, const char *argv[])
       /* Get next arg (arg2), if any. */
       if (os->ind < os->argc)
         {
-          SVN_INT_ERR(svn_utf_cstring_to_utf8
-                      (&arg2, os->argv[os->ind++], pool));
+          SVN_ERR(svn_utf_cstring_to_utf8(&arg2, os->argv[os->ind++], pool));
           arg2 = svn_dirent_internal_style(arg2, pool);
         }
       opt_state.arg2 = arg2;
@@ -2781,7 +2763,7 @@ main(int argc, const char *argv[])
                                           pool);
           svn_opt_format_option(&optstr, badopt, FALSE, pool);
           if (subcommand->name[0] == '-')
-            SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
+            SVN_ERR(subcommand_help(NULL, NULL, pool));
           else
             svn_error_clear
               (svn_cmdline_fprintf
@@ -2789,8 +2771,8 @@ main(int argc, const char *argv[])
                 _("Subcommand '%s' doesn't accept option '%s'\n"
                   "Type 'svnlook help %s' for usage.\n"),
                 subcommand->name, optstr, subcommand->name));
-          svn_pool_destroy(pool);
-          return EXIT_FAILURE;
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
     }
 
@@ -2831,14 +2813,40 @@ main(int argc, const char *argv[])
           err = svn_error_quick_wrap(err,
                                      _("Try 'svnlook help' for more info"));
         }
-      return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
+      return err;
     }
-  else
+
+  return SVN_NO_ERROR;
+}
+
+int
+main(int argc, const char *argv[])
+{
+  apr_pool_t *pool;
+  int exit_code = EXIT_SUCCESS;
+  svn_error_t *err;
+
+  /* Initialize the app. */
+  if (svn_cmdline_init("svnlook", stderr) != EXIT_SUCCESS)
+    return EXIT_FAILURE;
+
+  /* Create our top-level pool.  Use a separate mutexless allocator,
+   * given this application is single threaded.
+   */
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+
+  err = sub_main(&exit_code, argc, argv, pool);
+
+  /* Flush stdout and report if it fails. It would be flushed on exit anyway
+     but this makes sure that output is not silently lost if it fails. */
+  err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
+
+  if (err)
     {
-      svn_pool_destroy(pool);
-      /* Ensure everything is printed on stdout, so the user sees any
-         print errors. */
-      SVN_INT_ERR(svn_cmdline_fflush(stdout));
-      return EXIT_SUCCESS;
+      exit_code = EXIT_FAILURE;
+      svn_cmdline_handle_exit_error(err, NULL, "svnlook: ");
     }
+
+  svn_pool_destroy(pool);
+  return exit_code;
 }

Modified: subversion/branches/log-addressing/subversion/svnmucc/svnmucc.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnmucc/svnmucc.c?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnmucc/svnmucc.c (original)
+++ subversion/branches/log-addressing/subversion/svnmucc/svnmucc.c Wed Nov 27 08:19:45 2013
@@ -59,36 +59,20 @@
 #include "private/svn_ra_private.h"
 #include "private/svn_string_private.h"
 
-static void handle_error(svn_error_t *err, apr_pool_t *pool)
-{
-  if (err)
-    svn_handle_error2(err, stderr, FALSE, "svnmucc: ");
-  svn_error_clear(err);
-  if (pool)
-    svn_pool_destroy(pool);
-  exit(EXIT_FAILURE);
-}
-
-static apr_pool_t *
-init(const char *application)
+/* Version compatibility check */
+static svn_error_t *
+check_lib_versions(void)
 {
-  svn_error_t *err;
-  const svn_version_checklist_t checklist[] = {
-    {"svn_client", svn_client_version},
-    {"svn_subr", svn_subr_version},
-    {"svn_ra", svn_ra_version},
-    {NULL, NULL}
-  };
+  static const svn_version_checklist_t checklist[] =
+    {
+      { "svn_client", svn_client_version },
+      { "svn_subr",   svn_subr_version },
+      { "svn_ra",     svn_ra_version },
+      { NULL, NULL }
+    };
   SVN_VERSION_DEFINE(my_version);
 
-  if (svn_cmdline_init(application, stderr))
-    exit(EXIT_FAILURE);
-
-  err = svn_ver_check_list2(&my_version, checklist, svn_ver_equal);
-  if (err)
-    handle_error(err, NULL);
-
-  return apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+  return svn_ver_check_list2(&my_version, checklist, svn_ver_equal);
 }
 
 static svn_error_t *
@@ -174,8 +158,8 @@ struct operation {
 };
 
 
-/* An iterator (for use via apr_table_do) which sets node properties.
-   REC is a pointer to a struct driver_state. */
+/* Set node properties.
+   ... */
 static svn_error_t *
 change_props(const svn_delta_editor_t *editor,
              void *baton,
@@ -917,10 +901,10 @@ sanitize_url(const char *url,
   return svn_uri_canonicalize(url, pool);
 }
 
+/* Print a usage message on STREAM. */
 static void
-usage(apr_pool_t *pool, int exit_val)
+usage(FILE *stream, apr_pool_t *pool)
 {
-  FILE *stream = exit_val == EXIT_SUCCESS ? stdout : stderr;
   svn_error_clear(svn_cmdline_fputs(
     _("usage: svnmucc ACTION...\n"
       "Subversion multiple URL command client.\n"
@@ -964,16 +948,13 @@ usage(apr_pool_t *pool, int exit_val)
       "  --no-auth-cache        : do not cache authentication tokens\n"
       "  --version              : print version information\n"),
                   stream, pool));
-  svn_pool_destroy(pool);
-  exit(exit_val);
 }
 
-static void
-insufficient(apr_pool_t *pool)
+static svn_error_t *
+insufficient(void)
 {
-  handle_error(svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                "insufficient arguments"),
-               pool);
+  return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                          "insufficient arguments");
 }
 
 static svn_error_t *
@@ -1040,10 +1021,14 @@ sanitize_log_sources(apr_hash_t *revprop
   return SVN_NO_ERROR;
 }
 
-int
-main(int argc, const char **argv)
+/*
+ * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
+ * either return an error to be displayed, or set *EXIT_CODE to non-zero and
+ * return SVN_NO_ERROR.
+ */
+static svn_error_t *
+sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
 {
-  apr_pool_t *pool = init("svnmucc");
   apr_array_header_t *actions = apr_array_make(pool, 1,
                                                sizeof(struct action *));
   const char *anchor = NULL;
@@ -1094,6 +1079,9 @@ main(int argc, const char **argv)
   apr_hash_t *revprops = apr_hash_make(pool);
   int i;
 
+  /* Check library versions */
+  SVN_ERR(check_lib_versions());
+
   config_options = apr_array_make(pool, 0,
                                   sizeof(svn_cmdline__config_argument_t*));
 
@@ -1109,22 +1097,17 @@ main(int argc, const char **argv)
       if (APR_STATUS_IS_EOF(status))
         break;
       if (status != APR_SUCCESS)
-        handle_error(svn_error_wrap_apr(status, "getopt failure"), pool);
+        return svn_error_wrap_apr(status, "getopt failure");
       switch(opt)
         {
         case 'm':
-          err = svn_utf_cstring_to_utf8(&message, arg, pool);
-          if (err)
-            handle_error(err, pool);
+          SVN_ERR(svn_utf_cstring_to_utf8(&message, arg, pool));
           break;
         case 'F':
           {
             const char *arg_utf8;
-            err = svn_utf_cstring_to_utf8(&arg_utf8, arg, pool);
-            if (! err)
-              err = svn_stringbuf_from_file2(&filedata, arg, pool);
-            if (err)
-              handle_error(err, pool);
+            SVN_ERR(svn_utf_cstring_to_utf8(&arg_utf8, arg, pool));
+            SVN_ERR(svn_stringbuf_from_file2(&filedata, arg, pool));
           }
           break;
         case 'u':
@@ -1134,13 +1117,10 @@ main(int argc, const char **argv)
           password = apr_pstrdup(pool, arg);
           break;
         case 'U':
-          err = svn_utf_cstring_to_utf8(&root_url, arg, pool);
-          if (err)
-            handle_error(err, pool);
+          SVN_ERR(svn_utf_cstring_to_utf8(&root_url, arg, pool));
           if (! svn_path_is_url(root_url))
-            handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                           "'%s' is not a URL\n", root_url),
-                         pool);
+            return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                     "'%s' is not a URL\n", root_url);
           root_url = sanitize_url(root_url, pool);
           break;
         case 'r':
@@ -1153,17 +1133,13 @@ main(int argc, const char **argv)
             if ((! SVN_IS_VALID_REVNUM(base_revision))
                 || (! digits_end)
                 || *digits_end)
-              handle_error(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
-                                             NULL,
-                                             _("Invalid revision number '%s'"),
-                                             saved_arg),
-                           pool);
+              return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                       _("Invalid revision number '%s'"),
+                                       saved_arg);
           }
           break;
         case with_revprop_opt:
-          err = svn_opt_parse_revprop(&revprops, arg, pool);
-          if (err != SVN_NO_ERROR)
-            handle_error(err, pool);
+          SVN_ERR(svn_opt_parse_revprop(&revprops, arg, pool));
           break;
         case 'X':
           extra_args_file = apr_pstrdup(pool, arg);
@@ -1178,40 +1154,31 @@ main(int argc, const char **argv)
           trust_server_cert = TRUE;
           break;
         case config_dir_opt:
-          err = svn_utf_cstring_to_utf8(&config_dir, arg, pool);
-          if (err)
-            handle_error(err, pool);
+          SVN_ERR(svn_utf_cstring_to_utf8(&config_dir, arg, pool));
           break;
         case config_inline_opt:
-          err = svn_utf_cstring_to_utf8(&opt_arg, arg, pool);
-          if (err)
-            handle_error(err, pool);
-
-          err = svn_cmdline__parse_config_option(config_options, opt_arg,
-                                                 pool);
-          if (err)
-            handle_error(err, pool);
+          SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, arg, pool));
+          SVN_ERR(svn_cmdline__parse_config_option(config_options, opt_arg,
+                                                   pool));
           break;
         case no_auth_cache_opt:
           no_auth_cache = TRUE;
           break;
         case version_opt:
-          SVN_INT_ERR(display_version(opts, pool));
-          exit(EXIT_SUCCESS);
-          break;
+          SVN_ERR(display_version(opts, pool));
+          return SVN_NO_ERROR;
         case 'h':
         case '?':
-          usage(pool, EXIT_SUCCESS);
-          break;
+          usage(stdout, pool);
+          return SVN_NO_ERROR;
         }
     }
 
   if (non_interactive && force_interactive)
     {
-      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                             _("--non-interactive and --force-interactive "
-                               "are mutually exclusive"));
-      return svn_cmdline_handle_exit_error(err, pool, "svnmucc: ");
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("--non-interactive and --force-interactive "
+                                "are mutually exclusive"));
     }
   else
     non_interactive = !svn_cmdline__be_interactive(non_interactive,
@@ -1219,16 +1186,13 @@ main(int argc, const char **argv)
 
   if (trust_server_cert && !non_interactive)
     {
-      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                             _("--trust-server-cert requires "
-                               "--non-interactive"));
-      return svn_cmdline_handle_exit_error(err, pool, "svnmucc: ");
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("--trust-server-cert requires "
+                                "--non-interactive"));
     }
 
   /* Make sure we have a log message to use. */
-  err = sanitize_log_sources(revprops, message, filedata);
-  if (err)
-    handle_error(err, pool);
+  SVN_ERR(sanitize_log_sources(revprops, message, filedata));
 
   /* Copy the rest of our command-line arguments to an array,
      UTF-8-ing them along the way. */
@@ -1236,10 +1200,9 @@ main(int argc, const char **argv)
   while (opts->ind < opts->argc)
     {
       const char *arg = opts->argv[opts->ind++];
-      if ((err = svn_utf_cstring_to_utf8(&(APR_ARRAY_PUSH(action_args,
-                                                          const char *)),
-                                         arg, pool)))
-        handle_error(err, pool);
+      SVN_ERR(svn_utf_cstring_to_utf8(&APR_ARRAY_PUSH(action_args,
+                                                      const char *),
+                                      arg, pool));
     }
 
   /* If there are extra arguments in a supplementary file, tack those
@@ -1249,14 +1212,10 @@ main(int argc, const char **argv)
       const char *extra_args_file_utf8;
       svn_stringbuf_t *contents, *contents_utf8;
 
-      err = svn_utf_cstring_to_utf8(&extra_args_file_utf8,
-                                    extra_args_file, pool);
-      if (! err)
-        err = svn_stringbuf_from_file2(&contents, extra_args_file_utf8, pool);
-      if (! err)
-        err = svn_utf_stringbuf_to_utf8(&contents_utf8, contents, pool);
-      if (err)
-        handle_error(err, pool);
+      SVN_ERR(svn_utf_cstring_to_utf8(&extra_args_file_utf8,
+                                      extra_args_file, pool));
+      SVN_ERR(svn_stringbuf_from_file2(&contents, extra_args_file_utf8, pool));
+      SVN_ERR(svn_utf_stringbuf_to_utf8(&contents_utf8, contents, pool));
       svn_cstring_split_append(action_args, contents_utf8->data, "\n\r",
                                FALSE, pool);
     }
@@ -1287,13 +1246,16 @@ main(int argc, const char **argv)
         action->action = ACTION_PROPDEL;
       else if (! strcmp(action_string, "?") || ! strcmp(action_string, "h")
                || ! strcmp(action_string, "help"))
-        usage(pool, EXIT_SUCCESS);
+        {
+          usage(stdout, pool);
+          return SVN_NO_ERROR;
+        }
       else
-        handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                       "'%s' is not an action\n",
-                                       action_string), pool);
+        return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                 "'%s' is not an action\n",
+                                 action_string);
       if (++i == action_args->nelts)
-        insufficient(pool);
+        return insufficient();
 
       /* For copies, there should be a revision number next. */
       if (action->action == ACTION_CP)
@@ -1312,12 +1274,12 @@ main(int argc, const char **argv)
 
               action->rev = strtol(rev_str, &end, 0);
               if (*end)
-                handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                               "'%s' is not a revision\n",
-                                               rev_str), pool);
+                return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                         "'%s' is not a revision\n",
+                                         rev_str);
             }
           if (++i == action_args->nelts)
-            insufficient(pool);
+            return insufficient();
         }
       else
         {
@@ -1331,7 +1293,7 @@ main(int argc, const char **argv)
             svn_dirent_internal_style(APR_ARRAY_IDX(action_args, i,
                                                     const char *), pool);
           if (++i == action_args->nelts)
-            insufficient(pool);
+            return insufficient();
         }
 
       /* For propset, propsetf, and propdel, a property name (and
@@ -1342,7 +1304,7 @@ main(int argc, const char **argv)
         {
           action->prop_name = APR_ARRAY_IDX(action_args, i, const char *);
           if (++i == action_args->nelts)
-            insufficient(pool);
+            return insufficient();
 
           if (action->action == ACTION_PROPDEL)
             {
@@ -1354,7 +1316,7 @@ main(int argc, const char **argv)
                 svn_string_create(APR_ARRAY_IDX(action_args, i,
                                                 const char *), pool);
               if (++i == action_args->nelts)
-                insufficient(pool);
+                return insufficient();
             }
           else
             {
@@ -1363,12 +1325,10 @@ main(int argc, const char **argv)
                                                         const char *), pool);
 
               if (++i == action_args->nelts)
-                insufficient(pool);
+                return insufficient();
 
-              err = read_propvalue_file(&(action->prop_value),
-                                        propval_file, pool);
-              if (err)
-                handle_error(err, pool);
+              SVN_ERR(read_propvalue_file(&(action->prop_value),
+                                          propval_file, pool));
 
               action->action = ACTION_PROPSET;
             }
@@ -1377,14 +1337,10 @@ main(int argc, const char **argv)
               && svn_prop_needs_translation(action->prop_name))
             {
               svn_string_t *translated_value;
-              err = svn_subst_translate_string2(&translated_value, NULL,
-                                                NULL, action->prop_value, NULL,
-                                                FALSE, pool, pool);
-              if (err)
-                handle_error(
-                    svn_error_quick_wrap(err,
-                                         "Error normalizing property value"),
-                    pool);
+              SVN_ERR_W(svn_subst_translate_string2(&translated_value, NULL,
+                                                    NULL, action->prop_value,
+                                                    NULL, FALSE, pool, pool),
+                        "Error normalizing property value");
               action->prop_value = translated_value;
             }
         }
@@ -1412,10 +1368,10 @@ main(int argc, const char **argv)
           if (! svn_path_is_url(url))
             {
               if (! root_url)
-                handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                               "'%s' is not a URL, and "
-                                               "--root-url (-U) not provided\n",
-                                               url), pool);
+                return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                         "'%s' is not a URL, and "
+                                         "--root-url (-U) not provided\n",
+                                         url);
               /* ### These relpaths are already URI-encoded. */
               url = apr_pstrcat(pool, root_url, "/",
                                 svn_relpath_canonicalize(url, pool),
@@ -1437,20 +1393,23 @@ main(int argc, const char **argv)
             {
               anchor = svn_uri_get_longest_ancestor(anchor, url, pool);
               if (!anchor || !anchor[0])
-                handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                               "URLs in the action list do not "
-                                               "share a common ancestor"),
-                             pool);
+                return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                         "URLs in the action list do not "
+                                         "share a common ancestor");
             }
 
           if ((++i == action_args->nelts) && (j + 1 < num_url_args))
-            insufficient(pool);
+            return insufficient();
         }
       APR_ARRAY_PUSH(actions, struct action *) = action;
     }
 
   if (! actions->nelts)
-    usage(pool, EXIT_FAILURE);
+    {
+      *exit_code = EXIT_FAILURE;
+      usage(stderr, pool);
+      return SVN_NO_ERROR;
+    }
 
   if ((err = execute(actions, anchor, revprops, username, password,
                      config_dir, config_options, non_interactive,
@@ -1461,12 +1420,40 @@ main(int argc, const char **argv)
                                    _("Authentication failed and interactive"
                                      " prompting is disabled; see the"
                                      " --force-interactive option"));
-      handle_error(err, pool);
+      return err;
     }
 
-  /* Ensure that stdout is flushed, so the user will see all results. */
-  svn_error_clear(svn_cmdline_fflush(stdout));
+  return SVN_NO_ERROR;
+}
+
+int
+main(int argc, const char *argv[])
+{
+  apr_pool_t *pool;
+  int exit_code = EXIT_SUCCESS;
+  svn_error_t *err;
+
+  /* Initialize the app. */
+  if (svn_cmdline_init("svnmucc", stderr) != EXIT_SUCCESS)
+    return EXIT_FAILURE;
+
+  /* Create our top-level pool.  Use a separate mutexless allocator,
+   * given this application is single threaded.
+   */
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+
+  err = sub_main(&exit_code, argc, argv, pool);
+
+  /* Flush stdout and report if it fails. It would be flushed on exit anyway
+     but this makes sure that output is not silently lost if it fails. */
+  err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
+
+  if (err)
+    {
+      exit_code = EXIT_FAILURE;
+      svn_cmdline_handle_exit_error(err, NULL, "svnmucc: ");
+    }
 
   svn_pool_destroy(pool);
-  return EXIT_SUCCESS;
+  return exit_code;
 }

Modified: subversion/branches/log-addressing/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnrdump/svnrdump.c?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/log-addressing/subversion/svnrdump/svnrdump.c Wed Nov 27 08:19:45 2013
@@ -666,21 +666,6 @@ version(const char *progname,
 }
 
 
-/* Report and clear the error ERR, and return EXIT_FAILURE. */
-#define EXIT_ERROR(err)                                                 \
-  svn_cmdline_handle_exit_error(err, NULL, "svnrdump: ")
-
-/* A redefinition of the public SVN_INT_ERR macro, that suppresses the
- * error message if it is SVN_ERR_IO_PIPE_WRITE_ERROR, and with the
- * program name 'svnrdump' instead of 'svn'. */
-#undef SVN_INT_ERR
-#define SVN_INT_ERR(expr)                                        \
-  do {                                                           \
-    svn_error_t *svn_err__temp = (expr);                         \
-    if (svn_err__temp)                                           \
-      return EXIT_ERROR(svn_err__temp);                          \
-  } while (0)
-
 /* Handle the "dump" subcommand.  Implements `svn_opt_subcommand_t'.  */
 static svn_error_t *
 dump_cmd(apr_getopt_t *os,
@@ -829,8 +814,13 @@ validate_and_resolve_revisions(opt_baton
   return SVN_NO_ERROR;
 }
 
-static int
-sub_main(int argc, const char *argv[], apr_pool_t *pool)
+/*
+ * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
+ * either return an error to be displayed, or set *EXIT_CODE to non-zero and
+ * return SVN_NO_ERROR.
+ */
+static svn_error_t *
+sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
 {
   svn_error_t *err = SVN_NO_ERROR;
   const svn_opt_subcommand_desc2_t *subcommand = NULL;
@@ -854,7 +844,7 @@ sub_main(int argc, const char *argv[], a
   opt_baton->end_revision.kind = svn_opt_revision_unspecified;
   opt_baton->url = NULL;
 
-  SVN_INT_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
+  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
 
   os->interleave = TRUE; /* Options and arguments can be interleaved */
 
@@ -894,8 +884,9 @@ sub_main(int argc, const char *argv[], a
         break;
       if (status != APR_SUCCESS)
         {
-          SVN_INT_ERR(usage(argv[0], pool));
-          return EXIT_FAILURE;
+          SVN_ERR(usage(argv[0], pool));
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
 
       /* Stash the option code in an array before parsing it. */
@@ -908,11 +899,10 @@ sub_main(int argc, const char *argv[], a
             /* Make sure we've not seen -r already. */
             if (opt_baton->start_revision.kind != svn_opt_revision_unspecified)
               {
-                err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                       _("Multiple revision arguments "
-                                         "encountered; try '-r N:M' instead "
-                                         "of '-r N -r M'"));
-                return EXIT_ERROR(err);
+                return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                        _("Multiple revision arguments "
+                                          "encountered; try '-r N:M' instead "
+                                          "of '-r N -r M'"));
               }
             /* Parse the -r argument. */
             if (svn_opt_parse_revision(&(opt_baton->start_revision),
@@ -920,12 +910,10 @@ sub_main(int argc, const char *argv[], a
                                        opt_arg, pool) != 0)
               {
                 const char *utf8_opt_arg;
-                err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
-                if (! err)
-                  err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                          _("Syntax error in revision "
-                                            "argument '%s'"), utf8_opt_arg);
-                return EXIT_ERROR(err);
+                SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+                return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                         _("Syntax error in revision "
+                                           "argument '%s'"), utf8_opt_arg);
               }
           }
           break;
@@ -942,10 +930,10 @@ sub_main(int argc, const char *argv[], a
           opt_baton->help = TRUE;
           break;
         case opt_auth_username:
-          SVN_INT_ERR(svn_utf_cstring_to_utf8(&username, opt_arg, pool));
+          SVN_ERR(svn_utf_cstring_to_utf8(&username, opt_arg, pool));
           break;
         case opt_auth_password:
-          SVN_INT_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool));
+          SVN_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool));
           break;
         case opt_auth_nocache:
           no_auth_cache = TRUE;
@@ -968,9 +956,9 @@ sub_main(int argc, const char *argv[], a
                     apr_array_make(pool, 1,
                                    sizeof(svn_cmdline__config_argument_t*));
 
-            SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
-            SVN_INT_ERR(svn_cmdline__parse_config_option(config_options,
-                                                         opt_arg, pool));
+            SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
+            SVN_ERR(svn_cmdline__parse_config_option(config_options,
+                                                     opt_arg, pool));
         }
     }
 
@@ -978,10 +966,9 @@ sub_main(int argc, const char *argv[], a
    * exclusive. */
   if (non_interactive && force_interactive)
     {
-      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                             _("--non-interactive and --force-interactive "
-                               "are mutually exclusive"));
-      return EXIT_ERROR(err);
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("--non-interactive and --force-interactive "
+                                "are mutually exclusive"));
     }
 
   if (opt_baton->help)
@@ -1006,8 +993,9 @@ sub_main(int argc, const char *argv[], a
 
           else
             {
-              SVN_INT_ERR(help_cmd(NULL, NULL, pool));
-              return EXIT_FAILURE;
+              SVN_ERR(help_cmd(NULL, NULL, pool));
+              *exit_code = EXIT_FAILURE;
+              return SVN_NO_ERROR;
             }
         }
       else
@@ -1019,15 +1007,15 @@ sub_main(int argc, const char *argv[], a
           if (subcommand == NULL)
             {
               const char *first_arg_utf8;
-              err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, pool);
-              if (err)
-                return EXIT_ERROR(err);
+              SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg,
+                                              pool));
               svn_error_clear(
                 svn_cmdline_fprintf(stderr, pool,
                                     _("Unknown subcommand: '%s'\n"),
                                     first_arg_utf8));
-              SVN_INT_ERR(help_cmd(NULL, NULL, pool));
-              return EXIT_FAILURE;
+              SVN_ERR(help_cmd(NULL, NULL, pool));
+              *exit_code = EXIT_FAILURE;
+              return SVN_NO_ERROR;
             }
         }
     }
@@ -1052,56 +1040,55 @@ sub_main(int argc, const char *argv[], a
                                           subcommand, pool);
           svn_opt_format_option(&optstr, badopt, FALSE, pool);
           if (subcommand->name[0] == '-')
-            SVN_INT_ERR(help_cmd(NULL, NULL, pool));
+            SVN_ERR(help_cmd(NULL, NULL, pool));
           else
             svn_error_clear(svn_cmdline_fprintf(
                                 stderr, pool,
                                 _("Subcommand '%s' doesn't accept option '%s'\n"
                                   "Type 'svnrdump help %s' for usage.\n"),
                                 subcommand->name, optstr, subcommand->name));
-          return EXIT_FAILURE;
+          *exit_code = EXIT_FAILURE;
+          return SVN_NO_ERROR;
         }
     }
 
   if (strcmp(subcommand->name, "--version") == 0)
     {
-      SVN_INT_ERR(version(argv[0], opt_baton->quiet, pool));
-      return EXIT_SUCCESS;
+      SVN_ERR(version(argv[0], opt_baton->quiet, pool));
+      return SVN_NO_ERROR;
     }
 
   if (strcmp(subcommand->name, "help") == 0)
     {
-      SVN_INT_ERR(help_cmd(os, opt_baton, pool));
-      return EXIT_SUCCESS;
+      SVN_ERR(help_cmd(os, opt_baton, pool));
+      return SVN_NO_ERROR;
     }
 
   /* --trust-server-cert can only be used with --non-interactive */
   if (trust_server_cert && !non_interactive)
     {
-      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                             _("--trust-server-cert requires "
-                               "--non-interactive"));
-      return EXIT_ERROR(err);
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("--trust-server-cert requires "
+                                "--non-interactive"));
     }
 
   /* Expect one more non-option argument:  the repository URL. */
   if (os->ind != os->argc - 1)
     {
-      SVN_INT_ERR(usage(argv[0], pool));
-      return EXIT_FAILURE;
+      SVN_ERR(usage(argv[0], pool));
+      *exit_code = EXIT_FAILURE;
+      return SVN_NO_ERROR;
     }
   else
     {
       const char *repos_url;
 
-      SVN_INT_ERR(svn_utf_cstring_to_utf8(&repos_url,
-                                          os->argv[os->ind], pool));
+      SVN_ERR(svn_utf_cstring_to_utf8(&repos_url, os->argv[os->ind], pool));
       if (! svn_path_is_url(repos_url))
         {
-          err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, 0,
-                                  "Target '%s' is not a URL",
-                                  repos_url);
-          return EXIT_ERROR(err);
+          return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, 0,
+                                   "Target '%s' is not a URL",
+                                   repos_url);
         }
       opt_baton->url = svn_uri_canonicalize(repos_url, pool);
     }
@@ -1122,16 +1109,16 @@ sub_main(int argc, const char *argv[], a
   non_interactive = !svn_cmdline__be_interactive(non_interactive,
                                                  force_interactive);
 
-  SVN_INT_ERR(init_client_context(&(opt_baton->ctx),
-                                  non_interactive,
-                                  username,
-                                  password,
-                                  config_dir,
-                                  opt_baton->url,
-                                  no_auth_cache,
-                                  trust_server_cert,
-                                  config_options,
-                                  pool));
+  SVN_ERR(init_client_context(&(opt_baton->ctx),
+                              non_interactive,
+                              username,
+                              password,
+                              config_dir,
+                              opt_baton->url,
+                              no_auth_cache,
+                              trust_server_cert,
+                              config_options,
+                              pool));
 
   err = svn_client_open_ra_session2(&(opt_baton->session),
                                     opt_baton->url, NULL,
@@ -1152,23 +1139,23 @@ sub_main(int argc, const char *argv[], a
 
   if (err && err->apr_err == SVN_ERR_AUTHN_FAILED && non_interactive)
     {
-      err = svn_error_quick_wrap(err,
-                                 _("Authentication failed and interactive"
-                                   " prompting is disabled; see the"
-                                   " --force-interactive option"));
-      return EXIT_ERROR(err);
+      return svn_error_quick_wrap(err,
+                                  _("Authentication failed and interactive"
+                                    " prompting is disabled; see the"
+                                    " --force-interactive option"));
     }
   else if (err)
-    return EXIT_ERROR(err);
+    return err;
   else
-    return EXIT_SUCCESS;
+    return SVN_NO_ERROR;
 }
 
 int
 main(int argc, const char *argv[])
 {
   apr_pool_t *pool;
-  int exit_code;
+  int exit_code = EXIT_SUCCESS;
+  svn_error_t *err;
 
   /* Initialize the app. */
   if (svn_cmdline_init("svnrdump", stderr) != EXIT_SUCCESS)
@@ -1179,7 +1166,17 @@ main(int argc, const char *argv[])
    */
   pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
-  exit_code = sub_main(argc, argv, pool);
+  err = sub_main(&exit_code, argc, argv, pool);
+
+  /* Flush stdout and report if it fails. It would be flushed on exit anyway
+     but this makes sure that output is not silently lost if it fails. */
+  err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
+
+  if (err)
+    {
+      exit_code = EXIT_FAILURE;
+      svn_cmdline_handle_exit_error(err, NULL, "svnrdump: ");
+    }
 
   svn_pool_destroy(pool);
   return exit_code;

Modified: subversion/branches/log-addressing/subversion/svnserve/logger.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnserve/logger.c?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnserve/logger.c (original)
+++ subversion/branches/log-addressing/subversion/svnserve/logger.c Wed Nov 27 08:19:45 2013
@@ -42,8 +42,8 @@
 
 struct logger_t
 {
-  /* actual log file object */
-  apr_file_t *file;
+  /* actual log file / stream object */
+  svn_stream_t *stream;
 
   /* mutex used to serialize access to this structure */
   svn_mutex__t *mutex;
@@ -62,18 +62,39 @@ static apr_status_t cleanup_logger(void 
 }
 
 svn_error_t *
+logger__create_for_stderr(logger_t **logger,
+                          apr_pool_t *pool)
+{
+  logger_t *result = apr_pcalloc(pool, sizeof(*result));
+  result->pool = svn_pool_create(NULL);
+  
+  SVN_ERR(svn_stream_for_stderr(&result->stream, pool));
+  SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool));
+
+  apr_pool_cleanup_register(pool, result, cleanup_logger,
+                            apr_pool_cleanup_null);
+  
+  *logger = result;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 logger__create(logger_t **logger,
                const char *filename,
                apr_pool_t *pool)
 {
   logger_t *result = apr_pcalloc(pool, sizeof(*result));
-
-  SVN_ERR(svn_io_file_open(&result->file, filename,
+  apr_file_t *file;
+  
+  SVN_ERR(svn_io_file_open(&file, filename,
                            APR_WRITE | APR_CREATE | APR_APPEND,
                            APR_OS_DEFAULT, pool));
   SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool));
-  result->pool = svn_pool_create(NULL);
 
+  result->stream = svn_stream_from_aprfile2(file, FALSE,  pool);
+  result->pool = svn_pool_create(NULL);
+  
   apr_pool_cleanup_register(pool, result, cleanup_logger,
                             apr_pool_cleanup_null);
   
@@ -130,12 +151,12 @@ logger__log_error(logger_t *logger,
           }
           strcpy(errstr + len, APR_EOL_STR);
           len += strlen(APR_EOL_STR);
-          svn_error_clear(svn_io_file_write(logger->file, errstr, &len,
-                                            logger->pool));
+          svn_error_clear(svn_stream_write(logger->stream, errstr, &len));
 
           continuation = "-";
           err = err->child;
         }
+
       svn_pool_clear(logger->pool);
       
       svn_error_clear(svn_mutex__unlock(logger->mutex, SVN_NO_ERROR));
@@ -148,7 +169,6 @@ logger__write(logger_t *logger,
               apr_size_t len)
 {
   SVN_MUTEX__WITH_LOCK(logger->mutex,
-                       svn_io_file_write(logger->file, errstr, &len,
-                                         logger->pool));
+                       svn_stream_write(logger->stream, errstr, &len));
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/log-addressing/subversion/svnserve/logger.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnserve/logger.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnserve/logger.h (original)
+++ subversion/branches/log-addressing/subversion/svnserve/logger.h Wed Nov 27 08:19:45 2013
@@ -37,6 +37,14 @@ extern "C" {
  */
 typedef struct logger_t logger_t;
 
+/* In POOL, create a writer object that will write log messages to stderr
+ * and return it in *LOGGER.  The log file will not add any buffering
+ * on top of stderr.
+ */
+svn_error_t *
+logger__create_for_stderr(logger_t **logger,
+                          apr_pool_t *pool);
+
 /* In POOL, create a writer object for log file FILENAME and return it
  * in *LOGGER.  The log file will be flushed & closed when POOL gets
  * cleared or destroyed.

Modified: subversion/branches/log-addressing/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnserve/serve.c?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnserve/serve.c (original)
+++ subversion/branches/log-addressing/subversion/svnserve/serve.c Wed Nov 27 08:19:45 2013
@@ -202,12 +202,13 @@ log_authz_denied(const char *path,
   return logger__write(b->logger, line, strlen(line));
 }
 
-/* If CFG specifies a path to the password DB, read that DB and store it
- * in REPOSITORY->PWDB.
+/* If CFG specifies a path to the password DB, read that DB through
+ * CONFIG_POOL and store it in REPOSITORY->PWDB.
  */
 static svn_error_t *
 load_pwdb_config(repository_t *repository,
                  svn_config_t *cfg,
+                 svn_repos__config_pool_t *config_pool,
                  apr_pool_t *pool)
 {
   const char *pwdb_path;
@@ -223,8 +224,9 @@ load_pwdb_config(repository_t *repositor
       pwdb_path = svn_dirent_internal_style(pwdb_path, pool);
       pwdb_path = svn_dirent_join(repository->base, pwdb_path, pool);
 
-      err = svn_config_read3(&repository->pwdb, pwdb_path, TRUE,
-                             FALSE, FALSE, pool);
+      err = svn_repos__config_pool_get(&repository->pwdb, NULL, config_pool,
+                                       pwdb_path, TRUE, FALSE,
+                                       repository->repos, pool);
       if (err)
         {
           /* Because it may be possible to read the pwdb file with some
@@ -281,8 +283,8 @@ canonicalize_access_file(const char **ac
   return SVN_NO_ERROR;
 }
 
-/* Load the authz database for the listening server based on the
-   entries in the SERVER struct.
+/* Load the authz database for the listening server through AUTHZ_POOL
+   based on the entries in the SERVER struct.
 
    SERVER and CONN must not be NULL. The real errors will be logged with
    SERVER and CONN but return generic errors to the client. */
@@ -290,6 +292,7 @@ static svn_error_t *
 load_authz_config(repository_t *repository,
                   const char *repos_root,
                   svn_config_t *cfg,
+                  svn_repos__authz_pool_t *authz_pool,
                   apr_pool_t *pool)
 {
   const char *authzdb_path;
@@ -317,8 +320,9 @@ load_authz_config(repository_t *reposito
                                        repos_root, pool);
 
       if (!err)
-        err = svn_repos_authz_read2(&repository->authzdb, authzdb_path,
-                                    groupsdb_path, TRUE, pool);
+        err = svn_repos__authz_pool_get(&repository->authzdb, authz_pool,
+                                        authzdb_path, groupsdb_path, TRUE,
+                                        repository->repos, pool);
 
       if (err)
         return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, err, NULL);
@@ -3258,20 +3262,41 @@ repos_path_valid(const char *path)
   return TRUE;
 }
 
+/* APR pool cleanup callback that resets the REPOS pointer in ARG. */
+static apr_status_t
+reset_repos(void *arg)
+{
+  repository_t *repository = arg;
+  repository->repos = NULL;
+
+  return APR_SUCCESS;
+}
+
 /* Look for the repository given by URL, using ROOT as the virtual
  * repository root.  If we find one, fill in the repos, fs, repos_url,
- * and fs_path fields of REPOSITORY.  Set REPOSITORY->repos's client
- * capabilities to CAPABILITIES, which must be at least as long-lived
- * as POOL, and whose elements are SVN_RA_CAPABILITY_*.  VHOST and
- * READ_ONLY flags are the same as in the server baton.
+ * and fs_path fields of REPOSITORY.  REPOSITORY->REPO will be allocated
+ * SCRATCH_POOL because repositories may be closed and re-opened during
+ * the lifetime of a connection.   All other parts in REPOSITORY must
+ * be allocated in RESULT_POOL.  VHOST and READ_ONLY flags are the same
+ * as in the server baton.
+ *
+ * CONFIG_POOL, AUTHZ_POOL and REPOS_POOL shall be used to load any
+ * object of the respective type.
  */
-static svn_error_t *find_repos(const char *url, const char *root,
-                               svn_boolean_t vhost, svn_boolean_t read_only,
-                               svn_config_t *cfg, repository_t *repository,
-                               const apr_array_header_t *capabilities,
-                               apr_pool_t *pool)
+static svn_error_t *
+find_repos(const char *url,
+           const char *root,
+           svn_boolean_t vhost,
+           svn_boolean_t read_only,
+           svn_config_t *cfg,
+           repository_t *repository,
+           svn_repos__config_pool_t *config_pool,
+           svn_repos__authz_pool_t *authz_pool,
+           svn_repos__repos_pool_t *repos_pool,
+           apr_pool_t *result_pool,
+           apr_pool_t *scratch_pool)
 {
-  const char *path, *full_path, *repos_root, *fs_path, *hooks_env, *val;
+  const char *path, *full_path, *fs_path, *hooks_env;
   svn_stringbuf_t *url_buf;
 
   /* Skip past the scheme and authority part. */
@@ -3286,8 +3311,8 @@ static svn_error_t *find_repos(const cha
       if (path == NULL)
         path = "";
     }
-  path = svn_relpath_canonicalize(path, pool);
-  path = svn_path_uri_decode(path, pool);
+  path = svn_relpath_canonicalize(path, result_pool);
+  path = svn_path_uri_decode(path, result_pool);
 
   /* Ensure that it isn't possible to escape the root by disallowing
      '..' segments. */
@@ -3296,72 +3321,86 @@ static svn_error_t *find_repos(const cha
                             "Couldn't determine repository path");
 
   /* Join the server-configured root with the client path. */
-  full_path = svn_dirent_join(svn_dirent_canonicalize(root, pool),
-                              path, pool);
+  full_path = svn_dirent_join(svn_dirent_canonicalize(root, result_pool),
+                              path, result_pool);
 
   /* Search for a repository in the full path. */
-  repos_root = svn_repos_find_root_path(full_path, pool);
-  if (!repos_root)
+  repository->repos_root = svn_repos_find_root_path(full_path, result_pool);
+  if (!repository->repos_root)
     return svn_error_createf(SVN_ERR_RA_SVN_REPOS_NOT_FOUND, NULL,
                              "No repository found in '%s'", url);
 
   /* Open the repository and fill in b with the resulting information. */
-  SVN_ERR(svn_repos_open2(&repository->repos, repos_root,
-                          repository->fs_config, pool));
+  SVN_ERR(svn_repos__repos_pool_get(&repository->repos, repos_pool,
+                                    repository->repos_root, "",
+                                    scratch_pool));
   SVN_ERR(svn_repos_remember_client_capabilities(repository->repos,
-                                                 capabilities));
+                                                 repository->capabilities));
   repository->fs = svn_repos_fs(repository->repos);
-  fs_path = full_path + strlen(repos_root);
-  repository->fs_path = svn_stringbuf_create(*fs_path ? fs_path : "/", pool);
-  url_buf = svn_stringbuf_create(url, pool);
+  fs_path = full_path + strlen(repository->repos_root);
+  repository->fs_path = svn_stringbuf_create(*fs_path ? fs_path : "/",
+                                             result_pool);
+  url_buf = svn_stringbuf_create(url, result_pool);
   svn_path_remove_components(url_buf,
                         svn_path_component_count(repository->fs_path->data));
   repository->repos_url = url_buf->data;
-  repository->authz_repos_name = svn_dirent_is_child(root, repos_root, pool);
+  repository->authz_repos_name = svn_dirent_is_child(root,
+                                                     repository->repos_root,
+                                                     result_pool);
   if (repository->authz_repos_name == NULL)
-    repository->repos_name = svn_dirent_basename(repos_root, pool);
+    repository->repos_name = svn_dirent_basename(repository->repos_root,
+                                                 result_pool);
   else
     repository->repos_name = repository->authz_repos_name;
-  repository->repos_name = svn_path_uri_encode(repository->repos_name, pool);
+  repository->repos_name = svn_path_uri_encode(repository->repos_name,
+                                               result_pool);
+
+  /* Reset the REPOS pointer as soon as the REPOS will be returned to the
+     REPOS_POOL. */
+  apr_pool_cleanup_register(scratch_pool, repository, reset_repos,
+                            apr_pool_cleanup_null);
 
   /* If the svnserve configuration has not been loaded then load it from the
    * repository. */
   if (NULL == cfg)
     {
-      repository->base = svn_repos_conf_dir(repository->repos, pool);
+      repository->base = svn_repos_conf_dir(repository->repos, result_pool);
 
-      SVN_ERR(svn_config_read3(&cfg,
-                               svn_repos_svnserve_conf(repository->repos,
-                                                       pool),
-                               FALSE, /* must_exist */
-                               FALSE, /* section_names_case_sensitive */
-                               FALSE, /* option_names_case_sensitive */
-                               pool));
+      SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+                                         svn_repos_svnserve_conf
+                                            (repository->repos, result_pool), 
+                                         FALSE, FALSE, repository->repos,
+                                         result_pool));
     }
 
-  SVN_ERR(load_pwdb_config(repository, cfg, pool));
-  SVN_ERR(load_authz_config(repository, repos_root, cfg, pool));
+  SVN_ERR(load_pwdb_config(repository, cfg, config_pool, result_pool));
+  SVN_ERR(load_authz_config(repository, repository->repos_root, cfg,
+                            authz_pool, result_pool));
 
 #ifdef SVN_HAVE_SASL
-  /* Should we use Cyrus SASL? */
-  SVN_ERR(svn_config_get_bool(cfg, &repository->use_sasl,
-                              SVN_CONFIG_SECTION_SASL,
-                              SVN_CONFIG_OPTION_USE_SASL, FALSE));
-
-  svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL,
-                 SVN_CONFIG_OPTION_MIN_SSF, "0");
-  SVN_ERR(svn_cstring_atoui(&repository->min_ssf, val));
-
-  svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL,
-                 SVN_CONFIG_OPTION_MAX_SSF, "256");
-  SVN_ERR(svn_cstring_atoui(&repository->max_ssf, val));
+    {
+      const char *val;
 
+      /* Should we use Cyrus SASL? */
+      SVN_ERR(svn_config_get_bool(cfg, &repository->use_sasl,
+                                  SVN_CONFIG_SECTION_SASL,
+                                  SVN_CONFIG_OPTION_USE_SASL, FALSE));
+
+      svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL,
+                    SVN_CONFIG_OPTION_MIN_SSF, "0");
+      SVN_ERR(svn_cstring_atoui(&repository->min_ssf, val));
+
+      svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL,
+                    SVN_CONFIG_OPTION_MAX_SSF, "256");
+      SVN_ERR(svn_cstring_atoui(&repository->max_ssf, val));
+    }
 #endif
 
   /* Use the repository UUID as the default realm. */
-  SVN_ERR(svn_fs_get_uuid(repository->fs, &repository->realm, pool));
+  SVN_ERR(svn_fs_get_uuid(repository->fs, &repository->realm, result_pool));
   svn_config_get(cfg, &repository->realm, SVN_CONFIG_SECTION_GENERAL,
                  SVN_CONFIG_OPTION_REALM, repository->realm);
+  repository->realm = apr_pstrdup(result_pool, repository->realm);
 
   /* Make sure it's possible for the client to authenticate.  Note
      that this doesn't take into account any authz configuration read
@@ -3373,8 +3412,9 @@ static svn_error_t *find_repos(const cha
   svn_config_get(cfg, &hooks_env, SVN_CONFIG_SECTION_GENERAL,
                  SVN_CONFIG_OPTION_HOOKS_ENV, NULL);
   if (hooks_env)
-    hooks_env = svn_dirent_internal_style(hooks_env, pool);
-  SVN_ERR(svn_repos_hooks_setenv(repository->repos, hooks_env, pool));
+    hooks_env = svn_dirent_internal_style(hooks_env, scratch_pool);
+
+  repository->hooks_env = apr_pstrdup(result_pool, hooks_env);
 
   return SVN_NO_ERROR;
 }
@@ -3546,46 +3586,44 @@ get_client_info(svn_ra_svn_conn_t *conn,
   return client_info;
 }
 
-svn_error_t *serve(svn_ra_svn_conn_t *conn, serve_params_t *params,
-                   apr_pool_t *pool)
+/* Construct the server baton for CONN using PARAMS and return it in *BATON.
+ * It's lifetime is the same as that of CONN.  SCRATCH_POOL
+ */
+static svn_error_t *
+construct_server_baton(server_baton_t **baton,
+                       svn_ra_svn_conn_t *conn,
+                       serve_params_t *params,
+                       apr_pool_t *scratch_pool)
 {
   svn_error_t *err, *io_err;
   apr_uint64_t ver;
-  const char *uuid, *client_url, *ra_client_string, *client_string;
-  apr_array_header_t *caplist, *cap_words;
-  server_baton_t b = { 0 };
-  repository_t repository = { 0 };
-  fs_warning_baton_t warn_baton;
-  svn_stringbuf_t *cap_log = svn_stringbuf_create_empty(pool);
-
-  repository.username_case = params->username_case;
-  repository.base = params->base;
-  repository.pwdb = NULL;
-  repository.authzdb = NULL;
-  repository.realm = NULL;
-  repository.use_sasl = FALSE;
-
-  b.read_only = params->read_only;
-  b.pool = pool;
-  b.vhost = params->vhost;
-
-  b.repository = &repository;
-  b.logger = params->logger;
-  b.client_info = get_client_info(conn, params, pool);
-
-  /* construct FS configuration parameters */
-  repository.fs_config = apr_hash_make(pool);
-  svn_hash_sets(repository.fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
-                params->cache_txdeltas ? "1" :"0");
-  svn_hash_sets(repository.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
-                params->cache_fulltexts ? "1" :"0");
-  svn_hash_sets(repository.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                params->cache_revprops ? "1" :"0");
+  const char *client_url, *ra_client_string, *client_string;
+  apr_array_header_t *caplist;
+  apr_pool_t *conn_pool = svn_ra_svn__get_pool(conn);
+  server_baton_t *b = apr_pcalloc(conn_pool, sizeof(*b));
+  fs_warning_baton_t *warn_baton;
+  svn_stringbuf_t *cap_log = svn_stringbuf_create_empty(scratch_pool);
+  
+  b->repository = apr_pcalloc(conn_pool, sizeof(*b->repository));
+  b->repository->username_case = params->username_case;
+  b->repository->base = params->base;
+  b->repository->pwdb = NULL;
+  b->repository->authzdb = NULL;
+  b->repository->realm = NULL;
+  b->repository->use_sasl = FALSE;
+
+  b->read_only = params->read_only;
+  b->pool = conn_pool;
+  b->vhost = params->vhost;
+
+  b->logger = params->logger;
+  b->client_info = get_client_info(conn, params, conn_pool);
 
   /* Send greeting.  We don't support version 1 any more, so we can
    * send an empty mechlist. */
   if (params->compression_level > 0)
-    SVN_ERR(svn_ra_svn__write_cmd_response(conn, pool, "nn()(wwwwwwwwwww)",
+    SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool,
+                                           "nn()(wwwwwwwwwww)",
                                            (apr_uint64_t) 2, (apr_uint64_t) 2,
                                            SVN_RA_SVN_CAP_EDIT_PIPELINE,
                                            SVN_RA_SVN_CAP_SVNDIFF1,
@@ -3600,7 +3638,8 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
                                            SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE
                                            ));
   else
-    SVN_ERR(svn_ra_svn__write_cmd_response(conn, pool, "nn()(wwwwwwwwww)",
+    SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool,
+                                           "nn()(wwwwwwwwww)",
                                            (apr_uint64_t) 2, (apr_uint64_t) 2,
                                            SVN_RA_SVN_CAP_EDIT_PIPELINE,
                                            SVN_RA_SVN_CAP_ABSENT_ENTRIES,
@@ -3617,14 +3656,14 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
   /* Read client response, which we assume to be in version 2 format:
    * version, capability list, and client URL; then we do an auth
    * request. */
-  SVN_ERR(svn_ra_svn__read_tuple(conn, pool, "nlc?c(?c)",
+  SVN_ERR(svn_ra_svn__read_tuple(conn, scratch_pool, "nlc?c(?c)",
                                  &ver, &caplist, &client_url,
                                  &ra_client_string,
                                  &client_string));
   if (ver != 2)
     return SVN_NO_ERROR;
 
-  client_url = svn_uri_canonicalize(client_url, pool);
+  client_url = svn_uri_canonicalize(client_url, conn_pool);
   SVN_ERR(svn_ra_svn_set_capabilities(conn, caplist));
 
   /* All released versions of Subversion support edit-pipeline,
@@ -3645,14 +3684,15 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
     int i;
     svn_ra_svn_item_t *item;
 
-    cap_words = apr_array_make(pool, 1, sizeof(const char *));
+    b->repository->capabilities = apr_array_make(conn_pool, 1,
+                                                 sizeof(const char *));
     for (i = 0; i < caplist->nelts; i++)
       {
         item = &APR_ARRAY_IDX(caplist, i, svn_ra_svn_item_t);
         /* ra_svn_set_capabilities() already type-checked for us */
         if (strcmp(item->u.word, SVN_RA_SVN_CAP_MERGEINFO) == 0)
           {
-            APR_ARRAY_PUSH(cap_words, const char *)
+            APR_ARRAY_PUSH(b->repository->capabilities, const char *)
               = SVN_RA_CAPABILITY_MERGEINFO;
           }
         /* Save for operational log. */
@@ -3662,57 +3702,40 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
       }
   }
 
-  err = handle_config_error(find_repos(client_url, params->root,
-                                       b.vhost, b.read_only,
-                                       params->cfg, b.repository,
-                                       cap_words, pool), &b);
+  err = handle_config_error(find_repos(client_url, params->root, b->vhost,
+                                       b->read_only, params->cfg,
+                                       b->repository, params->config_pool,
+                                       params->authz_pool, params->repos_pool, 
+                                       conn_pool, scratch_pool),
+                            b);
   if (!err)
     {
-      if (repository.anon_access == NO_ACCESS
-          && (repository.auth_access == NO_ACCESS
-              || (!b.client_info->tunnel_user && !repository.pwdb
-                  && !repository.use_sasl)))
+      if (b->repository->anon_access == NO_ACCESS
+          && (b->repository->auth_access == NO_ACCESS
+              || (!b->client_info->tunnel_user && !b->repository->pwdb
+                  && !b->repository->use_sasl)))
         err = error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                                    "No access allowed to this repository",
-                                   &b);
+                                   b);
     }
   if (!err)
     {
-      SVN_ERR(auth_request(conn, pool, &b, READ_ACCESS, FALSE));
-      if (current_access(&b) == NO_ACCESS)
+      SVN_ERR(auth_request(conn, scratch_pool, b, READ_ACCESS, FALSE));
+      if (current_access(b) == NO_ACCESS)
         err = error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
-                                   "Not authorized for access", &b);
+                                   "Not authorized for access", b);
     }
   if (err)
     {
-      log_error(err, &b);
-      io_err = svn_ra_svn__write_cmd_failure(conn, pool, err);
+      log_error(err, b);
+      io_err = svn_ra_svn__write_cmd_failure(conn, scratch_pool, err);
       svn_error_clear(err);
       SVN_ERR(io_err);
-      return svn_ra_svn__flush(conn, pool);
+      return svn_ra_svn__flush(conn, scratch_pool);
     }
 
-  /* Log the open. */
-  if (ra_client_string == NULL || ra_client_string[0] == '\0')
-    ra_client_string = "-";
-  else
-    ra_client_string = svn_path_uri_encode(ra_client_string, pool);
-  if (client_string == NULL || client_string[0] == '\0')
-    client_string = "-";
-  else
-    client_string = svn_path_uri_encode(client_string, pool);
-  SVN_ERR(log_command(&b, conn, pool,
-                      "open %" APR_UINT64_T_FMT " cap=(%s) %s %s %s",
-                      ver, cap_log->data,
-                      svn_path_uri_encode(b.repository->fs_path->data, pool),
-                      ra_client_string, client_string));
-
-  warn_baton.server = &b;
-  warn_baton.conn = conn;
-  warn_baton.pool = svn_pool_create(pool);
-  svn_fs_set_warning_func(b.repository->fs, fs_warning_func, &warn_baton);
-
-  SVN_ERR(svn_fs_get_uuid(b.repository->fs, &uuid, pool));
+  SVN_ERR(svn_fs_get_uuid(b->repository->fs, &b->repository->uuid,
+                          conn_pool));
 
   /* We can't claim mergeinfo capability until we know whether the
      repository supports mergeinfo (i.e., is not a 1.4 repository),
@@ -3722,29 +3745,203 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
      the client has sent the url. */
   {
     svn_boolean_t supports_mergeinfo;
-    SVN_ERR(svn_repos_has_capability(repository.repos, &supports_mergeinfo,
-                                     SVN_REPOS_CAPABILITY_MERGEINFO, pool));
-
-    SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(cc(!",
-                                    "success", uuid,
-                                    b.repository->repos_url));
+    SVN_ERR(svn_repos_has_capability(b->repository->repos,
+                                     &supports_mergeinfo,
+                                     SVN_REPOS_CAPABILITY_MERGEINFO,
+                                     scratch_pool));
+
+    SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w(cc(!",
+                                    "success", b->repository->uuid,
+                                    b->repository->repos_url));
     if (supports_mergeinfo)
-      SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_CAP_MERGEINFO));
-    SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
+      SVN_ERR(svn_ra_svn__write_word(conn, scratch_pool,
+                                     SVN_RA_SVN_CAP_MERGEINFO));
+    SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "!))"));
+    SVN_ERR(svn_ra_svn__flush(conn, scratch_pool));
   }
 
+  /* Log the open. */
+  if (ra_client_string == NULL || ra_client_string[0] == '\0')
+    ra_client_string = "-";
+  else
+    ra_client_string = svn_path_uri_encode(ra_client_string, scratch_pool);
+  if (client_string == NULL || client_string[0] == '\0')
+    client_string = "-";
+  else
+    client_string = svn_path_uri_encode(client_string, scratch_pool);
+  SVN_ERR(log_command(b, conn, scratch_pool,
+                      "open %" APR_UINT64_T_FMT " cap=(%s) %s %s %s",
+                      ver, cap_log->data,
+                      svn_path_uri_encode(b->repository->fs_path->data,
+                                          scratch_pool),
+                      ra_client_string, client_string));
+
+  warn_baton = apr_pcalloc(scratch_pool, sizeof(*warn_baton));
+  warn_baton->server = b;
+  warn_baton->conn = conn;
+  warn_baton->pool = svn_pool_create(scratch_pool);
+  svn_fs_set_warning_func(b->repository->fs, fs_warning_func, warn_baton);
+
   /* Set up editor shims. */
   {
     svn_delta_shim_callbacks_t *callbacks =
-                                svn_delta_shim_callbacks_default(pool);
+                                svn_delta_shim_callbacks_default(conn_pool);
 
     callbacks->fetch_base_func = fetch_base_func;
     callbacks->fetch_props_func = fetch_props_func;
     callbacks->fetch_kind_func = fetch_kind_func;
-    callbacks->fetch_baton = &b;
+    callbacks->fetch_baton = b;
 
     SVN_ERR(svn_ra_svn__set_shim_callbacks(conn, callbacks));
   }
 
-  return svn_ra_svn__handle_commands2(conn, pool, main_commands, &b, FALSE);
+  *baton = b;
+
+  return SVN_NO_ERROR;
+}
+
+/* Open a svn_repos object in CONNECTION for the same repository and with
+   the same settings as last time.  The repository object remains valid
+   until POOL gets cleaned up at which point the respective pointer in
+   CONNECTION reset.  The repository in CONNECTION must have been opened
+   at some point in the past using construct_server_baton.
+ */
+static svn_error_t *
+reopen_repos(connection_t *connection,
+             apr_pool_t *pool)
+{
+  fs_warning_baton_t *warn_baton = apr_pcalloc(pool, sizeof(*warn_baton));
+  repository_t *repository = connection->baton->repository;
+
+  /* Open the repository and fill in b with the resulting information. */
+  SVN_ERR(svn_repos__repos_pool_get(&repository->repos,
+                                    connection->params->repos_pool,
+                                    repository->repos_root, repository->uuid,
+                                    pool));
+  repository->fs = svn_repos_fs(repository->repos);
+
+  /* Reset the REPOS pointer as soon as the REPOS will be returned to the
+     REPOS_POOL. */
+  apr_pool_cleanup_register(pool, repository, reset_repos,
+                            apr_pool_cleanup_null);
+
+  /* Configure svn_repos object */
+  SVN_ERR(svn_repos_remember_client_capabilities(repository->repos,
+                                                 repository->capabilities));
+  SVN_ERR(svn_repos_hooks_setenv(repository->repos, repository->hooks_env,
+                                 pool));
+  
+  warn_baton->server = connection->baton;
+  warn_baton->conn = connection->conn;
+  warn_baton->pool = svn_pool_create(pool);
+  svn_fs_set_warning_func(connection->baton->repository->fs,
+                          fs_warning_func, &warn_baton);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+serve_interruptable(svn_boolean_t *terminate_p,
+                    connection_t *connection,
+                    svn_boolean_t (* is_busy)(connection_t *),
+                    apr_pool_t *pool)
+{
+  svn_boolean_t terminate = FALSE;
+  const svn_ra_svn_cmd_entry_t *command;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+
+  /* Prepare command parser. */
+  apr_hash_t *cmd_hash = apr_hash_make(pool);
+  for (command = main_commands; command->cmdname; command++)
+    svn_hash_sets(cmd_hash, command->cmdname, command);
+
+  /* Auto-initialize connection & open repository */
+  if (connection->conn)
+    {
+      /* This is not the first call for CONNECTION. */
+      if (connection->baton->repository->repos == NULL)
+        SVN_ERR(reopen_repos(connection, pool));
+    }
+  else
+    {
+      apr_status_t ar;
+
+      /* Enable TCP keep-alives on the socket so we time out when
+       * the connection breaks due to network-layer problems.
+       * If the peer has dropped the connection due to a network partition
+       * or a crash, or if the peer no longer considers the connection
+       * valid because we are behind a NAT and our public IP has changed,
+       * it will respond to the keep-alive probe with a RST instead of an
+       * acknowledgment segment, which will cause svn to abort the session
+       * even while it is currently blocked waiting for data from the peer. */
+      ar = apr_socket_opt_set(connection->usock, APR_SO_KEEPALIVE, 1);
+      if (ar)
+        {
+          /* It's not a fatal error if we cannot enable keep-alives. */
+        }
+
+      /* create the connection, configure ports etc. */
+      connection->conn
+        = svn_ra_svn_create_conn3(connection->usock, NULL, NULL,
+                                  connection->params->compression_level,
+                                  connection->params->zero_copy_limit,
+                                  connection->params->error_check_interval,
+                                  pool);
+
+      /* Construct server baton and open the repository for the first time. */
+      SVN_ERR(construct_server_baton(&connection->baton, connection->conn,
+                                     connection->params, pool));
+    }
+
+  /* Process incoming commands. */
+  while (!terminate)
+    {
+      svn_pool_clear(iterpool);
+      if (is_busy && is_busy(connection))
+        {
+          svn_boolean_t has_command;
+
+          /* If the server is busy, execute just one command and only if
+           * there is one currently waiting in our receive buffers.
+           */
+          SVN_ERR(svn_ra_svn__has_command(&has_command, &terminate,
+                                          connection->conn, iterpool));
+          if (has_command)
+            SVN_ERR(svn_ra_svn__handle_command(&terminate, cmd_hash,
+                                              connection->baton,
+                                              connection->conn,
+                                              FALSE, iterpool));
+
+          break;
+        }
+      else
+        {
+          /* The server is not busy, thus let's serve whichever command
+           * comes in next and whenever it comes in.  This requires the
+           * busy() callback test to return TRUE while there are still some
+           * resources left.
+           */
+          SVN_ERR(svn_ra_svn__handle_command(&terminate, cmd_hash,
+                                             connection->baton,
+                                             connection->conn,
+                                             FALSE, iterpool));
+        }
+    }
+
+  /* error or normal end of session. Close the connection */
+  svn_pool_destroy(iterpool);
+  if (terminate_p)
+    *terminate_p = terminate;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *serve(svn_ra_svn_conn_t *conn,
+                   serve_params_t *params,
+                   apr_pool_t *pool)
+{
+  server_baton_t *baton = NULL;
+
+  SVN_ERR(construct_server_baton(&baton, conn, params, pool));
+  return svn_ra_svn__handle_commands2(conn, pool, main_commands, baton, FALSE);
 }

Modified: subversion/branches/log-addressing/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnserve/server.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnserve/server.h (original)
+++ subversion/branches/log-addressing/subversion/svnserve/server.h Wed Nov 27 08:19:45 2013
@@ -36,8 +36,11 @@ extern "C" {
 #include "svn_repos.h"
 #include "svn_ra_svn.h"
 
+#include "private/svn_atomic.h"
 #include "private/svn_mutex.h"
-
+#include "private/svn_repos_private.h"
+#include "private/svn_subr_private.h"
+  
 enum username_case_type { CASE_FORCE_UPPER, CASE_FORCE_LOWER, CASE_ASIS };
 
 enum authn_type { UNAUTHENTICATED, AUTHENTICATED };
@@ -46,6 +49,7 @@ enum access_type { NO_ACCESS, READ_ACCES
 typedef struct repository_t {
   svn_repos_t *repos;
   const char *repos_name;  /* URI-encoded name of repository (not for authz) */
+  const char *repos_root;  /* Repository root directory */
   svn_fs_t *fs;            /* For convenience; same as svn_repos_fs(repos) */
   const char *base;        /* Base directory for config files */
   svn_config_t *pwdb;      /* Parsed password database */
@@ -53,8 +57,11 @@ typedef struct repository_t {
   const char *authz_repos_name; /* The name of the repository for authz */
   const char *realm;       /* Authentication realm */
   const char *repos_url;   /* URL to base of repository */
+  const char *hooks_env;   /* Path to the hooks environment file or NULL */
+  const char *uuid;        /* Repository ID */
+  apr_array_header_t *capabilities;
+                           /* Client capabilities (SVN_RA_CAPABILITY_*) */
   svn_stringbuf_t *fs_path;/* Decoded base in-repos path (w/ leading slash) */
-  apr_hash_t *fs_config;   /* Additional FS configuration parameters */
   enum username_case_type username_case; /* Case-normalize the username? */
   svn_boolean_t use_sasl;  /* Use Cyrus SASL for authentication;
                               always false if SVN_HAVE_SASL not defined */
@@ -115,17 +122,17 @@ typedef struct serve_params_t {
   /* logging data structure; possibly NULL. */
   struct logger_t *logger;
 
-  /* Username case normalization style. */
-  enum username_case_type username_case;
+  /* all configurations should be opened through this factory */
+  svn_repos__config_pool_t *config_pool;
 
-  /* Enable text delta caching for all FSFS repositories. */
-  svn_boolean_t cache_txdeltas;
+  /* all authz data should be opened through this factory */
+  svn_repos__authz_pool_t *authz_pool;
 
-  /* Enable full-text caching for all FSFS repositories. */
-  svn_boolean_t cache_fulltexts;
+  /* all repositories should be opened through this factory */
+  svn_repos__repos_pool_t *repos_pool;
 
-  /* Enable revprop caching for all FSFS repositories. */
-  svn_boolean_t cache_revprops;
+  /* Username case normalization style. */
+  enum username_case_type username_case;
 
   /* Size of the in-memory cache (used by FSFS only). */
   apr_uint64_t memory_cache_size;
@@ -148,6 +155,42 @@ typedef struct serve_params_t {
   svn_boolean_t vhost;
 } serve_params_t;
 
+/* This structure contains all data that describes a client / server
+   connection.  Their lifetime is separated from the thread-local
+   serving pools. */
+typedef struct connection_t
+{
+  /* socket return by accept() */
+  apr_socket_t *usock;
+
+  /* server-global parameters */
+  serve_params_t *params;
+
+  /* connection-specific objects */
+  server_baton_t *baton;
+
+  /* buffered connection object used by the marshaller */
+  svn_ra_svn_conn_t *conn;
+
+  /* memory pool for objects with connection lifetime */
+  apr_pool_t *pool;
+
+  /* source and ultimate destiny for POOL */
+  svn_root_pools__t *root_pools;
+  
+  /* Number of threads using the pool.
+     The pool passed to apr_thread_create can only be released when both
+
+        A: the call to apr_thread_create has returned to the calling thread
+        B: the new thread has started running and reached apr_thread_start_t
+
+     So we set the atomic counter to 2 then both the calling thread and
+     the new thread decrease it and when it reaches 0 the pool can be
+     released.  */
+  svn_atomic_t ref_count;
+  
+} connection_t;
+
 /* Return a client_info_t structure allocated in POOL and initialize it
  * with data from CONN. */
 client_info_t * get_client_info(svn_ra_svn_conn_t *conn,
@@ -158,6 +201,23 @@ client_info_t * get_client_info(svn_ra_s
 svn_error_t *serve(svn_ra_svn_conn_t *conn, serve_params_t *params,
                    apr_pool_t *pool);
 
+/* Serve the connection CONNECTION for as long as IS_BUSY does not
+   return TRUE.  If IS_BUSY is NULL, serve the connection until it
+   either gets terminated or there is an error.  If TERMINATE_P is
+   not NULL, set *TERMINATE_P to TRUE if the connection got
+   terminated.
+
+   For the first call, CONNECTION->CONN may be NULL in which case we
+   will create an ra_svn connection object.  Subsequent calls will
+   check for an open repository and automatically re-open the repo
+   in pool if necessary.
+ */
+svn_error_t *
+serve_interruptable(svn_boolean_t *terminate_p,
+                    connection_t *connection,
+                    svn_boolean_t (* is_busy)(connection_t *),
+                    apr_pool_t *pool);
+
 /* Initialize the Cyrus SASL library. POOL is used for allocations. */
 svn_error_t *cyrus_init(apr_pool_t *pool);