You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/06 21:13:44 UTC

svn commit: r993127 [4/11] - in /subversion/branches/performance: ./ build/ build/generator/ notes/ notes/tree-conflicts/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org...

Modified: subversion/branches/performance/subversion/libsvn_ra_serf/win32_auth_sspi.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_serf/win32_auth_sspi.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_serf/win32_auth_sspi.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_serf/win32_auth_sspi.c Mon Sep  6 19:13:39 2010
@@ -171,14 +171,18 @@ do_auth(serf_sspi_context_t *sspi_contex
   apr_size_t tmp_len, token_len = 0;
   const char *space;
 
-  space = strchr(auth_attr, ' ');
-  if (space)
+  if (auth_attr != NULL)
     {
-      const char *base64_token = apr_pstrmemdup(pool,
-                                                auth_attr, space - auth_attr);
-      token_len = apr_base64_decode_len(base64_token);
-      token = apr_palloc(pool, token_len);
-      apr_base64_decode(token, base64_token);
+      space = strchr(auth_attr, ' ');
+      if (space)
+        {
+          const char *base64_token = apr_pstrmemdup(pool,
+                                                    auth_attr,
+                                                    space - auth_attr);
+          token_len = apr_base64_decode_len(base64_token);
+          token = apr_palloc(pool, token_len);
+          apr_base64_decode(token, base64_token);
+        }
     }
 
   /* We can get a whole batch of 401 responses from the server, but we should

Modified: subversion/branches/performance/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_svn/client.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_svn/client.c Mon Sep  6 19:13:39 2010
@@ -885,8 +885,10 @@ static svn_error_t *ra_svn_end_commit(vo
                                  &(commit_info->author),
                                  &(commit_info->post_commit_err)));
 
-  return ccb->callback(commit_info, ccb->callback_baton, ccb->pool);
+  if (ccb->callback)
+    SVN_ERR(ccb->callback(commit_info, ccb->callback_baton, ccb->pool));
 
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *ra_svn_commit(svn_ra_session_t *session,

Modified: subversion/branches/performance/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/dump.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/dump.c Mon Sep  6 19:13:39 2010
@@ -25,6 +25,7 @@
 #include "svn_pools.h"
 #include "svn_error.h"
 #include "svn_fs.h"
+#include "svn_hash.h"
 #include "svn_iter.h"
 #include "svn_repos.h"
 #include "svn_string.h"
@@ -40,12 +41,6 @@
 
 /*----------------------------------------------------------------------*/
 
-/** A variant of our hash-writing routine in libsvn_subr;  this one
-    writes to a stringbuf instead of a file, and outputs PROPS-END
-    instead of END.  If OLDHASH is not NULL, then only properties
-    which vary from OLDHASH will be written, and properties which
-    exist only in OLDHASH will be written out with "D" entries
-    (like "K" entries but with no corresponding value). **/
 
 static void
 write_hash_to_stringbuf(apr_hash_t *hash,
@@ -295,6 +290,53 @@ make_dir_baton(const char *path,
 }
 
 
+/* For each property in PROPHASH, write headers containing MD5 and SHA1
+ * checksums of property content to STREAM.
+ * Do temporary allocations in SCRATCH_POOL. */
+static svn_error_t *
+write_prop_content_checksums(svn_stream_t *stream,
+                             apr_hash_t *prophash,
+                             apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+  apr_pool_t *iterpool;
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (hi = apr_hash_first(scratch_pool, prophash);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      svn_checksum_t *checksum;
+      const char *hex_digest;
+      const char *propname;
+      svn_string_t *propval;
+
+      svn_pool_clear(iterpool);
+
+      propname = svn__apr_hash_index_key(hi);
+      propval = svn__apr_hash_index_val(hi);
+
+      SVN_ERR(svn_checksum(&checksum, svn_checksum_md5,
+                           propval->data, propval->len, iterpool));
+      hex_digest = svn_checksum_to_cstring(checksum, iterpool);
+      if (hex_digest)
+        SVN_ERR(svn_stream_printf(stream, iterpool,
+                                  SVN_REPOS_DUMPFILE_PROP_CONTENT_MD5
+                                  ": (%s) %s\n", propname, hex_digest));
+      SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1,
+                           propval->data, propval->len, iterpool));
+      hex_digest = svn_checksum_to_cstring(checksum, iterpool);
+      if (hex_digest)
+        SVN_ERR(svn_stream_printf(stream, iterpool,
+                                  SVN_REPOS_DUMPFILE_PROP_CONTENT_SHA1
+                                  ": (%s) %s\n", propname, hex_digest));
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+
 /* This helper is the main "meat" of the editor -- it does all the
    work of writing a node record.
 
@@ -509,6 +551,7 @@ dump_node(struct edit_baton *eb,
     {
       apr_hash_t *prophash, *oldhash = NULL;
       apr_size_t proplen;
+      svn_stream_t *propstream;
 
       SVN_ERR(svn_fs_node_proplist(&prophash, eb->fs_root, path, pool));
 
@@ -559,12 +602,19 @@ dump_node(struct edit_baton *eb,
                                     SVN_REPOS_DUMPFILE_PROP_DELTA
                                     ": true\n"));
         }
-      write_hash_to_stringbuf(prophash, oldhash, &propstring, pool);
+      else
+        oldhash = apr_hash_make(pool);
+      propstring = svn_stringbuf_create_ensure(0, pool);
+      propstream = svn_stream_from_stringbuf(propstring, pool);
+      svn_hash_write_incremental(prophash, oldhash, propstream, "PROPS-END",
+                                 pool);
+      SVN_ERR(svn_stream_close(propstream));
       proplen = propstring->len;
       content_length += proplen;
       SVN_ERR(svn_stream_printf(eb->stream, pool,
                                 SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
                                 ": %" APR_SIZE_T_FMT "\n", proplen));
+      SVN_ERR(write_prop_content_checksums(eb->stream, prophash, pool));
     }
 
   /* If we are supposed to dump text, write out a text length header
@@ -962,6 +1012,7 @@ write_revision_record(svn_stream_t *stre
   svn_stringbuf_t *encoded_prophash;
   apr_time_t timetemp;
   svn_string_t *datevalue;
+  svn_stream_t *propstream;
 
   /* Read the revision props even if we're aren't going to dump
      them for verification purposes */
@@ -981,7 +1032,10 @@ write_revision_record(svn_stream_t *stre
                    datevalue);
     }
 
-  write_hash_to_stringbuf(props, NULL, &encoded_prophash, pool);
+  encoded_prophash = svn_stringbuf_create_ensure(0, pool);
+  propstream = svn_stream_from_stringbuf(encoded_prophash, pool);
+  svn_hash_write2(props, propstream, "PROPS-END", pool);
+  SVN_ERR(svn_stream_close(propstream));
 
   /* ### someday write a revision-content-checksum */
 
@@ -992,6 +1046,7 @@ write_revision_record(svn_stream_t *stre
                             SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
                             ": %" APR_SIZE_T_FMT "\n",
                             encoded_prophash->len));
+  SVN_ERR(write_prop_content_checksums(stream, props, pool));
 
   /* Write out a regular Content-length header for the benefit of
      non-Subversion RFC-822 parsers. */

Modified: subversion/branches/performance/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/repos.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/repos.c Mon Sep  6 19:13:39 2010
@@ -1806,14 +1806,14 @@ struct hotcopy_ctx_t {
   size_t src_len; /* len of the source path*/
 };
 
-/** Called by (svn_io_dir_walk).
+/** Called by (svn_io_dir_walk2).
  * Copies the repository structure with exception of @c SVN_REPOS__DB_DIR,
  * @c SVN_REPOS__LOCK_DIR and @c SVN_REPOS__FORMAT.
  * Those directories and files are handled separetly.
  * @a baton is a pointer to (struct hotcopy_ctx_t) specifying
  * destination path to copy to and the length of the source path.
  *
- * @copydoc svn_io_dir_walk()
+ * @copydoc svn_io_dir_walk2()
  */
 static svn_error_t *hotcopy_structure(void *baton,
                                       const char *path,
@@ -1910,11 +1910,11 @@ svn_repos_hotcopy(const char *src_path,
 
   hotcopy_context.dest = dst_path;
   hotcopy_context.src_len = strlen(src_path);
-  SVN_ERR(svn_io_dir_walk(src_path,
-                          0,
-                          hotcopy_structure,
-                          &hotcopy_context,
-                          pool));
+  SVN_ERR(svn_io_dir_walk2(src_path,
+                           0,
+                           hotcopy_structure,
+                           &hotcopy_context,
+                           pool));
 
   /* Prepare dst_repos object so that we may create locks,
      so that we may open repository */

Modified: subversion/branches/performance/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/config_win.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/config_win.c Mon Sep  6 19:13:39 2010
@@ -177,7 +177,7 @@ svn_config__parse_registry(svn_config_t 
     {
       return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
                                "Unrecognised registry path '%s'",
-                               svn_path_local_style(file, pool));
+                               svn_dirent_local_style(file, pool));
     }
 
   err = RegOpenKeyEx(base_hkey, file, 0,
@@ -189,11 +189,11 @@ svn_config__parse_registry(svn_config_t 
       if (!is_enoent)
         return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
                                  "Can't open registry key '%s'",
-                                 svn_path_local_style(file, pool));
+                                 svn_dirent_local_style(file, pool));
       else if (must_exist && is_enoent)
         return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
                                  "Can't find registry key '%s'",
-                                 svn_path_local_style(file, pool));
+                                 svn_dirent_local_style(file, pool));
       else
         return SVN_NO_ERROR;
     }

Modified: subversion/branches/performance/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/deprecated.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/deprecated.c Mon Sep  6 19:13:39 2010
@@ -751,6 +751,43 @@ svn_io_get_dirents(apr_hash_t **dirents,
   return svn_io_get_dirents2(dirents, path, pool);
 }
 
+struct walk_func_filter_baton_t
+{
+  svn_io_walk_func_t walk_func;
+  void *walk_baton;
+};
+
+/* Implements svn_io_walk_func_t, but only allows APR_DIR and APR_REG
+   finfo types through to the wrapped function/baton.  */
+static svn_error_t *
+walk_func_filter_func(void *baton,
+                      const char *path,
+                      const apr_finfo_t *finfo,
+                      apr_pool_t *pool)
+{
+  struct walk_func_filter_baton_t *b = baton;
+
+  if (finfo->filetype == APR_DIR || finfo->filetype == APR_REG)
+    SVN_ERR(b->walk_func(b->walk_baton, path, finfo, pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_io_dir_walk(const char *dirname,
+                apr_int32_t wanted,
+                svn_io_walk_func_t walk_func,
+                void *walk_baton,
+                apr_pool_t *pool)
+{
+  struct walk_func_filter_baton_t baton;
+  baton.walk_func = walk_func;
+  baton.walk_baton = walk_baton;
+  return svn_error_return(svn_io_dir_walk2(dirname, wanted,
+                                           walk_func_filter_func,
+                                           &baton, pool));
+}
+
 svn_error_t *
 svn_io_file_read_full(apr_file_t *file, void *buf,
                       apr_size_t nbytes, apr_size_t *bytes_read,
@@ -759,7 +796,6 @@ svn_io_file_read_full(apr_file_t *file, 
   return svn_io_file_read_full2(file, buf, nbytes, bytes_read, FALSE, pool);
 }
 
-
 /*** From constructors.c ***/
 svn_log_changed_path_t *
 svn_log_changed_path_dup(const svn_log_changed_path_t *changed_path,

Modified: subversion/branches/performance/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/io.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/io.c Mon Sep  6 19:13:39 2010
@@ -2044,44 +2044,8 @@ svn_io_get_dir_filenames(apr_hash_t **di
                          const char *path,
                          apr_pool_t *pool)
 {
-  apr_status_t status;
-  apr_dir_t *this_dir;
-  apr_finfo_t this_entry;
-  apr_int32_t flags = APR_FINFO_NAME;
-
-  *dirents = apr_hash_make(pool);
-
-  SVN_ERR(svn_io_dir_open(&this_dir, path, pool));
-
-  for (status = apr_dir_read(&this_entry, flags, this_dir);
-       status == APR_SUCCESS;
-       status = apr_dir_read(&this_entry, flags, this_dir))
-    {
-      if ((this_entry.name[0] == '.')
-          && ((this_entry.name[1] == '\0')
-              || ((this_entry.name[1] == '.')
-                  && (this_entry.name[2] == '\0'))))
-        {
-          continue;
-        }
-      else
-        {
-          const char *name;
-          SVN_ERR(entry_name_to_utf8(&name, this_entry.name, path, pool));
-          apr_hash_set(*dirents, name, APR_HASH_KEY_STRING, name);
-        }
-    }
-
-  if (! (APR_STATUS_IS_ENOENT(status)))
-    return svn_error_wrap_apr(status, _("Can't read directory '%s'"),
-                              svn_dirent_local_style(path, pool));
-
-  status = apr_dir_close(this_dir);
-  if (status)
-    return svn_error_wrap_apr(status, _("Error closing directory '%s'"),
-                              svn_dirent_local_style(path, pool));
-
-  return SVN_NO_ERROR;
+  return svn_error_return(svn_io_get_dirents3(dirents, path, TRUE,
+                                              pool, pool));
 }
 
 svn_io_dirent2_t *
@@ -2764,11 +2728,15 @@ svn_io_detect_mimetype2(const char **mim
 
 
   /* Right now, this function is going to be really stupid.  It's
-     going to examine the first block of data, and make sure that 85%
+     going to examine the first block of data, and make sure that 15%
      of the bytes are such that their value is in the ranges 0x07-0x0D
-     or 0x20-0x7F, and that 100% of those bytes is not 0x00.
+     or 0x20-0x7F, and that none of those bytes is 0x00.  If those
+     criteria are not met, we're calling it binary.
 
-     If those criteria are not met, we're calling it binary. */
+     NOTE:  Originally, I intended to target 85% of the bytes being in
+     the specified ranges, but I flubbed the condition.  At any rate,
+     folks aren't complaining, so I'm not sure that it's worth
+     adjusting this retroactively now.  --cmpilato  */
   if (amt_read > 0)
     {
       apr_size_t i;
@@ -3338,11 +3306,11 @@ svn_io_dir_read(apr_finfo_t *finfo,
 
 
 svn_error_t *
-svn_io_dir_walk(const char *dirname,
-                apr_int32_t wanted,
-                svn_io_walk_func_t walk_func,
-                void *walk_baton,
-                apr_pool_t *pool)
+svn_io_dir_walk2(const char *dirname,
+                 apr_int32_t wanted,
+                 svn_io_walk_func_t walk_func,
+                 void *walk_baton,
+                 apr_pool_t *pool)
 {
   apr_status_t apr_err;
   apr_dir_t *handle;
@@ -3411,11 +3379,11 @@ svn_io_dir_walk(const char *dirname,
           SVN_ERR(entry_name_to_utf8(&name_utf8, finfo.name, dirname,
                                      subpool));
           full_path = svn_dirent_join(dirname, name_utf8, subpool);
-          SVN_ERR(svn_io_dir_walk(full_path,
-                                  wanted,
-                                  walk_func,
-                                  walk_baton,
-                                  subpool));
+          SVN_ERR(svn_io_dir_walk2(full_path,
+                                   wanted,
+                                   walk_func,
+                                   walk_baton,
+                                   subpool));
         }
       else if (finfo.filetype == APR_REG || finfo.filetype == APR_LNK)
         {
@@ -3429,9 +3397,10 @@ svn_io_dir_walk(const char *dirname,
                                subpool));
         }
       /* else:
-         some other type of file; skip it.
+         Some other type of file; skip it for now.  We've reserved the
+         right to expand our coverage here in the future, though,
+         without revving this API.
       */
-
     }
 
   svn_pool_destroy(subpool);

Modified: subversion/branches/performance/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/opt.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/opt.c Mon Sep  6 19:13:39 2010
@@ -942,12 +942,6 @@ svn_opt__arg_canonicalize_url(const char
   /* Auto-escape some ASCII characters. */
   target = svn_path_uri_autoescape(target, pool);
 
-  /* The above doesn't guarantee a valid URI. */
-  if (! svn_path_is_uri_safe(target))
-    return svn_error_createf(SVN_ERR_BAD_URL, 0,
-                             _("URL '%s' is not properly URI-encoded"),
-                             target);
-
   /* Verify that no backpaths are present in the URL. */
   if (svn_path_is_backpath_present(target))
     return svn_error_createf(SVN_ERR_BAD_URL, 0,

Modified: subversion/branches/performance/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/sqlite.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/sqlite.c Mon Sep  6 19:13:39 2010
@@ -81,10 +81,12 @@ struct svn_sqlite__stmt_t
 };
 
 
-/* Convert SQLite error codes to SVN */
-#define SQLITE_ERROR_CODE(x) ((x) == SQLITE_READONLY    \
-                              ? SVN_ERR_SQLITE_READONLY \
-                              : SVN_ERR_SQLITE_ERROR )
+/* Convert SQLite error codes to SVN. Evaluates X multiple times */
+#define SQLITE_ERROR_CODE(x) ((x) == SQLITE_READONLY       \
+                              ? SVN_ERR_SQLITE_READONLY    \
+                              : ((x) == SQLITE_BUSY        \
+                                 ? SVN_ERR_SQLITE_BUSY     \
+                                 : SVN_ERR_SQLITE_ERROR) )
 
 
 /* SQLITE->SVN quick error wrap, much like SVN_ERR. */
@@ -174,10 +176,11 @@ step_with_expectation(svn_sqlite__stmt_t
   if ((got_row && !expecting_row)
       ||
       (!got_row && expecting_row))
-    return svn_error_create(SVN_ERR_SQLITE_ERROR, NULL,
+    return svn_error_create(SVN_ERR_SQLITE_ERROR,
+                            svn_sqlite__reset(stmt),
                             expecting_row
-                            ? _("Expected database row missing")
-                            : _("Extra database row found"));
+                              ? _("Expected database row missing")
+                              : _("Extra database row found"));
 
   return SVN_NO_ERROR;
 }
@@ -965,8 +968,50 @@ svn_sqlite__with_transaction(svn_sqlite_
   /* Commit or rollback the sqlite transaction. */
   if (err)
     {
-      svn_error_clear(exec_sql(db, "ROLLBACK TRANSACTION;"));
-      return svn_error_return(err);
+      svn_error_t *err2 = exec_sql(db, "ROLLBACK TRANSACTION;");
+
+      if (err2 && err2->apr_err == SVN_ERR_SQLITE_BUSY)
+        {
+          int i;
+          /* ### Houston, we have a problem!
+
+             We are trying to rollback but we can't because some
+             statements are still busy. This leaves the database
+             unusable for future transactions as the current transaction
+             is still open.
+
+             As we are returning the actual error as the most relevant
+             error in the chain, our caller might assume that it can
+             retry/compensate on this error (e.g. SVN_WC_LOCKED), while
+             in fact the SQLite database is unusable until the statements
+             started within this transaction are reset and the transaction
+             aborted.
+
+             We try to compensate by resetting al prepared but unreset
+             statements; but we leave the busy error in the chain anyway to
+             help diagnosing the original error and help in finding where
+             a reset statement is missing. */
+
+          /* ### Should we reorder the errors in this specific case
+             ### to avoid returning the normal error as top level error? */
+
+          err2 = svn_error_compose_create(err2,
+                   svn_error_create(SVN_ERR_SQLITE_RESETTING_FOR_ROLLBACK,
+                                    NULL, NULL));
+
+          for (i = 0; i < db->nbr_statements; i++)
+            if (db->prepared_stmts[i] && db->prepared_stmts[i]->needs_reset)
+              err2 = svn_error_compose_create(
+                         err2,
+                         svn_sqlite__reset(db->prepared_stmts[i]));
+
+          err2 = svn_error_compose_create(
+                      exec_sql(db, "ROLLBACK TRANSACTION;"),
+                      err2);
+        }
+
+      return svn_error_compose_create(err,
+                                      err2);
     }
 
   return svn_error_return(exec_sql(db, "COMMIT TRANSACTION;"));

Modified: subversion/branches/performance/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/stream.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/stream.c Mon Sep  6 19:13:39 2010
@@ -51,7 +51,6 @@ struct svn_stream_t {
   svn_write_fn_t write_fn;
   svn_skip_fn_t skip_fn;
   svn_close_fn_t close_fn;
-  svn_io_reset_fn_t reset_fn;
   svn_io_mark_fn_t mark_fn;
   svn_io_seek_fn_t seek_fn;
   svn_io_buffered_fn_t buffered_fn;
@@ -71,7 +70,6 @@ svn_stream_create(void *baton, apr_pool_
   stream->skip_fn = NULL;
   stream->write_fn = NULL;
   stream->close_fn = NULL;
-  stream->reset_fn = NULL;
   stream->mark_fn = NULL;
   stream->seek_fn = NULL;
   stream->buffered_fn = NULL;
@@ -111,12 +109,6 @@ svn_stream_set_close(svn_stream_t *strea
 }
 
 void
-svn_stream_set_reset(svn_stream_t *stream, svn_io_reset_fn_t reset_fn)
-{
-  stream->reset_fn = reset_fn;
-}
-
-void
 svn_stream_set_mark(svn_stream_t *stream, svn_io_mark_fn_t mark_fn)
 {
   stream->mark_fn = mark_fn;
@@ -162,10 +154,8 @@ svn_stream_write(svn_stream_t *stream, c
 svn_error_t *
 svn_stream_reset(svn_stream_t *stream)
 {
-  if (stream->reset_fn == NULL)
-    return svn_error_create(SVN_ERR_STREAM_RESET_NOT_SUPPORTED, NULL, NULL);
-
-  return stream->reset_fn(stream->baton);
+  return svn_error_return(
+            svn_stream_seek(stream, NULL));
 }
 
 svn_boolean_t
@@ -669,14 +659,9 @@ write_handler_empty(void *baton, const c
 }
 
 static svn_error_t *
-reset_handler_empty(void *baton)
-{
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
 mark_handler_empty(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
+  *mark = NULL; /* Seek to start of stream marker */
   return SVN_NO_ERROR;
 }
 
@@ -702,7 +687,6 @@ svn_stream_empty(apr_pool_t *pool)
   svn_stream_set_read(stream, read_handler_empty);
   svn_stream_set_skip(stream, skip_handler_empty);
   svn_stream_set_write(stream, write_handler_empty);
-  svn_stream_set_reset(stream, reset_handler_empty);
   svn_stream_set_mark(stream, mark_handler_empty);
   svn_stream_set_seek(stream, seek_handler_empty);
   svn_stream_set_buffered(stream, buffered_handler_empty);
@@ -789,12 +773,6 @@ write_handler_disown(void *baton, const 
 }
 
 static svn_error_t *
-reset_handler_disown(void *baton)
-{
-  return svn_stream_reset(baton);
-}
-
-static svn_error_t *
 mark_handler_disown(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
   return svn_stream_mark(baton, mark, pool);
@@ -820,7 +798,6 @@ svn_stream_disown(svn_stream_t *stream, 
   svn_stream_set_read(s, read_handler_disown);
   svn_stream_set_skip(s, skip_handler_disown);
   svn_stream_set_write(s, write_handler_disown);
-  svn_stream_set_reset(s, reset_handler_disown);
   svn_stream_set_mark(s, mark_handler_disown);
   svn_stream_set_seek(s, seek_handler_disown);
   svn_stream_set_buffered(s, buffered_handler_disown);
@@ -926,19 +903,6 @@ close_handler_cached_handle(void *baton)
 }
 
 static svn_error_t *
-reset_handler_apr(void *baton)
-{
-  apr_off_t offset;
-  struct baton_apr *btn = baton;
-
-  /* If we're reading from a range, reset to the start of the range.
-   * Otherwise, reset to the start of the file. */
-  offset = btn->start >= 0 ? btn->start : 0;
-
-  return svn_io_file_seek(btn->file, APR_SET, &offset, btn->pool);
-}
-
-static svn_error_t *
 mark_handler_apr(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
   struct baton_apr *btn = baton;
@@ -955,10 +919,25 @@ static svn_error_t *
 seek_handler_apr(void *baton, svn_stream_mark_t *mark)
 {
   struct baton_apr *btn = baton;
-  struct mark_apr *mark_apr;
 
-  mark_apr = (struct mark_apr *)mark;
-  SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &mark_apr->off, btn->pool));
+  if (mark != NULL)
+    {
+      struct mark_apr *mark_apr;
+
+      mark_apr = (struct mark_apr *)mark;
+      SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &mark_apr->off, btn->pool));
+    }
+  else
+    {
+      apr_off_t offset;
+
+      /* If we're reading from a range, reset to the start of the range.
+       * Otherwise, reset to the start of the file. */
+      offset = btn->start >= 0 ? btn->start : 0;
+
+      SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &offset, btn->pool));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1047,7 +1026,6 @@ stream_from_aprfile(struct baton_apr **b
   svn_stream_set_read(stream, read_handler_apr);
   svn_stream_set_skip(stream, skip_handler_apr);
   svn_stream_set_write(stream, write_handler_apr);
-  svn_stream_set_reset(stream, reset_handler_apr);
   svn_stream_set_mark(stream, mark_handler_apr);
   svn_stream_set_seek(stream, seek_handler_apr);
   svn_stream_set_buffered(stream, buffered_handler_apr);
@@ -1072,6 +1050,16 @@ svn_stream_from_aprfile2(apr_file_t *fil
 
   /* construct and init the default stream structures */
   stream = stream_from_aprfile(&baton, file, pool);
+  baton = apr_palloc(pool, sizeof(*baton));
+  baton->file = file;
+  baton->pool = pool;
+  baton->start = -1;
+  baton->end = -1;
+  stream = svn_stream_create(baton, pool);
+  svn_stream_set_read(stream, read_handler_apr);
+  svn_stream_set_write(stream, write_handler_apr);
+  svn_stream_set_mark(stream, mark_handler_apr);
+  svn_stream_set_seek(stream, seek_handler_apr);
 
   /* make sure to close the file handle after use if we own it */
   if (! disown)
@@ -1215,7 +1203,6 @@ svn_stream_from_aprfile_range_readonly(a
   stream = svn_stream_create(baton, pool);
   svn_stream_set_read(stream, read_range_handler_apr);
   svn_stream_set_skip(stream, skip_range_handler_apr);
-  svn_stream_set_reset(stream, reset_handler_apr);
   svn_stream_set_mark(stream, mark_handler_apr);
   svn_stream_set_seek(stream, seek_handler_apr);
   svn_stream_set_buffered(stream, buffered_handler_apr);
@@ -1780,20 +1767,13 @@ write_handler_stringbuf(void *baton, con
 }
 
 static svn_error_t *
-reset_handler_stringbuf(void *baton)
-{
-  struct stringbuf_stream_baton *btn = baton;
-  btn->amt_read = 0;
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
 mark_handler_stringbuf(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
   struct stringbuf_stream_baton *btn;
   struct stringbuf_stream_mark *stringbuf_stream_mark;
 
   btn = baton;
+
   stringbuf_stream_mark = apr_palloc(pool, sizeof(*stringbuf_stream_mark));
   stringbuf_stream_mark->pos = btn->amt_read;
   *mark = (svn_stream_mark_t *)stringbuf_stream_mark;
@@ -1803,12 +1783,18 @@ mark_handler_stringbuf(void *baton, svn_
 static svn_error_t *
 seek_handler_stringbuf(void *baton, svn_stream_mark_t *mark)
 {
-  struct stringbuf_stream_baton *btn;
-  struct stringbuf_stream_mark *stringbuf_stream_mark;
+  struct stringbuf_stream_baton *btn = baton;
+
+  if (mark != NULL)
+    {
+      struct stringbuf_stream_mark *stringbuf_stream_mark;
+
+      stringbuf_stream_mark = (struct stringbuf_stream_mark *)mark;
+      btn->amt_read = stringbuf_stream_mark->pos;
+    }
+  else
+    btn->amt_read = 0;
 
-  btn = baton;
-  stringbuf_stream_mark = (struct stringbuf_stream_mark *)mark;
-  btn->amt_read = stringbuf_stream_mark->pos;
   return SVN_NO_ERROR;
 }
 
@@ -1835,7 +1821,6 @@ svn_stream_from_stringbuf(svn_stringbuf_
   svn_stream_set_read(stream, read_handler_stringbuf);
   svn_stream_set_skip(stream, skip_handler_stringbuf);
   svn_stream_set_write(stream, write_handler_stringbuf);
-  svn_stream_set_reset(stream, reset_handler_stringbuf);
   svn_stream_set_mark(stream, mark_handler_stringbuf);
   svn_stream_set_seek(stream, seek_handler_stringbuf);
   svn_stream_set_buffered(stream, buffered_handler_stringbuf);
@@ -1848,6 +1833,11 @@ struct string_stream_baton
   apr_size_t amt_read;
 };
 
+/* svn_stream_mark_t for streams backed by stringbufs. */
+struct string_stream_mark {
+    apr_size_t pos; 
+};
+
 static svn_error_t *
 read_handler_string(void *baton, char *buffer, apr_size_t *len)
 {
@@ -1871,6 +1861,38 @@ skip_handler_string(void *baton, apr_siz
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+mark_handler_string(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
+{
+  struct string_stream_baton *btn;
+  struct string_stream_mark *marker;
+
+  btn = baton;
+
+  marker = apr_palloc(pool, sizeof(*marker));
+  marker->pos = btn->amt_read;
+  *mark = (svn_stream_mark_t *)marker;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+seek_handler_string(void *baton, svn_stream_mark_t *mark)
+{
+  struct string_stream_baton *btn = baton;
+
+  if (mark != NULL)
+    {
+      struct string_stream_mark *marker;
+
+      marker = (struct string_stream_mark *)mark;
+      btn->amt_read = marker->pos;
+    }
+  else
+    btn->amt_read = 0;
+
+  return SVN_NO_ERROR;
+}
+
 svn_stream_t *
 svn_stream_from_string(const svn_string_t *str,
                        apr_pool_t *pool)
@@ -1887,6 +1909,8 @@ svn_stream_from_string(const svn_string_
   stream = svn_stream_create(baton, pool);
   svn_stream_set_read(stream, read_handler_string);
   svn_stream_set_skip(stream, skip_handler_string);
+  svn_stream_set_mark(stream, mark_handler_string);
+  svn_stream_set_seek(stream, seek_handler_string);
   return stream;
 }
 

Modified: subversion/branches/performance/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/subst.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/subst.c Mon Sep  6 19:13:39 2010
@@ -1241,30 +1241,6 @@ translated_stream_close(void *baton)
   return SVN_NO_ERROR;
 }
 
-/* Implements svn_io_reset_fn_t. */
-static svn_error_t *
-translated_stream_reset(void *baton)
-{
-  struct translated_stream_baton *b = baton;
-  svn_error_t *err;
-
-  err = svn_stream_reset(b->stream);
-  if (err == NULL)
-    {
-      b->in_baton->newline_off = 0;
-      b->in_baton->keyword_off = 0;
-      b->in_baton->src_format_len = 0;
-      b->out_baton->newline_off = 0;
-      b->out_baton->keyword_off = 0;
-      b->out_baton->src_format_len = 0;
-
-      b->written = FALSE;
-      svn_stringbuf_setempty(b->readbuf);
-      b->readbuf_off = 0;
-    }
-
-  return svn_error_return(err);
-}
 
 /* svn_stream_mark_t for translation streams. */
 typedef struct
@@ -1306,23 +1282,43 @@ static svn_error_t *
 translated_stream_seek(void *baton, svn_stream_mark_t *mark)
 {
   struct translated_stream_baton *b = baton;
-  mark_translated_t *mt = (mark_translated_t *)mark;
 
-  /* Flush output buffer if necessary. */
-  if (b->written)
-    SVN_ERR(translate_chunk(b->stream, b->out_baton, NULL, 0, b->iterpool));
-
-  SVN_ERR(svn_stream_seek(b->stream, mt->mark));
-
-  /* Restore translation state, avoiding new allocations. */
-  *b->in_baton = *mt->saved_baton.in_baton;
-  *b->out_baton = *mt->saved_baton.out_baton;
-  b->written = mt->saved_baton.written;
-  svn_stringbuf_setempty(b->readbuf);
-  svn_stringbuf_appendbytes(b->readbuf, mt->saved_baton.readbuf->data, 
-                            mt->saved_baton.readbuf->len);
-  b->readbuf_off = mt->saved_baton.readbuf_off;
-  memcpy(b->buf, mt->saved_baton.buf, SVN__TRANSLATION_BUF_SIZE);
+  if (mark != NULL)
+    {
+      mark_translated_t *mt = (mark_translated_t *)mark;
+
+      /* Flush output buffer if necessary. */
+      if (b->written)
+        SVN_ERR(translate_chunk(b->stream, b->out_baton, NULL, 0,
+                                b->iterpool));
+
+      SVN_ERR(svn_stream_seek(b->stream, mt->mark));
+    
+      /* Restore translation state, avoiding new allocations. */
+      *b->in_baton = *mt->saved_baton.in_baton;
+      *b->out_baton = *mt->saved_baton.out_baton;
+      b->written = mt->saved_baton.written;
+      svn_stringbuf_setempty(b->readbuf);
+      svn_stringbuf_appendbytes(b->readbuf, mt->saved_baton.readbuf->data, 
+                                mt->saved_baton.readbuf->len);
+      b->readbuf_off = mt->saved_baton.readbuf_off;
+      memcpy(b->buf, mt->saved_baton.buf, SVN__TRANSLATION_BUF_SIZE);
+    }
+  else
+    {
+      SVN_ERR(svn_stream_reset(b->stream));
+
+      b->in_baton->newline_off = 0;
+      b->in_baton->keyword_off = 0;
+      b->in_baton->src_format_len = 0;
+      b->out_baton->newline_off = 0;
+      b->out_baton->keyword_off = 0;
+      b->out_baton->src_format_len = 0;
+
+      b->written = FALSE;
+      svn_stringbuf_setempty(b->readbuf);
+      b->readbuf_off = 0;
+    }
 
   return SVN_NO_ERROR;
 }
@@ -1435,7 +1431,6 @@ svn_subst_stream_translated(svn_stream_t
   svn_stream_set_skip(s, translated_stream_skip);
   svn_stream_set_write(s, translated_stream_write);
   svn_stream_set_close(s, translated_stream_close);
-  svn_stream_set_reset(s, translated_stream_reset);
   svn_stream_set_mark(s, translated_stream_mark);
   svn_stream_set_seek(s, translated_stream_seek);
   svn_stream_set_buffered(s, translated_stream_buffered);

Propchange: subversion/branches/performance/subversion/libsvn_subr/svn_file_handle_cache.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Sep  6 19:13:39 2010
@@ -0,0 +1 @@
+/subversion/trunk/subversion/libsvn_subr/svn_file_handle_cache.c:962911-970000

Propchange: subversion/branches/performance/subversion/libsvn_subr/svn_temp_serializer.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Sep  6 19:13:39 2010
@@ -0,0 +1 @@
+/subversion/trunk/subversion/libsvn_subr/svn_temp_serializer.c:962911-970000

Modified: subversion/branches/performance/subversion/libsvn_wc/adm_crawler.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/adm_crawler.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/adm_crawler.c Mon Sep  6 19:13:39 2010
@@ -241,7 +241,8 @@ report_revisions_and_depths(svn_wc__db_t
   dir_abspath = svn_dirent_join(anchor_abspath, dir_path, scratch_pool);
   SVN_ERR(svn_wc__db_base_get_children(&base_children, db, dir_abspath,
                                        scratch_pool, iterpool));
-  SVN_ERR(svn_io_get_dir_filenames(&dirents, dir_abspath, scratch_pool));
+  SVN_ERR(svn_io_get_dirents3(&dirents, dir_abspath, TRUE,
+                              scratch_pool, scratch_pool));
 
   /*** Do the real reporting and recursing. ***/
 
@@ -1100,21 +1101,20 @@ svn_wc__internal_transmit_text_deltas(co
 
   /* If the caller wants a copy of the working file translated to
    * repository-normal form, make the copy by tee-ing the stream and set
-   * *TEMPFILE to the path to it. */
+   * *TEMPFILE to the path to it.  This is only needed for the 1.6 API,
+   * 1.7 doesn't set TEMPFILE.  Even when using the 1.6 API this file
+   * is not used by the functions that would have used it when using
+   * the 1.6 code.  It's possible that 3rd party users (if there are any)
+   * might expect this file to be a text-base. */
   if (tempfile)
     {
       svn_stream_t *tempstream;
 
-      SVN_ERR(svn_wc__text_base_deterministic_tmp_path(tempfile,
-                                                       db, local_abspath,
-                                                       result_pool));
-
-      /* Make an untranslated copy of the working file in the
-         administrative tmp area because a) we need to detranslate eol
-         and keywords anyway, and b) after the commit, we're going to
-         copy the tmp file to become the new text base anyway. */
-      SVN_ERR(svn_stream_open_writable(&tempstream, *tempfile,
-                                       scratch_pool, scratch_pool));
+      /* It can't be the same location as in 1.6 because the admin directory
+         no longer exists. */
+      SVN_ERR(svn_stream_open_unique(&tempstream, tempfile,
+                                     NULL, svn_io_file_del_none,
+                                     result_pool, scratch_pool));
 
       /* Wrap the translated stream with a new stream that writes the
          translated contents into the new text base file as we read from it.
@@ -1316,8 +1316,7 @@ svn_wc__internal_transmit_text_deltas(co
 }
 
 svn_error_t *
-svn_wc_transmit_text_deltas3(const char **tempfile,
-                             const svn_checksum_t **new_text_base_md5_checksum,
+svn_wc_transmit_text_deltas3(const svn_checksum_t **new_text_base_md5_checksum,
                              const svn_checksum_t **new_text_base_sha1_checksum,
                              svn_wc_context_t *wc_ctx,
                              const char *local_abspath,
@@ -1327,7 +1326,7 @@ svn_wc_transmit_text_deltas3(const char 
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
 {
-  return svn_wc__internal_transmit_text_deltas(tempfile,
+  return svn_wc__internal_transmit_text_deltas(NULL,
                                                new_text_base_md5_checksum,
                                                new_text_base_sha1_checksum,
                                                wc_ctx->db, local_abspath,

Modified: subversion/branches/performance/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/adm_files.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/adm_files.c Mon Sep  6 19:13:39 2010
@@ -189,24 +189,6 @@ make_adm_subdir(const char *path,
 
 
 svn_error_t *
-svn_wc__text_base_deterministic_tmp_path(const char **result_abspath,
-                                         svn_wc__db_t *db,
-                                         const char *local_abspath,
-                                         apr_pool_t *pool)
-{
-  const char *newpath, *base_name;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  svn_dirent_split(&newpath, &base_name, local_abspath, pool);
-  *result_abspath = simple_extend(newpath, TRUE, SVN_WC__ADM_TEXT_BASE,
-                                  base_name, SVN_WC__BASE_EXT, pool);
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
 svn_wc__text_base_path_to_read(const char **result_abspath,
                                svn_wc__db_t *db,
                                const char *local_abspath,
@@ -605,15 +587,15 @@ init_adm_tmp_area(const char *path, apr_
   /* SVN_WC__ADM_TMP */
   SVN_ERR(make_adm_subdir(path, SVN_WC__ADM_TMP, FALSE, pool));
 
-  /* SVN_WC__ADM_TMP/SVN_WC__ADM_TEXT_BASE */
-  SVN_ERR(make_adm_subdir(path, SVN_WC__ADM_TEXT_BASE, TRUE, pool));
-
+#if (SVN_WC__VERSION < 18)
   /* SVN_WC__ADM_TMP/SVN_WC__ADM_PROP_BASE */
   SVN_ERR(make_adm_subdir(path, SVN_WC__ADM_PROP_BASE, TRUE, pool));
 
   /* SVN_WC__ADM_TMP/SVN_WC__ADM_PROPS */
-  return svn_error_return(make_adm_subdir(path, SVN_WC__ADM_PROPS, TRUE,
-                                          pool));
+  SVN_ERR(make_adm_subdir(path, SVN_WC__ADM_PROPS, TRUE, pool));
+#endif
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -637,11 +619,13 @@ init_adm(svn_wc__db_t *db,
 
   /** Make subdirectories. ***/
 
+#if (SVN_WC__VERSION < 18)
   /* SVN_WC__ADM_PROP_BASE */
   SVN_ERR(make_adm_subdir(local_abspath, SVN_WC__ADM_PROP_BASE, FALSE, pool));
 
   /* SVN_WC__ADM_PROPS */
   SVN_ERR(make_adm_subdir(local_abspath, SVN_WC__ADM_PROPS, FALSE, pool));
+#endif
 
   /* SVN_WC__ADM_PRISTINE */
   SVN_ERR(make_adm_subdir(local_abspath, SVN_WC__ADM_PRISTINE, FALSE, pool));
@@ -757,7 +741,9 @@ svn_wc__adm_destroy(svn_wc__db_t *db,
                     const char *dir_abspath,
                     apr_pool_t *scratch_pool)
 {
+#ifndef SINGLE_DB
   const char *adm_abspath;
+#endif
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
 
@@ -767,8 +753,10 @@ svn_wc__adm_destroy(svn_wc__db_t *db,
      directory, which also removes the lock */
   SVN_ERR(svn_wc__db_temp_forget_directory(db, dir_abspath, scratch_pool));
 
+#ifndef SINGLE_DB
   adm_abspath = svn_wc__adm_child(dir_abspath, NULL, scratch_pool);
   SVN_ERR(svn_io_remove_dir2(adm_abspath, FALSE, NULL, NULL, scratch_pool));
+#endif
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/performance/subversion/libsvn_wc/adm_files.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/adm_files.h?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/adm_files.h (original)
+++ subversion/branches/performance/subversion/libsvn_wc/adm_files.h Mon Sep  6 19:13:39 2010
@@ -52,14 +52,6 @@ svn_boolean_t svn_wc__adm_area_exists(co
                                       apr_pool_t *pool);
 
 
-/* Set *RESULT_ABSPATH to the deterministic absolute path to where
-   LOCAL_ABSPATH's temporary text-base file is or should be created. */
-svn_error_t *
-svn_wc__text_base_deterministic_tmp_path(const char **result_abspath,
-                                         svn_wc__db_t *db,
-                                         const char *local_abspath,
-                                         apr_pool_t *pool);
-
 /* Set *CONTENTS to a readonly stream on the pristine text of the working
  * version of the file LOCAL_ABSPATH in DB.  If the file is locally copied
  * or moved to this path, this means the pristine text of the copy source,

Modified: subversion/branches/performance/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/adm_ops.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/adm_ops.c Mon Sep  6 19:13:39 2010
@@ -546,75 +546,6 @@ svn_wc_process_committed_queue2(svn_wc_c
 }
 
 
-/* Recursively mark a tree DIR_ABSPATH with schedule svn_wc_schedule_delete
-   and a KEEP_LOCAL flag. */
-static svn_error_t *
-mark_tree_deleted(svn_wc__db_t *db,
-                 const char *dir_abspath,
-                 svn_boolean_t keep_local,
-                 svn_wc_notify_func2_t notify_func,
-                 void *notify_baton,
-                 apr_pool_t *pool)
-{
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  const apr_array_header_t *children;
-  int i;
-
-  /* Read the entries file for this directory. */
-  SVN_ERR(svn_wc__db_read_children(&children, db, dir_abspath,
-                                   pool, iterpool));
-
-  /* Mark each entry in the entries file. */
-  for (i = 0; i < children->nelts; i++)
-    {
-      const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
-      const char *child_abspath;
-      svn_boolean_t hidden;
-      svn_wc__db_kind_t kind;
-
-      /* Clear our per-iteration pool. */
-      svn_pool_clear(iterpool);
-
-      child_abspath = svn_dirent_join(dir_abspath, child_basename, iterpool);
-
-      /* We exclude hidden nodes from this operation. */
-      SVN_ERR(svn_wc__db_node_hidden(&hidden, db, child_abspath, iterpool));
-      if (hidden)
-        continue;
-
-      SVN_ERR(svn_wc__db_read_kind(&kind, db, child_abspath, FALSE, iterpool));
-
-      /* If this is a directory, recurse; otherwise, delete. */
-      if (kind == svn_wc__db_kind_dir)
-        {
-          SVN_ERR(mark_tree_deleted(db, child_abspath,
-                                    keep_local,
-                                    notify_func, notify_baton,
-                                    iterpool));
-        }
-      else
-        {
-          SVN_ERR(svn_wc__db_temp_op_delete(db, child_abspath, iterpool));
-        }
-
-      /* Tell someone what we've done. */
-      if (notify_func != NULL)
-        notify_func(notify_baton,
-                    svn_wc_create_notify(child_abspath,
-                                         svn_wc_notify_delete,
-                                         iterpool),
-                    iterpool);
-    }
-
-  /* Handle directories now, after handling their kiddos. */
-  SVN_ERR(svn_wc__db_temp_op_delete(db, dir_abspath, iterpool));
-  if (keep_local)
-    SVN_ERR(svn_wc__db_temp_set_keep_local(db, dir_abspath, TRUE, iterpool));
-
-  /* Destroy our per-iteration pool. */
-  svn_pool_destroy(iterpool);
-  return SVN_NO_ERROR;
-}
 
 /* Remove/erase PATH from the working copy. This involves deleting PATH
  * from the physical filesystem. PATH is assumed to be an unversioned file
@@ -755,7 +686,8 @@ erase_from_wc(svn_wc__db_t *db,
         }
 
       /* Now handle any remaining unversioned items */
-      err = svn_io_get_dirents2(&unversioned, local_abspath, scratch_pool);
+      err = svn_io_get_dirents3(&unversioned, local_abspath, TRUE,
+                                scratch_pool, scratch_pool);
       if (err)
         {
           svn_pool_destroy(iterpool);
@@ -813,7 +745,6 @@ svn_wc_delete4(svn_wc_context_t *wc_ctx,
   svn_wc__db_t *db = wc_ctx->db;
   svn_boolean_t was_add = FALSE, was_replace = FALSE;
   svn_boolean_t was_copied = FALSE;
-  svn_boolean_t was_deleted = FALSE; /* Silence a gcc uninitialized warning */
   svn_error_t *err;
   svn_wc__db_status_t status;
   svn_wc__db_kind_t kind;
@@ -880,56 +811,42 @@ svn_wc_delete4(svn_wc_context_t *wc_ctx,
         }
     }
 
-  /* ### Maybe we should disallow deleting switched nodes here? */
-
   if (kind == svn_wc__db_kind_dir)
     {
-      svn_revnum_t unused_base_rev;
-
-      SVN_ERR(svn_wc__db_temp_is_dir_deleted(&was_deleted, &unused_base_rev,
-                                             db, local_abspath, pool));
+      
+      apr_pool_t *iterpool = svn_pool_create(pool);
+      const apr_array_header_t *children;
+      int i;
 
-      if (was_add && !was_deleted)
+      SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
+                                       pool, pool));
+      
+      for (i = 0; i < children->nelts; i++)
         {
-          /* Deleting a directory that has been added but not yet
-             committed is easy, just remove the administrative dir. */
+          const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
+          const char *child_abspath;
+          svn_boolean_t hidden;
 
-          SVN_ERR(svn_wc__internal_remove_from_revision_control(
-                                           wc_ctx->db,
-                                           local_abspath,
-                                           FALSE, FALSE,
-                                           cancel_func, cancel_baton,
-                                           pool));
-        }
-      else if (!was_add)
-        {
-          svn_boolean_t available;
+          svn_pool_clear(iterpool);
 
-          /* If the working copy in the subdirectory is not available,
-             we can't mark its tree as deleted. */
-          SVN_ERR(svn_wc__adm_available(&available, NULL, NULL,
-                                        wc_ctx->db, local_abspath,
-                                        pool));
+          child_abspath = svn_dirent_join(local_abspath, child_basename,
+                                          iterpool);
+          SVN_ERR(svn_wc__db_node_hidden(&hidden, db, child_abspath, iterpool));
+          if (hidden)
+            continue;
 
-          if (available)
-            {
-              /* Recursively mark a whole tree for deletion. */
-              SVN_ERR(mark_tree_deleted(wc_ctx->db,
-                                        local_abspath,
-                                        keep_local,
-                                        notify_func, notify_baton,
-                                        pool));
-            }
+          SVN_ERR(svn_wc_delete4(wc_ctx, child_abspath,
+                                 keep_local, delete_unversioned_target,
+                                 cancel_func, cancel_baton,
+                                 notify_func, notify_baton,
+                                 iterpool));
         }
-      /* else
-         ### Handle added directory that is deleted in parent_access
-             (was_deleted=TRUE). The current behavior is to just delete the
-             directory with its administrative area inside, which is OK for
-             WC-1.0, but when we move to a single database per working copy
-             something must unversion the directory. */
+
+      svn_pool_destroy(iterpool);
     }
 
-  if (kind != svn_wc__db_kind_dir || !was_add || was_deleted)
+  /* ### Maybe we should disallow deleting switched nodes here? */
+
     {
       const char *parent_abspath = svn_dirent_dirname(local_abspath, pool);
 
@@ -939,6 +856,8 @@ svn_wc_delete4(svn_wc_context_t *wc_ctx,
              Luckily most of this is for free once properties and pristine
              are handled in the WC-NG way. */
       SVN_ERR(svn_wc__db_temp_op_delete(wc_ctx->db, local_abspath, pool));
+      if (keep_local)
+        SVN_ERR(svn_wc__db_temp_set_keep_local(db, local_abspath, TRUE, pool));
       SVN_ERR(svn_wc__wq_add_delete(wc_ctx->db, parent_abspath, local_abspath,
                                     kind, was_add, was_copied, was_replace,
                                     pool));
@@ -1106,6 +1025,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
                  svn_dirent_local_style(local_abspath, scratch_pool));
 #endif
 
+  SVN_ERR(svn_wc__write_check(db, parent_abspath, scratch_pool));
+
   {
     svn_wc__db_status_t parent_status;
     svn_wc__db_kind_t parent_kind;
@@ -1268,12 +1189,14 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
     }
 #endif
 
+#ifndef SVN_WC__SINGLE_DB
   if (kind == svn_node_dir && !exists)
     {
       /* Lock on parent needs to be propogated into the child db. */
-      SVN_ERR(svn_wc__db_wclock_set(db, local_abspath, 0, scratch_pool));
-      SVN_ERR(svn_wc__db_temp_mark_locked(db, local_abspath, scratch_pool));
+      SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE,
+                                       scratch_pool));
     }
+#endif
 
 #if (SVN_WC__VERSION < SVN_WC__PROPS_IN_DB)
   /* ### this is totally bogus. we clear these cuz turds might have been
@@ -1322,8 +1245,26 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
         }
     }
   else if (!copyfrom_url)
-    SVN_ERR(svn_wc__db_op_add_directory(db, local_abspath, NULL,
-                                        scratch_pool));
+    {
+      SVN_ERR(svn_wc__db_op_add_directory(db, local_abspath, NULL,
+                                          scratch_pool));
+#ifdef SVN_WC__SINGLE_DB
+      if (!exists)
+        {
+          /* If using the legacy 1.6 interface the parent lock may not
+             be recursive and add is expected to lock the new dir.
+
+             ### Perhaps the lock should be created in the same
+             transaction that adds the node? */
+          svn_boolean_t locked;
+          SVN_ERR(svn_wc_locked2(&locked, NULL, wc_ctx, local_abspath,
+                                 scratch_pool));
+          if (!locked)
+            SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE,
+                                             scratch_pool));
+        }
+#endif
+    }
   else if (!is_wc_root)
     SVN_ERR(svn_wc__db_op_copy_dir(db,
                                    local_abspath,
@@ -1350,6 +1291,7 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
       const char *absent_repos_relpath, *absent_repos_root_url;
       const char *absent_repos_uuid;
       svn_revnum_t absent_revision;
+      svn_boolean_t owns_lock;
 
       /* Read the not present status from the parent working copy,
          to reinsert it after hooking up the child working copy */
@@ -1393,6 +1335,15 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
                                                 scratch_pool));
       else
         SVN_ERR(svn_wc__db_base_remove(db, local_abspath, scratch_pool));
+
+      /* The subdir is now part of our parent working copy. Our caller assumes
+         that we return the new node locked, so obtain a lock if we didn't
+         receive the lock via our depth infinity lock */
+      SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, local_abspath, FALSE,
+                                          scratch_pool));
+      if (!owns_lock)
+        SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE,
+                                         scratch_pool));
     }
 
   /* Report the addition to the caller. */
@@ -2018,8 +1969,9 @@ svn_wc__internal_remove_from_revision_co
 
       /* Only check if the file was modified when it wasn't overwritten with a
          special file */
-      SVN_ERR(svn_wc__get_special(&wc_special, db, local_abspath,
-                                  scratch_pool));
+      SVN_ERR(svn_wc__get_translate_info(NULL, NULL, NULL,
+                                         &wc_special, db, local_abspath,
+                                         scratch_pool, scratch_pool));
       SVN_ERR(svn_io_check_special_path(local_abspath, &on_disk,
                                         &local_special, scratch_pool));
       if (wc_special || ! local_special)
@@ -2409,7 +2361,12 @@ svn_wc__set_file_external_location(svn_w
   if (url)
     {
       external_repos_relpath = svn_uri_is_child(repos_root_url, url, NULL);
-      SVN_ERR_ASSERT(external_repos_relpath != NULL);
+
+      if (external_repos_relpath == NULL)
+          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                   _("Can't add a file external to '%s' as it"
+                                     " is not a file in repository '%s'."),
+                                   url, repos_root_url);
 
       external_repos_relpath = svn_path_uri_decode(external_repos_relpath,
                                                    scratch_pool);

Modified: subversion/branches/performance/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/copy.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/copy.c Mon Sep  6 19:13:39 2010
@@ -259,9 +259,9 @@ copy_versioned_file(svn_wc__db_t *db,
     {
       svn_skel_t *work_item;
 
-      SVN_ERR(svn_wc__loggy_move(&work_item, db, dir_abspath,
-                                 tmp_dst_abspath, dst_abspath,
-                                 scratch_pool));
+      SVN_ERR(svn_wc__wq_build_file_move(&work_item, db,
+                                         tmp_dst_abspath, dst_abspath,
+                                         scratch_pool, scratch_pool));
       work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
     }
 
@@ -312,11 +312,12 @@ copy_versioned_dir(svn_wc__db_t *db,
     {
       svn_skel_t *work_item;
 
-      SVN_ERR(svn_wc__loggy_move(&work_item, db, dir_abspath,
-                                 tmp_dst_abspath, dst_abspath,
-                                 scratch_pool));
+      SVN_ERR(svn_wc__wq_build_file_move(&work_item, db,
+                                         tmp_dst_abspath, dst_abspath,
+                                         scratch_pool, scratch_pool));
       work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
 
+#ifndef SVN_WC__SINGLE_DB
       if (kind == svn_node_dir)
         {
           /* Create the per-directory db in the copied directory.  The
@@ -362,7 +363,35 @@ copy_versioned_dir(svn_wc__db_t *db,
 
           if (!repos_root_url)
             {
-              if (status == svn_wc__db_status_added || !have_base)
+              if (status == svn_wc__db_status_deleted)
+                {
+                  const char *work_del_abspath;
+
+                  SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, NULL,
+                                                   &work_del_abspath,
+                                                   db, src_abspath,
+                                                   scratch_pool, scratch_pool));
+                  if (work_del_abspath)
+                    {
+                      const char *parent_del_abspath
+                        = svn_dirent_dirname(work_del_abspath, scratch_pool);
+
+                      SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
+                                                       &repos_root_url,
+                                                       &repos_uuid,
+                                                       NULL, NULL, NULL, NULL,
+                                                       db, parent_del_abspath,
+                                                       scratch_pool,
+                                                       scratch_pool));
+                    }
+                  else
+                    SVN_ERR(svn_wc__db_scan_base_repos(NULL, &repos_root_url,
+                                                       &repos_uuid,
+                                                       db, src_abspath,
+                                                       scratch_pool,
+                                                       scratch_pool));
+                }
+              else if (status == svn_wc__db_status_added || !have_base)
                 SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
                                                  &repos_root_url, &repos_uuid,
                                                  NULL, NULL, NULL, NULL,
@@ -391,6 +420,7 @@ copy_versioned_dir(svn_wc__db_t *db,
           SVN_ERR(svn_wc__db_temp_forget_directory(db, tmp_dst_abspath,
                                                    scratch_pool));
         }
+#endif
     }
 
 #if (SVN_WC__VERSION < SVN_WC__PROPS_IN_DB)
@@ -454,8 +484,11 @@ copy_versioned_dir(svn_wc__db_t *db,
     }
 
   if (kind == svn_node_dir)
-    /* All children, versioned and unversioned */
-    SVN_ERR(svn_io_get_dirents2(&children, src_abspath, scratch_pool));
+    /* All children, versioned and unversioned.  We're only interested in the
+       names of the children, so we can pass TRUE as the only_check_type
+       param. */
+    SVN_ERR(svn_io_get_dirents3(&children, src_abspath, TRUE,
+                                scratch_pool, scratch_pool));
 
   /* Copy all the versioned children */
   SVN_ERR(svn_wc__db_read_children(&versioned_children, db, src_abspath,
@@ -526,9 +559,10 @@ copy_versioned_dir(svn_wc__db_t *db,
           if (tmp_dst_abspath)
             {
               svn_skel_t *work_item;
-              SVN_ERR(svn_wc__loggy_move(&work_item, db, dir_abspath,
-                                         tmp_dst_abspath, unver_dst_abspath,
-                                         iterpool));
+              SVN_ERR(svn_wc__wq_build_file_move(&work_item, db,
+                                                 tmp_dst_abspath,
+                                                 unver_dst_abspath,
+                                                 iterpool, iterpool));
               SVN_ERR(svn_wc__db_wq_add(db, dst_abspath, work_item,
                                         iterpool));
             }

Modified: subversion/branches/performance/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/deprecated.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/deprecated.c Mon Sep  6 19:13:39 2010
@@ -42,6 +42,7 @@
 #include "entries.h"
 #include "lock.h"
 #include "props.h"
+#include "translate.h"
 #include "workqueue.h"
 
 #include "svn_private_config.h"
@@ -420,12 +421,14 @@ svn_wc_transmit_text_deltas2(const char 
                                          svn_wc__adm_get_db(adm_access),
                                          pool));
 
-  SVN_ERR(svn_wc_transmit_text_deltas3(tempfile,
-                                       digest ? &new_text_base_md5_checksum
-                                              : NULL,
-                                       NULL, wc_ctx,
-                                       local_abspath, fulltext, editor,
-                                       file_baton, pool, pool));
+  SVN_ERR(svn_wc__internal_transmit_text_deltas(tempfile,
+                                                (digest
+                                                 ? &new_text_base_md5_checksum
+                                                 : NULL),
+                                                NULL, wc_ctx->db,
+                                                local_abspath, fulltext,
+                                                editor, file_baton,
+                                                pool, pool));
 
   if (digest)
     memcpy(digest, new_text_base_md5_checksum->digest, APR_MD5_DIGESTSIZE);
@@ -2216,12 +2219,18 @@ svn_wc_prop_get(const svn_string_t **val
 
   svn_wc_context_t *wc_ctx;
   const char *local_abspath;
+  svn_error_t *err;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
                                          svn_wc__adm_get_db(adm_access), pool));
 
-  SVN_ERR(svn_wc_prop_get2(value, wc_ctx, local_abspath, name, pool, pool));
+  err = svn_wc_prop_get2(value, wc_ctx, local_abspath, name, pool, pool);
+
+  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+    svn_error_clear(err);
+  else
+    SVN_ERR(err);
 
   return svn_error_return(svn_wc_context_destroy(wc_ctx));
 }
@@ -3293,19 +3302,14 @@ svn_wc_translated_stream(svn_stream_t **
 {
   const char *local_abspath;
   const char *versioned_abspath;
-  svn_wc_context_t *wc_ctx;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
   SVN_ERR(svn_dirent_get_absolute(&versioned_abspath, versioned_file, pool));
-  SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
-                                         svn_wc__adm_get_db(adm_access),
-                                         pool));
 
-  SVN_ERR(svn_wc_translated_stream2(stream, wc_ctx, local_abspath,
-                                    versioned_abspath, flags,
-                                    pool, pool));
-
-  return svn_error_return(svn_wc_context_destroy(wc_ctx));
+  return svn_error_return(
+    svn_wc__internal_translated_stream(stream, svn_wc__adm_get_db(adm_access),
+                                       local_abspath, versioned_abspath, flags,
+                                       pool, pool));
 }
 
 svn_error_t *
@@ -3319,15 +3323,13 @@ svn_wc_translated_file2(const char **xla
   const char *versioned_abspath;
   const char *root;
   const char *tmp_root;
-  svn_wc_context_t *wc_ctx;
 
   SVN_ERR(svn_dirent_get_absolute(&versioned_abspath, versioned_file, pool));
-  SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL,
-                                         svn_wc__adm_get_db(adm_access),
-                                         pool));
 
-  SVN_ERR(svn_wc_translated_file3(xlated_path, src, wc_ctx, versioned_abspath,
-                                  flags, NULL, NULL, pool, pool));
+  SVN_ERR(svn_wc__internal_translated_file(xlated_path, src,
+                                           svn_wc__adm_get_db(adm_access),
+                                           versioned_abspath,
+                                           flags, NULL, NULL, pool, pool));
   if (! svn_dirent_is_absolute(versioned_file))
     {
       SVN_ERR(svn_io_temp_dir(&tmp_root, pool));
@@ -3338,7 +3340,7 @@ svn_wc_translated_file2(const char **xla
         }
     }
 
-  return svn_error_return(svn_wc_context_destroy(wc_ctx));
+  return SVN_NO_ERROR;
 }
 
 /*** From relocate.c ***/

Modified: subversion/branches/performance/subversion/libsvn_wc/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/lock.c?rev=993127&r1=993126&r2=993127&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/lock.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/lock.c Mon Sep  6 19:13:39 2010
@@ -204,7 +204,7 @@ pool_cleanup_locked(void *p)
             {
               /* There is no remaining work, so we're good to remove any
                  potential "physical" lock.  */
-              err = svn_wc__db_wclock_remove(db, lock->abspath, scratch_pool);
+              err = svn_wc__db_wclock_release(db, lock->abspath, scratch_pool);
             }
         }
       svn_error_clear(err);
@@ -312,7 +312,8 @@ adm_access_alloc(svn_wc_adm_access_t **a
       svn_boolean_t owns_lock;
 
       /* If the db already owns a lock, we can't add an extra lock record */
-      SVN_ERR(svn_wc__db_temp_own_lock(&owns_lock, db, path, scratch_pool));
+      SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, path, FALSE,
+                                          scratch_pool));
 
       /* If DB owns the lock, but when there is no access baton open for this
          directory, old access baton based code is trying to access data that
@@ -321,9 +322,8 @@ adm_access_alloc(svn_wc_adm_access_t **a
       if (!owns_lock
           || svn_wc__adm_retrieve_internal2(db, lock->abspath, scratch_pool))
         {
-          SVN_ERR(svn_wc__db_wclock_set(db, lock->abspath, 0, scratch_pool));
-
-          SVN_ERR(svn_wc__db_temp_mark_locked(db, lock->abspath, scratch_pool));
+          SVN_ERR(svn_wc__db_wclock_obtain(db, lock->abspath, 0, FALSE,
+                                           scratch_pool));
         }
     }
 
@@ -332,7 +332,7 @@ adm_access_alloc(svn_wc_adm_access_t **a
   if (err)
     return svn_error_compose_create(
                 err,
-                svn_wc__db_wclock_remove(db, lock->abspath, scratch_pool));
+                svn_wc__db_wclock_release(db, lock->abspath, scratch_pool));
 
   /* ### does this utf8 thing really/still apply??  */
   /* It's important that the cleanup handler is registered *after* at least
@@ -516,8 +516,9 @@ close_single(svn_wc_adm_access_t *adm_ac
     return SVN_NO_ERROR;
 
   /* Physically unlock if required */
-  SVN_ERR(svn_wc__db_temp_own_lock(&locked, adm_access->db,
-                                   adm_access->abspath, scratch_pool));
+  SVN_ERR(svn_wc__db_wclock_owns_lock(&locked, adm_access->db,
+                                      adm_access->abspath, TRUE,
+                                      scratch_pool));
   if (locked)
     {
       if (!preserve_lock)
@@ -528,9 +529,9 @@ close_single(svn_wc_adm_access_t *adm_ac
              from the working copy.  It is an error for the lock to
              have disappeared if the administrative area still exists. */
 
-          svn_error_t *err = svn_wc__db_wclock_remove(adm_access->db,
-                                                      adm_access->abspath,
-                                                      scratch_pool);
+          svn_error_t *err = svn_wc__db_wclock_release(adm_access->db,
+                                                       adm_access->abspath,
+                                                       scratch_pool);
           if (err)
             {
               if (svn_wc__adm_area_exists(adm_access->abspath, scratch_pool))
@@ -1051,43 +1052,15 @@ child_is_disjoint(svn_boolean_t *disjoin
   const char *node_repos_root, *node_repos_relpath, *node_repos_uuid;
   const char *parent_repos_root, *parent_repos_relpath, *parent_repos_uuid;
   svn_wc__db_status_t parent_status;
-  const apr_array_header_t *children;
   const char *parent_abspath, *base;
-  svn_error_t *err;
-  svn_boolean_t found_in_parent = FALSE;
-  int i;
-
-  svn_dirent_split(&parent_abspath, &base, local_abspath, scratch_pool);
 
   /* Check if the parent directory knows about this node */
-  err = svn_wc__db_read_children(&children, db, parent_abspath, scratch_pool,
-                                 scratch_pool);
+  SVN_ERR(svn_wc__db_is_wcroot(disjoint, db, local_abspath, scratch_pool));
 
-  if (err && err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)
-    {
-      svn_error_clear(err);
-      *disjoint = TRUE;
-      return SVN_NO_ERROR;
-    }
-  else
-    SVN_ERR(err);
-
-  for (i = 0; i < children->nelts; i++)
-    {
-      const char *name = APR_ARRAY_IDX(children, i, const char *);
-
-      if (strcmp(name, base) == 0)
-        {
-          found_in_parent = TRUE;
-          break;
-        }
-    }
+  if (*disjoint)
+    return SVN_NO_ERROR;
 
-  if (!found_in_parent)
-    {
-      *disjoint = TRUE;
-      return SVN_NO_ERROR;
-    }
+  svn_dirent_split(&parent_abspath, &base, local_abspath, scratch_pool);
 
   SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, &node_repos_relpath,
                                &node_repos_root, &node_repos_uuid, NULL, NULL,
@@ -1096,8 +1069,8 @@ child_is_disjoint(svn_boolean_t *disjoin
                                db, local_abspath,
                                scratch_pool, scratch_pool));
 
-  /* If the node does not have its own relpath, its value is inherited
-     which tells us that it is not disjoint. */
+  /* If the node does not have its own repos_relpath, its value is inherited
+     from a parent node, which implies that the node is not disjoint. */
   if (node_repos_relpath == NULL)
     {
       *disjoint = FALSE;
@@ -1419,9 +1392,9 @@ svn_wc_adm_locked(const svn_wc_adm_acces
 {
   svn_boolean_t locked;
   apr_pool_t *subpool = svn_pool_create(adm_access->pool);
-  svn_error_t *err = svn_wc__db_temp_own_lock(&locked, adm_access->db,
-                                              adm_access->abspath,
-                                              subpool);
+  svn_error_t *err = svn_wc__db_wclock_owns_lock(&locked, adm_access->db,
+                                                 adm_access->abspath, TRUE,
+                                                 subpool);
   svn_pool_destroy(subpool);
 
   if (err)
@@ -1441,7 +1414,8 @@ svn_wc__write_check(svn_wc__db_t *db,
 {
   svn_boolean_t locked;
 
-  SVN_ERR(svn_wc__db_temp_own_lock(&locked, db, local_abspath, scratch_pool));
+  SVN_ERR(svn_wc__db_wclock_owns_lock(&locked, db, local_abspath, FALSE,
+                                      scratch_pool));
   if (!locked)
     return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
                              _("No write-lock in '%s'"),
@@ -1461,8 +1435,8 @@ svn_wc_locked2(svn_boolean_t *locked_her
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   if (locked_here != NULL)
-    SVN_ERR(svn_wc__db_temp_own_lock(locked_here, wc_ctx->db, local_abspath,
-                                     scratch_pool));
+    SVN_ERR(svn_wc__db_wclock_owns_lock(locked_here, wc_ctx->db, local_abspath,
+                                        FALSE, scratch_pool));
   if (locked != NULL)
     SVN_ERR(svn_wc__db_wclocked(locked, wc_ctx->db, local_abspath,
                                 scratch_pool));
@@ -1552,30 +1526,124 @@ svn_wc__adm_missing(svn_wc__db_t *db,
   return (kind == svn_wc__db_kind_dir) && !available && obstructed;
 }
 
+#ifndef SVN_WC__SINGLE_DB
+static svn_error_t *
+acquire_locks_recursively(svn_wc_context_t *wc_ctx,
+                          const char* local_abspath,
+                          svn_boolean_t lock_root,
+                          apr_pool_t *scratch_pool)
+{
+ svn_wc__db_t *db = wc_ctx->db;
+  const apr_array_header_t *children;
+  apr_pool_t *iterpool;
+  svn_error_t *err;
+  int i;
+  int format;
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
+                                   scratch_pool, iterpool));
+
+  /* The current lock paradigm is that each directory holds a lock for itself,
+     and there are no inherited locks.  In the eventual wc-ng paradigm, a
+     lock on a directory, would imply a infinite-depth lock on the children.
+     But since we aren't quite there yet, we do the infinite locking
+     manually (and be sure to release them in svn_wc__release_write_lock(). */
+
+  for (i = 0; i < children->nelts; i ++)
+    {
+      svn_wc__db_kind_t kind;
+      const char *child_relpath = APR_ARRAY_IDX(children, i, const char *);
+      const char *child_abspath;
+
+      svn_pool_clear(iterpool);
+      child_abspath = svn_dirent_join(local_abspath, child_relpath, iterpool);
+
+      SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath, FALSE,
+                                   iterpool));
+      if (kind == svn_wc__db_kind_dir)
+        {
+          err = acquire_locks_recursively(wc_ctx, child_abspath, FALSE,
+                                         iterpool);
+          if (err && err->apr_err == SVN_ERR_WC_LOCKED)
+            {
+              while(i >= 0)
+                {
+                  svn_error_t *err2;
+                  svn_pool_clear(iterpool);
+                  child_relpath = APR_ARRAY_IDX(children, i, const char *);
+                  child_abspath = svn_dirent_join(local_abspath, child_relpath,
+                                                  iterpool);
+
+                  /* Don't release locks on non-directories as that will
+                     try to release the lock on the parent directory! */
+                  err2 = svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath,
+                                              FALSE, iterpool);
+
+                  if (!err2 && kind == svn_wc__db_kind_dir)
+                    err2 = svn_wc__release_write_lock(wc_ctx, child_abspath,
+                                                      iterpool);
+
+                  err = svn_error_compose_create(err, err2);
+                  --i;
+                }
+              return svn_error_return(err);
+            }
+        }
+    }
+
+  if (lock_root)
+    SVN_ERR(svn_wc__db_wclock_obtain(db, local_abspath, 0, FALSE, iterpool));
+  else
+    {
+      /* We don't want to try and lock an unversioned directory that
+         obstructs a versioned directory. */
+      err = svn_wc__internal_check_wc(&format, wc_ctx->db, local_abspath,
+                                      iterpool);
+
+      if (!err && format)
+          SVN_ERR(svn_wc__db_wclock_obtain(wc_ctx->db, local_abspath, 0, FALSE,
+                                          iterpool));
+
+      svn_error_clear(err);
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+#endif
 
 svn_error_t *
-svn_wc__acquire_write_lock(const char **anchor_abspath,
+svn_wc__acquire_write_lock(const char **lock_root_abspath,
                            svn_wc_context_t *wc_ctx,
                            const char *local_abspath,
+                           svn_boolean_t lock_anchor,
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool)
 {
+  svn_wc__db_t *db = wc_ctx->db;
   svn_wc__db_kind_t kind;
-  apr_pool_t *iterpool;
-  const apr_array_header_t *children;
-  int format, i;
   svn_error_t *err;
-
-  SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
+  SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath,
+                               (lock_root_abspath != NULL),
                                scratch_pool));
 
-  if (anchor_abspath)
+  if (!lock_root_abspath && kind != svn_wc__db_kind_dir)
+    return svn_error_createf(SVN_ERR_WC_NOT_DIRECTORY, NULL,
+                             _("Can't obtain lock on non-directory '%s'."),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+
+  if (lock_anchor)
     {
       const char *parent_abspath;
       svn_wc__db_kind_t parent_kind;
 
+      SVN_ERR_ASSERT(lock_root_abspath != NULL);
+
       parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-      err = svn_wc__db_read_kind(&parent_kind, wc_ctx->db, parent_abspath, TRUE,
+      err = svn_wc__db_read_kind(&parent_kind, db, parent_abspath, TRUE,
                                  scratch_pool);
       if (err && SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
         {
@@ -1600,67 +1668,36 @@ svn_wc__acquire_write_lock(const char **
                                  _("'%s' is not a working copy"),
                                  svn_dirent_local_style(local_abspath,
                                                         scratch_pool));
-
-      *anchor_abspath = apr_pstrdup(result_pool, local_abspath);
     }
   else if (kind != svn_wc__db_kind_dir)
-    local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
-  SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
-                                   scratch_pool, scratch_pool));
-
-  /* The current lock paradigm is that each directory holds a lock for itself,
-     and there are no inherited locks.  In the eventual wc-ng paradigm, a
-     lock on a directory, would imply a infinite-depth lock on the children.
-     But since we aren't quite there yet, we do the infinite locking
-     manually (and be sure to release them in svn_wc__release_write_lock(). */
-
-  iterpool = svn_pool_create(scratch_pool);
-  for (i = 0; i < children->nelts; i ++)
     {
-      const char *child_relpath = APR_ARRAY_IDX(children, i, const char *);
-      const char *child_abspath;
-
-      svn_pool_clear(iterpool);
-      child_abspath = svn_dirent_join(local_abspath, child_relpath, iterpool);
+      local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
-      SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath, FALSE,
-                                   iterpool));
-      if (kind == svn_wc__db_kind_dir)
+      /* Can't lock parents that don't exist */
+      if (kind == svn_wc__db_kind_unknown)
         {
-          err = svn_wc__acquire_write_lock(NULL, wc_ctx, child_abspath, NULL,
-                                           iterpool);
-          if (err && err->apr_err == SVN_ERR_WC_LOCKED)
-            {
-              while(i >= 0)
-                {
-                  svn_error_t *err2;
-                  svn_pool_clear(iterpool);
-                  child_relpath = APR_ARRAY_IDX(children, i, const char *);
-                  child_abspath = svn_dirent_join(local_abspath, child_relpath,
-                                                  iterpool);
-                   err2 = svn_wc__release_write_lock(wc_ctx, child_abspath,
-                                                     iterpool);
-                   if (err2)
-                     svn_error_compose(err, err2);
-                   --i;
-                }
-              return svn_error_return(err);
-            }
+          SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE,
+                                       scratch_pool));
+
+          if (kind != svn_wc__db_kind_dir)
+            return svn_error_createf(
+                             SVN_ERR_WC_NOT_DIRECTORY, NULL,
+                             _("Can't obtain lock on non-directory '%s'."),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
         }
     }
 
-  /* We don't want to try and lock an unversioned directory that
-     obstructs a versioned directory. */
-  err = svn_wc__internal_check_wc(&format, wc_ctx->db, local_abspath, iterpool);
-  if (!err && format)
-    {
-      SVN_ERR(svn_wc__db_wclock_set(wc_ctx->db, local_abspath, 0, iterpool));
-      SVN_ERR(svn_wc__db_temp_mark_locked(wc_ctx->db, local_abspath, iterpool));
-    }
-  svn_error_clear(err);
+  if (lock_root_abspath)
+    *lock_root_abspath = apr_pstrdup(result_pool, local_abspath);
 
-  svn_pool_destroy(iterpool);
+#ifndef SVN_WC__SINGLE_DB
+  SVN_ERR(acquire_locks_recursively(wc_ctx, local_abspath, TRUE,
+                                    scratch_pool));
+#else
+  SVN_ERR(svn_wc__db_wclock_obtain(wc_ctx->db, local_abspath, -1, FALSE,
+                                   scratch_pool));
+#endif
 
   return SVN_NO_ERROR;
 }
@@ -1679,10 +1716,20 @@ svn_wc__release_write_lock(svn_wc_contex
   svn_boolean_t locked_here;
   int i;
 
-  SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
-                               scratch_pool));
-  if (kind != svn_wc__db_kind_dir)
-    local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+#ifndef SVN_WC__SINGLE_DB
+  SVN_ERR(svn_wc__db_wclock_owns_lock(&locked_here, wc_ctx->db, local_abspath,
+                                      TRUE, scratch_pool));
+
+  if (!locked_here)
+    {
+      /* Make wclock_release() check if the node should have been locked,
+         like when the node is no wcroot (so can't have a multi-db lock) */
+      SVN_ERR(svn_wc__db_wclock_release(wc_ctx->db, local_abspath,
+                                        scratch_pool));
+
+      return SVN_NO_ERROR;
+    }
+#endif
 
   SVN_ERR(svn_wc__db_wq_fetch(&id, &work_item, wc_ctx->db, local_abspath,
                               scratch_pool, scratch_pool));
@@ -1692,6 +1739,7 @@ svn_wc__release_write_lock(svn_wc_contex
       return SVN_NO_ERROR;
     }
 
+#ifndef SVN_WC__SINGLE_DB
   /* We need to recursively remove locks (see comment in
      svn_wc__acquire_write_lock(). */
 
@@ -1710,16 +1758,24 @@ svn_wc__release_write_lock(svn_wc_contex
       SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath, FALSE,
                                    iterpool));
       if (kind == svn_wc__db_kind_dir)
-        SVN_ERR(svn_wc__release_write_lock(wc_ctx, child_abspath, iterpool));
+        {
+          svn_error_t *err = svn_wc__release_write_lock(wc_ctx, child_abspath, iterpool);
+
+          if (err && err->apr_err == SVN_ERR_WC_NOT_LOCKED)
+            svn_error_clear(err);
+          else
+            SVN_ERR(err);
+        }
     }
 
-  SVN_ERR(svn_wc__db_temp_own_lock(&locked_here, wc_ctx->db, local_abspath,
-                                   iterpool));
-  if (locked_here)
-    SVN_ERR(svn_wc__db_wclock_remove(wc_ctx->db, local_abspath, iterpool));
+  SVN_ERR(svn_wc__db_wclock_release(wc_ctx->db, local_abspath, iterpool));
 
   svn_pool_destroy(iterpool);
 
+#else
+  SVN_ERR(svn_wc__db_wclock_release(wc_ctx->db, local_abspath, scratch_pool));
+#endif
+
   return SVN_NO_ERROR;
 }
 
@@ -1728,14 +1784,16 @@ svn_wc__call_with_write_lock(svn_wc__wit
                              void *baton,
                              svn_wc_context_t *wc_ctx,
                              const char *local_abspath,
+                             svn_boolean_t lock_anchor,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
 {
   svn_error_t *err1, *err2;
-  SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath,
-                                     scratch_pool, scratch_pool));
-  err1 = func(baton, result_pool, scratch_pool);
-  err2 = svn_wc__release_write_lock(wc_ctx, local_abspath, scratch_pool);
+  const char *lock_root_abspath;
+  SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, wc_ctx, local_abspath,
+                                     lock_anchor, scratch_pool, scratch_pool));
+  err1 = svn_error_return(func(baton, result_pool, scratch_pool));
+  err2 = svn_wc__release_write_lock(wc_ctx, lock_root_abspath, scratch_pool);
   return svn_error_compose_create(err1, err2);
 }