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/10/25 19:50:28 UTC

svn commit: r1027203 [2/5] - in /subversion/branches/performance: ./ notes/http-and-webdav/ subversion/bindings/ctypes-python/csvn/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_fs/ subversion/libsvn_fs_...

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=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/adm_ops.c Mon Oct 25 17:50:25 2010
@@ -1246,183 +1246,6 @@ svn_wc__register_file_external(svn_wc_co
 */
 
 
-/* */
-static svn_error_t *
-revert_admin_things(svn_boolean_t *reverted,
-                    svn_wc__db_t *db,
-                    const char *local_abspath,
-                    svn_boolean_t use_commit_times,
-                    apr_pool_t *pool)
-{
-  SVN_ERR(svn_wc__wq_add_revert(reverted, db, local_abspath, use_commit_times,
-                                pool));
-  SVN_ERR(svn_wc__wq_run(db, local_abspath, NULL, NULL, pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Revert LOCAL_ABSPATH in DB, where the on-disk node kind is DISK_KIND.
-   *DEPTH is the depth of the reversion crawl the caller is
-   using; this function may choose to override that value as needed.
-
-   See svn_wc_revert4() for the interpretations of
-   USE_COMMIT_TIMES, CANCEL_FUNC and CANCEL_BATON.
-
-   Set *DID_REVERT to true if actually reverting anything, else do not
-   touch *DID_REVERT.
-
-   Use POOL for allocations.
- */
-static svn_error_t *
-revert_entry(svn_depth_t *depth,
-             svn_wc__db_t *db,
-             const char *local_abspath,
-             svn_node_kind_t disk_kind,
-             svn_boolean_t use_commit_times,
-             svn_cancel_func_t cancel_func,
-             void *cancel_baton,
-             svn_boolean_t *did_revert,
-             apr_pool_t *pool)
-{
-  svn_wc__db_status_t status, base_status;
-  svn_wc__db_kind_t kind, base_kind;
-  svn_boolean_t replaced;
-  svn_boolean_t have_base;
-  svn_revnum_t base_revision;
-  svn_boolean_t is_add_root;
-
-  /* Initialize this even though revert_admin_things() is guaranteed
-     to set it, because we don't know that revert_admin_things() will
-     be called. */
-  svn_boolean_t reverted = FALSE;
-
-  SVN_ERR(svn_wc__db_read_info(&status, &kind,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, &have_base, NULL,
-                               NULL, NULL,
-                               db, local_abspath, pool, pool));
-
-  if (have_base)
-    SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, &base_revision,
-                                     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, NULL, NULL, NULL,
-                                     db, local_abspath, pool, pool));
-
-  replaced = (status == svn_wc__db_status_added
-              && have_base
-              && base_status != svn_wc__db_status_not_present);
-
-  if (status == svn_wc__db_status_added)
-    {
-      const char *op_root_abspath;
-      SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       db, local_abspath, pool, pool));
-
-      is_add_root = (strcmp(op_root_abspath, local_abspath) == 0);
-    }
-  else
-    is_add_root = FALSE;
-
-  /* Additions. */
-  if (!replaced
-      && is_add_root)
-    {
-      const char *repos_relpath;
-      const char *repos_root_url;
-      const char *repos_uuid;
-      /* Before removing item from revision control, notice if the
-         BASE_NODE is in a 'not-present' state. */
-      svn_boolean_t was_not_present = FALSE;
-
-      /* NOTE: if WAS_NOT_PRESENT gets set, then we have BASE nodes.
-         The code below will then figure out the repository information, so
-         that we can later insert a node for the same repository. */
-
-      if (have_base
-          && base_status == svn_wc__db_status_not_present)
-        {
-          /* Remember the BASE revision. (already handled)  */
-          /* Remember the repository this node is associated with.  */
-
-          was_not_present = TRUE;
-
-          SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
-                                             &repos_root_url,
-                                             &repos_uuid,
-                                             db, local_abspath,
-                                             pool, pool));
-        }
-
-      /* ### much of this is probably bullshit. we should be able to just
-         ### remove the WORKING and ACTUAL rows, and be done. but we're
-         ### not quite there yet, so nodes get fully removed and then
-         ### shoved back into the database. this is why we need to record
-         ### the repository information, and the BASE revision.  */
-
-      if (kind == svn_wc__db_kind_file
-          || kind == svn_wc__db_kind_dir)
-        {
-          SVN_ERR(svn_wc__internal_remove_from_revision_control(db,
-                                                                local_abspath,
-                                                                FALSE, FALSE,
-                                                                cancel_func,
-                                                                cancel_baton,
-                                                                pool));
-        }
-      else  /* Else it's `none', or something exotic like a symlink... */
-        {
-          return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-                                   _("Unknown or unexpected kind for path "
-                                     "'%s'"),
-                                   svn_dirent_local_style(local_abspath,
-                                                          pool));
-
-        }
-
-      /* Recursivity is taken care of by svn_wc_remove_from_revision_control,
-         and we've definitely reverted PATH at this point. */
-      *depth = svn_depth_empty;
-      reverted = TRUE;
-
-      /* If the removed item was *also* in a 'not-present' state, make
-         sure we leave a not-present node behind */
-      if (was_not_present)
-        {
-          SVN_ERR(svn_wc__db_base_add_not_present_node(
-                    db, local_abspath,
-                    repos_relpath, repos_root_url, repos_uuid,
-                    base_revision,
-                    base_kind,
-                    NULL, NULL,
-                    pool));
-        }
-    }
-  /* Regular prop and text edit. */
-  /* Deletions and replacements. */
-  else if (status == svn_wc__db_status_normal
-           || status == svn_wc__db_status_deleted
-           || replaced
-           || (status == svn_wc__db_status_added && !is_add_root))
-    {
-      /* Revert the prop and text mods (if any). */
-      SVN_ERR(revert_admin_things(&reverted, db, local_abspath,
-                                  use_commit_times, pool));
-
-      /* Force recursion on replaced directories. */
-      if (kind == svn_wc__db_kind_dir && replaced)
-        *depth = svn_depth_infinity;
-    }
-
-  /* If PATH was reverted, tell our client that. */
-  if (reverted)
-    *did_revert = TRUE;
-
-  return SVN_NO_ERROR;
-}
-
 /* Verifies if an add (or copy) to LOCAL_ABSPATH can be reverted with depth
  * DEPTH, without touching nodes that are filtered by DEPTH.
  *
@@ -1496,6 +1319,7 @@ verify_revert_depth(svn_wc__db_t *db,
    documentation. */
 static svn_error_t *
 revert_internal(svn_wc__db_t *db,
+                const char *revert_root,
                 const char *local_abspath,
                 svn_depth_t depth,
                 svn_boolean_t use_commit_times,
@@ -1507,10 +1331,14 @@ revert_internal(svn_wc__db_t *db,
                 apr_pool_t *pool)
 {
   svn_node_kind_t disk_kind;
-  svn_wc__db_status_t status;
+  svn_wc__db_status_t status, base_status;
   svn_wc__db_kind_t db_kind;
   svn_boolean_t unversioned;
+  svn_boolean_t have_base;
+  svn_boolean_t replaced;
+  svn_boolean_t reverted = FALSE;
   const svn_wc_conflict_description2_t *tree_conflict;
+  const char *op_root_abspath = NULL;
   svn_error_t *err;
 
   /* Check cancellation here, so recursive calls get checked early. */
@@ -1523,7 +1351,7 @@ revert_internal(svn_wc__db_t *db,
   err = svn_wc__db_read_info(&status, &db_kind,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                             NULL, NULL, NULL, NULL, &have_base, NULL, NULL,
                              NULL,
                              db, local_abspath, pool, pool);
 
@@ -1542,11 +1370,30 @@ revert_internal(svn_wc__db_t *db,
         case svn_wc__db_status_excluded:
           unversioned = TRUE;
           break;
+        case svn_wc__db_status_incomplete:
+          /* Remove NAME from PATH's entries file
+
+             Not being able to revert incomplete entries breaks working
+             copies flat out, but the usual revert process can't be
+             applied.  Most preconditions aren't met. */
+          SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath, pool));
+          return SVN_NO_ERROR;
+          break;
         default:
           unversioned = FALSE;
           break;
       }
 
+  if (! unversioned && have_base)
+    SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL,
+                                     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                     NULL, NULL, NULL, NULL, NULL,
+                                     db, local_abspath, pool, pool));
+
+  replaced = ! unversioned && (status == svn_wc__db_status_added
+              && have_base
+              && base_status != svn_wc__db_status_not_present);
+
   SVN_ERR(svn_wc__db_op_read_tree_conflict(&tree_conflict, db, local_abspath,
                                            pool, pool));
   if (unversioned && tree_conflict == NULL)
@@ -1586,8 +1433,13 @@ revert_internal(svn_wc__db_t *db,
        svn_dirent_local_style(local_abspath, pool));
 
   /* Safeguard 3:  can we deal with the node kind of PATH currently in
-     the working copy? */
-  if ((disk_kind != svn_node_none)
+     the working copy?
+
+     Note: we can reach this point for paths which have tree conflict info
+           set on them.  Those are not necessarily nodes we can version,
+           meaning this check doesn't make sense for unversioned nodes. */
+  if (!unversioned
+      && (disk_kind != svn_node_none)
       && (disk_kind != svn_node_file)
       && (disk_kind != svn_node_dir))
     return svn_error_createf
@@ -1595,17 +1447,18 @@ revert_internal(svn_wc__db_t *db,
        _("Cannot revert '%s': unsupported node kind in working copy"),
        svn_dirent_local_style(local_abspath, pool));
 
+  if (!unversioned && status == svn_wc__db_status_added)
+    SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
+                                     NULL, NULL, NULL, NULL, NULL,
+                                     db, local_abspath, pool, pool));
+
   /* Safeguard 4:  Make sure we don't revert deeper then asked */
-  if (status == svn_wc__db_status_added
+  if (!unversioned
+      && status == svn_wc__db_status_added
       && db_kind == svn_wc__db_kind_dir
       && depth >= svn_depth_empty
       && depth < svn_depth_infinity)
     {
-      const char *op_root_abspath;
-      SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       db, local_abspath, pool, pool));
-
       /* If this node is an operation root for a copy/add, then reverting
          it will change its descendants, if it has any. */
       if (strcmp(local_abspath, op_root_abspath) == 0)
@@ -1617,7 +1470,6 @@ revert_internal(svn_wc__db_t *db,
   if (svn_wc__internal_changelist_match(db, local_abspath, changelist_hash,
                                         pool))
     {
-      svn_boolean_t reverted = FALSE;
       const svn_wc_conflict_description2_t *conflict;
 
       /* Clear any tree conflict on the path, even if it is not a versioned
@@ -1634,10 +1486,19 @@ revert_internal(svn_wc__db_t *db,
       /* Actually revert this entry.  If this is a working copy root,
          we provide a base_name from the parent path. */
       if (!unversioned)
-        SVN_ERR(revert_entry(&depth, db, local_abspath, disk_kind,
-                             use_commit_times,
-                             cancel_func, cancel_baton,
-                             &reverted, pool));
+        {
+          /* Revert the prop, text and tree mods (if any). */
+          SVN_ERR(svn_wc__wq_add_revert(&reverted, db, revert_root,
+                                        local_abspath, use_commit_times,
+                                        pool));
+          SVN_ERR(svn_wc__wq_run(db, local_abspath,
+                                 cancel_func, cancel_baton, pool));
+
+          /* Force recursion on replaced directories. */
+          if (db_kind == svn_wc__db_kind_dir && replaced)
+            depth = svn_depth_infinity;
+
+        }
 
       /* Notify */
       if (notify_func && reverted)
@@ -1647,7 +1508,23 @@ revert_internal(svn_wc__db_t *db,
                        pool);
     }
 
+
+  if (op_root_abspath && strcmp(local_abspath, op_root_abspath) == 0)
+    /* If this is a copy or add root, disable notifications for the children,
+       because wc-1.0 used to behave like that. */
+    {
+      notify_func = NULL;
+      notify_baton = NULL;
+    }
+
   /* Finally, recurse if requested. */
+
+  /* ### This doesn't work properly for added directories.  Reverting
+     ### the parent before the children is wrong, it means node rows
+     ### exist for the children after the parent row is removed.
+     ### Either the wq revert of the parent above has to remove the
+     ### children or this recursion has to do children before parents.
+   */
   if (!unversioned && db_kind == svn_wc__db_kind_dir && depth > svn_depth_empty)
     {
       const apr_array_header_t *children;
@@ -1690,7 +1567,7 @@ revert_internal(svn_wc__db_t *db,
             continue;
 
           /* Revert the entry. */
-          SVN_ERR(revert_internal(db, node_abspath,
+          SVN_ERR(revert_internal(db, revert_root, node_abspath,
                                   depth_under_here, use_commit_times,
                                   changelist_hash, cancel_func, cancel_baton,
                                   notify_func, notify_baton, iterpool));
@@ -1734,7 +1611,8 @@ revert_internal(svn_wc__db_t *db,
                                 const svn_wc_conflict_description2_t *);
 
                 if (conflict->kind == svn_wc_conflict_kind_tree)
-                  SVN_ERR(revert_internal(db, conflict->local_abspath,
+                  SVN_ERR(revert_internal(db, revert_root,
+                                          conflict->local_abspath,
                                           svn_depth_empty,
                                           use_commit_times, changelist_hash,
                                           cancel_func, cancel_baton,
@@ -1747,6 +1625,20 @@ revert_internal(svn_wc__db_t *db,
       svn_pool_destroy(iterpool);
     }
 
+  if (reverted  /* implies !unversioned; only versioned paths get reverted */
+      && ! replaced
+      && status == svn_wc__db_status_added
+      && db_kind == svn_wc__db_kind_dir)
+    {
+      /* Non-replaced directories have their admin area deleted. wc-1.0 */
+      /* In wc-ng, this call does not really delete the admin area - since
+         there isn't one - but it does destroy the adm_access structure
+         which may be cached inside DB, if the DB is used with old entries
+         functions. */
+      SVN_ERR(svn_wc__adm_destroy(db, local_abspath,
+                                  cancel_func, cancel_baton, pool));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1769,7 +1661,7 @@ svn_wc_revert4(svn_wc_context_t *wc_ctx,
     SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelists, pool));
 
   return svn_error_return(revert_internal(wc_ctx->db,
-                                          local_abspath, depth,
+                                          local_abspath, local_abspath, depth,
                                           use_commit_times, changelist_hash,
                                           cancel_func, cancel_baton,
                                           notify_func, notify_baton,

Modified: subversion/branches/performance/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/conflicts.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/conflicts.c Mon Oct 25 17:50:25 2010
@@ -220,6 +220,7 @@ resolve_conflict_on_node(svn_wc__db_t *d
 
   if (resolve_text)
     {
+      svn_stream_t *tmp_stream = NULL;
       const char *auto_resolve_src;
 
       /* Handle automatic conflict resolution before the temporary files are
@@ -244,7 +245,6 @@ resolve_conflict_on_node(svn_wc__db_t *d
             if (conflict_old && conflict_working && conflict_new)
               {
                 const char *temp_dir;
-                svn_stream_t *tmp_stream;
                 svn_diff_t *diff;
                 svn_diff_conflict_display_style_t style =
                   conflict_choice == svn_wc_conflict_choose_theirs_conflict
@@ -256,7 +256,8 @@ resolve_conflict_on_node(svn_wc__db_t *d
                                                        pool, pool));
                 SVN_ERR(svn_stream_open_unique(&tmp_stream,
                                                &auto_resolve_src,
-                                               temp_dir, svn_io_file_del_none,
+                                               temp_dir,
+                                               svn_io_file_del_on_close,
                                                pool, pool));
 
                 /* ### If any of these paths isn't absolute, treat it
@@ -290,7 +291,6 @@ resolve_conflict_on_node(svn_wc__db_t *d
                                                     NULL, NULL, NULL, NULL,
                                                     style,
                                                     pool));
-                SVN_ERR(svn_stream_close(tmp_stream));
               }
             else
               auto_resolve_src = NULL;
@@ -305,6 +305,9 @@ resolve_conflict_on_node(svn_wc__db_t *d
         SVN_ERR(svn_io_copy_file(
           svn_dirent_join(conflict_dir_abspath, auto_resolve_src, pool),
           local_abspath, TRUE, pool));
+
+      if (tmp_stream)
+        SVN_ERR(svn_stream_close(tmp_stream));
     }
 
   /* Records whether we found any of the conflict files.  */

Modified: subversion/branches/performance/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/copy.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/copy.c Mon Oct 25 17:50:25 2010
@@ -197,11 +197,6 @@ copy_pristine_text_if_necessary(svn_wc__
    otherwise copy both the versioned metadata and the filesystem node (even
    if it is the wrong kind, and recursively if it is a dir).
 
-   A replacement for both copy_file_administratively and
-   copy_added_file_administratively.
-
-   ### Not yet fully working.  Relies on in-db-props.
-
    This also works for versioned symlinks that are stored in the db as
    svn_wc__db_kind_file with svn:special set. */
 static svn_error_t *
@@ -238,10 +233,22 @@ copy_versioned_file(svn_wc__db_t *db,
                              tmpdir_abspath,
                              TRUE, /* recursive */
                              cancel_func, cancel_baton, scratch_pool));
+
       if (tmp_dst_abspath)
         {
           svn_skel_t *work_item;
 
+          /* Remove 'read-only' from the destination file; it's a local add. */
+            {
+              const svn_string_t *needs_lock;
+              SVN_ERR(svn_wc__internal_propget(&needs_lock, db, src_abspath,
+                                               SVN_PROP_NEEDS_LOCK,
+                                               scratch_pool, scratch_pool));
+              if (needs_lock)
+                SVN_ERR(svn_io_set_file_read_write(tmp_dst_abspath,
+                                                   FALSE, scratch_pool));
+            }
+
           SVN_ERR(svn_wc__wq_build_file_move(&work_item, db,
                                              tmp_dst_abspath, dst_abspath,
                                              scratch_pool, scratch_pool));
@@ -426,6 +433,50 @@ copy_versioned_dir(svn_wc__db_t *db,
 }
 
 
+#ifdef SVN_WC__OP_DEPTH
+/*
+A plan for copying a versioned node, recursively, with proper op-depths.
+
+Each DB change mentioned in a separate step is intended to change the WC
+from one valid state to another and must be exectuted within a DB txn.
+Several such changes can be batched together in a bigger txn if we don't
+want clients to be able to see intermediate states.
+
+### TODO: This plan doesn't yet provide well for notification of all copied
+    paths.
+
+copy-versioned_node:
+  # Copy a versioned file/dir SRC_PATH to DST_PATH, recursively.
+
+  # This function takes care to copy both the metadata tree and the disk
+  # tree as they are, even if they are different node kinds and so different
+  # tree shapes.
+
+  src_op_depth = working_op_depth_of(src_path)
+  src_depth = relpath_depth(src_path)
+  dst_depth = relpath_depth(dst_path)
+
+  # The source tree has in the NODES table, by design:
+  #   - zero or more rows below SRC_OP_DEPTH (these are uninteresting);
+  #   - one or more rows at SRC_OP_DEPTH;
+  #   - no rows with SRC_OP_DEPTH < row.op_depth <= SRC_DEPTH;
+  #   - zero or more rows above SRC_DEPTH (modifications);
+  # and SRC_OP_DEPTH <= SRC_DEPTH.
+
+  Copy single NODES row from src_path@src_op_depth to dst_path@dst_depth.
+  Copy all rows of descendent paths in == src_op_depth to == dst_depth.
+  Copy all rows of descendent paths in > src_depth to > dst_depth,
+    adjusting op_depth by (dst_depth - src_depth).
+
+  Copy disk node recursively (if it exists, and whatever its kind).
+  Copy ACTUAL_NODE rows (props and any other actual metadata).
+
+  # ### Are there no scenarios in which we would want to decrease dst_depth
+  #     and so subsume the destination into an existing op?  I guess not.
+
+*/
+#endif
+
 
 /* Public Interface */
 

Modified: subversion/branches/performance/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/props.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/props.c Mon Oct 25 17:50:25 2010
@@ -139,30 +139,9 @@ svn_wc__get_prejfile_abspath(const char 
 static svn_error_t *
 immediate_install_props(svn_wc__db_t *db,
                         const char *local_abspath,
-                        svn_wc__db_kind_t kind,
                         apr_hash_t *working_props,
                         apr_pool_t *scratch_pool)
 {
-  apr_hash_t *base_props;
-
-  /* ### no pristines should be okay.  */
-  SVN_ERR_W(svn_wc__db_read_pristine_props(&base_props, db, local_abspath,
-                                           scratch_pool, scratch_pool),
-            _("Failed to load pristine properties"));
-
-  /* Check if the props are modified. If no changes, then wipe out
-     the ACTUAL props. No pristines defined means that any ACTUAL
-     props are okay, so go ahead and set them.  */
-  if (base_props != NULL)
-    {
-      apr_array_header_t *prop_diffs;
-
-      SVN_ERR(svn_prop_diffs(&prop_diffs, working_props, base_props,
-                             scratch_pool));
-      if (prop_diffs->nelts == 0)
-        working_props = NULL;
-    }
-
   SVN_ERR(svn_wc__db_op_set_props(db, local_abspath,
                                   working_props,
                                   NULL /* conflict */,
@@ -350,7 +329,6 @@ svn_wc__perform_props_merge(svn_wc_notif
       {
         svn_wc__db_status_t status;
         svn_boolean_t have_base;
-        apr_array_header_t *prop_diffs;
 
         SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL,
                                      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -365,41 +343,18 @@ svn_wc__perform_props_merge(svn_wc_notif
           SVN_ERR(svn_wc__db_temp_base_set_props(db, local_abspath,
                                                  new_base_props, pool));
 
-        /* Check if the props are modified. */
-        SVN_ERR(svn_prop_diffs(&prop_diffs, actual_props, new_base_props, pool));
-
-        /* Save the actual properties file if it differs from base. */
-        if (prop_diffs->nelts == 0)
-          SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, NULL, NULL, NULL,
-                                          pool));
-        else
-          SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props,
-                                          NULL, NULL, pool));
+        SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props,
+                                        NULL, NULL, pool));
       }
 #else
       if (base_merge)
         return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                                 U_("base_merge=TRUE is no longer supported"));
 
-      {
-        apr_array_header_t *prop_diffs;
-
-        SVN_ERR(svn_prop_diffs(&prop_diffs, new_actual_props, new_base_props,
-                               pool));
-
-        /* Save the actual properties file if it differs from base. */
-        if (prop_diffs->nelts == 0)
-          new_actual_props = NULL; /* Remove actual properties*/
-
-        /* For the old school: write the properties into the "working"
-           (aka ACTUAL) location. Note that PROPS may be NULL, indicating
-           a removal of the props file.  */
-
-        SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, new_actual_props,
-                                        NULL /* conflict */,
-                                        NULL /* work_item */,
-                                        pool));
-      }
+      SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, new_actual_props,
+                                      NULL /* conflict */,
+                                      NULL /* work_item */,
+                                      pool));
 #endif
 
       SVN_ERR(svn_wc__wq_run(db, local_abspath,
@@ -2185,7 +2140,7 @@ svn_wc__internal_propset(svn_wc__db_t *d
 
   /* Drop it right onto the disk. We don't need loggy since we aren't
      coordinating this change with anything else.  */
-  SVN_ERR(immediate_install_props(db, local_abspath, kind, prophash,
+  SVN_ERR(immediate_install_props(db, local_abspath, prophash,
                                   scratch_pool));
 
   if (notify_func)

Modified: subversion/branches/performance/subversion/libsvn_wc/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/relocate.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/relocate.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/relocate.c Mon Oct 25 17:50:25 2010
@@ -82,9 +82,9 @@ svn_wc_relocate4(svn_wc_context_t *wc_ct
 {
   svn_wc__db_kind_t kind;
   const char *repos_relpath;
-  const char *old_repos_root;
-  const char *old_url;
-  const char *new_repos_root;
+  const char *old_repos_root, *old_url;
+  const char *new_repos_root, *new_url;
+  int from_len, old_url_len;
   const char *uuid;
   svn_boolean_t is_wc_root;
 
@@ -129,16 +129,28 @@ svn_wc_relocate4(svn_wc_context_t *wc_ct
                             _("Cannot relocate a single file"));
 
   old_url = svn_uri_join(old_repos_root, repos_relpath, scratch_pool);
-  if (strcmp(old_url, from) != 0)
-    return svn_error_create(SVN_ERR_WC_INVALID_RELOCATION, NULL,
-                            _("Given source URL invalid"));
+  old_url_len = strlen(old_url);
+  from_len = strlen(from);
+  if ((from_len > old_url_len) || (strncmp(old_url, from, strlen(from)) != 0))
+    return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL,
+                             _("Invalid source URL prefix: '%s' (does not "
+                               "overlap target's URL '%s')"),
+                             from, old_url);
+  
+  if (old_url_len == from_len)
+    new_url = to;
+  else
+    new_url = apr_pstrcat(scratch_pool, to, old_url + from_len, NULL);
+  if (! svn_path_is_url(new_url))
+    return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL,
+                             _("Invalid destination URL: '%s'"), new_url);
 
-  new_repos_root = uri_remove_components(to, repos_relpath, scratch_pool);
+  new_repos_root = uri_remove_components(new_url, repos_relpath, scratch_pool);
   if (!new_repos_root)
     return svn_error_createf(SVN_ERR_WC_INVALID_RELOCATION, NULL,
-                             _("Given destination URL invalid: '%s'"), to);
+                             _("Invalid destination URL: '%s'"), new_url);
 
-  SVN_ERR(validator(validator_baton, uuid, to, new_repos_root, scratch_pool));
+  SVN_ERR(validator(validator_baton, uuid, new_url, new_repos_root, scratch_pool));
 
   return svn_error_return(svn_wc__db_global_relocate(wc_ctx->db, local_abspath,
                                                      new_repos_root,

Modified: subversion/branches/performance/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/status.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/status.c Mon Oct 25 17:50:25 2010
@@ -233,6 +233,115 @@ struct file_baton
 
 
 /** Code **/
+
+/* Fill in *INFO with the information it would contain if it were
+   obtained from svn_wc__db_read_children_info. */
+static svn_error_t *
+read_info(const struct svn_wc__db_info_t **info,
+          const char *local_abspath,
+          svn_wc__db_t *db,
+          apr_pool_t *result_pool,
+          apr_pool_t *scratch_pool)
+{
+  struct svn_wc__db_info_t *mutable 
+    = apr_palloc(scratch_pool, sizeof(struct svn_wc__db_info_t));
+
+  SVN_ERR(svn_wc__db_read_info(&mutable->status, &mutable->kind,
+                               &mutable->revnum, &mutable->repos_relpath,
+                               &mutable->repos_root_url, NULL,
+                               &mutable->changed_rev,
+                               &mutable->changed_date,
+                               &mutable->changed_author,
+                               &mutable->last_mod_time,
+                               &mutable->depth, NULL,
+                               &mutable->translated_size, NULL,
+                               &mutable->changelist, NULL, NULL, NULL, NULL,
+                               &mutable->props_mod,
+                               &mutable->have_base, NULL,
+                               &mutable->conflicted, &mutable->lock,
+                               db, local_abspath,
+                               result_pool, scratch_pool));
+
+  if (mutable->status == svn_wc__db_status_deleted)
+    mutable->has_props = FALSE;
+  else if (mutable->props_mod)
+    {
+      mutable->has_props = TRUE;
+#ifdef HAVE_SYMLINK
+      SVN_ERR(svn_wc__get_translate_info(NULL, NULL, NULL, &mutable->special,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool));
+#endif
+    }
+  else
+    {
+      apr_hash_t *properties;
+
+      SVN_ERR(svn_wc__db_read_pristine_props(&properties, db, local_abspath,
+                                             scratch_pool, scratch_pool));
+      mutable->has_props = (properties && !!apr_hash_count(properties));
+#ifdef HAVE_SYMLINK
+      mutable->special = (mutable->has_props
+                          && apr_hash_get(properties, SVN_PROP_SPECIAL,
+                                          APR_HASH_KEY_STRING));
+#endif
+    }
+
+  *info = mutable;
+
+  return SVN_NO_ERROR;
+}
+
+/* Return *REPOS_RELPATH and *REPOS_ROOT_URL for LOCAL_ABSPATH using
+   information in INFO if available, falling back on
+   PARENT_REPOS_RELPATH and PARENT_REPOS_ROOT_URL if available, and
+   finally falling back on querying DB. */
+static svn_error_t *
+get_repos_root_url_relpath(const char **repos_relpath,
+                           const char **repos_root_url,
+                           const struct svn_wc__db_info_t *info,
+                           const char *parent_repos_relpath,
+                           const char *parent_repos_root_url,
+                           svn_wc__db_t *db,
+                           const char *local_abspath,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  if (info->repos_relpath && info->repos_root_url)
+    {
+      *repos_relpath = info->repos_relpath;
+      *repos_root_url = info->repos_root_url;
+    }
+  else if (parent_repos_relpath && parent_repos_root_url)
+    {
+      *repos_relpath = svn_relpath_join(parent_repos_relpath,
+                                        svn_dirent_basename(local_abspath,
+                                                            NULL),
+                                        scratch_pool);
+      *repos_root_url = parent_repos_root_url;
+    }
+  else if (info->status == svn_wc__db_status_added)
+    {
+      SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
+                                       repos_relpath, repos_root_url,
+                                       NULL, NULL, NULL, NULL, NULL,
+                                       db, local_abspath,
+                                       result_pool, scratch_pool));
+    }
+  else if (info->have_base)
+    {
+      SVN_ERR(svn_wc__db_scan_base_repos(repos_relpath, repos_root_url, NULL,
+                                         db, local_abspath,
+                                         result_pool, scratch_pool));
+    }
+  else
+    {
+      *repos_relpath = NULL;
+      *repos_root_url = NULL;
+    }
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 internal_status(svn_wc_status3_t **status,
                 svn_wc__db_t *db,
@@ -262,6 +371,7 @@ assemble_status(svn_wc_status3_t **statu
                 const char *local_abspath,
                 const char *parent_repos_root_url,
                 const char *parent_repos_relpath,
+                const struct svn_wc__db_info_t *info,
                 const svn_io_dirent2_t *dirent,
                 svn_boolean_t get_all,
                 const svn_lock_t *repos_lock,
@@ -269,76 +379,32 @@ assemble_status(svn_wc_status3_t **statu
                 apr_pool_t *scratch_pool)
 {
   svn_wc_status3_t *stat;
-  svn_wc__db_status_t db_status;
-  svn_wc__db_kind_t db_kind;
-  const char *repos_relpath;
-  const char *repos_root_url;
   svn_boolean_t switched_p = FALSE;
-  svn_boolean_t prop_modified_p;
-  svn_wc__db_lock_t *lock;
-  svn_revnum_t revision;
-  svn_revnum_t changed_rev;
-  const char *changed_author;
-  apr_time_t changed_date;
-  const char *changelist;
-  svn_boolean_t have_base;
-  svn_boolean_t conflicted;
   svn_boolean_t copied = FALSE;
-  svn_filesize_t translated_size;
-  apr_time_t last_mod_time;
-  svn_depth_t depth;
+  svn_boolean_t conflicted;
   svn_error_t *err;
+  const char *repos_relpath;
+  const char *repos_root_url;
 
   /* Defaults for two main variables. */
   enum svn_wc_status_kind node_status = svn_wc_status_normal;
   enum svn_wc_status_kind text_status = svn_wc_status_normal;
   enum svn_wc_status_kind prop_status = svn_wc_status_none;
 
-  SVN_ERR(svn_wc__db_read_info(&db_status, &db_kind, &revision,
-                               &repos_relpath, &repos_root_url, NULL,
-                               &changed_rev, &changed_date,
-                               &changed_author, &last_mod_time, &depth, NULL,
-                               &translated_size, NULL, &changelist, NULL, NULL,
-                               NULL, NULL, &prop_modified_p, &have_base, NULL,
-                               &conflicted, &lock, db, local_abspath,
-                               result_pool, scratch_pool));
 
-  if (!repos_relpath)
-    {
-      /* The node is not switched, so imply from parent if possible */
-
-      if (parent_repos_relpath != NULL)
-        repos_relpath = svn_relpath_join(parent_repos_relpath,
-                                         svn_dirent_basename(local_abspath,
-                                                             NULL),
-                                         result_pool);
-      else if (db_status == svn_wc__db_status_added)
-        SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath,
-                                         &repos_root_url, NULL, NULL, NULL,
-                                         NULL, NULL,
-                                         db, local_abspath,
-                                         result_pool, scratch_pool));
-      else if (have_base)
-        SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
-                                           &repos_root_url, NULL,
-                                           db, local_abspath,
-                                           result_pool, scratch_pool));
+  if (!info)
+    SVN_ERR(read_info(&info, local_abspath, db, result_pool, scratch_pool));
 
-      switched_p = FALSE;
-    }
-  else if (!parent_repos_relpath)
+  if (!info->repos_relpath || !parent_repos_relpath)
     switched_p = FALSE;
   else
     {
       /* A node is switched if it doesn't have the implied repos_relpath */
-
-      const char *name = svn_relpath_is_child(parent_repos_relpath, repos_relpath, NULL);
+      const char *name = svn_relpath_is_child(parent_repos_relpath,
+                                              info->repos_relpath, NULL);
       switched_p = !name || (strcmp(name, svn_dirent_basename(local_abspath, NULL)) != 0);
     }
 
-  if (!repos_root_url && parent_repos_root_url)
-    repos_root_url = apr_pstrdup(result_pool, parent_repos_root_url);
-
   /* Examine whether our target is missing or obstructed or missing.
 
      While we are not completely in single-db mode yet, data about
@@ -347,14 +413,14 @@ assemble_status(svn_wc_status3_t **statu
      mode these obstructions are no longer reported and we have
      to detect obstructions by looking at the on disk status in DIRENT.
      */
-  if (db_kind == svn_wc__db_kind_dir)
+  if (info->kind == svn_wc__db_kind_dir)
     {
-      if (db_status == svn_wc__db_status_incomplete)
+      if (info->status == svn_wc__db_status_incomplete)
         {
           /* Highest precedence.  */
           node_status = svn_wc_status_incomplete;
         }
-      else if (db_status == svn_wc__db_status_deleted)
+      else if (info->status == svn_wc__db_status_deleted)
         {
           node_status = svn_wc_status_deleted;
 
@@ -374,7 +440,7 @@ assemble_status(svn_wc_status3_t **statu
     }
   else
     {
-      if (db_status == svn_wc__db_status_deleted)
+      if (info->status == svn_wc__db_status_deleted)
         {
           node_status = svn_wc_status_deleted;
 
@@ -400,13 +466,11 @@ assemble_status(svn_wc_status3_t **statu
      It means that no further information is available, and we should skip
      all this work.  */
   if (node_status == svn_wc_status_normal
-      || (node_status == svn_wc_status_missing && db_kind != svn_wc__db_kind_dir))
+      || (node_status == svn_wc_status_missing
+          && info->kind != svn_wc__db_kind_dir))
     {
       svn_boolean_t has_props;
       svn_boolean_t text_modified_p = FALSE;
-#ifdef HAVE_SYMLINK
-      svn_boolean_t wc_special;
-#endif /* HAVE_SYMLINK */
 
       /* Implement predecence rules: */
 
@@ -415,43 +479,30 @@ assemble_status(svn_wc_status3_t **statu
             precedence over M. */
 
       /* Does the node have props? */
-      if (db_status == svn_wc__db_status_deleted)
+      if (info->status == svn_wc__db_status_deleted)
         has_props = FALSE; /* Not interesting */
-      else if (prop_modified_p)
+      else if (info->props_mod)
         has_props = TRUE;
       else
-        {
-          apr_hash_t *props;
-        
-          SVN_ERR(svn_wc__db_read_pristine_props(&props, db, local_abspath,
-                                                 scratch_pool, scratch_pool));
+        has_props = info->has_props;
 
-          has_props = (props != NULL && apr_hash_count(props) > 0);
-        }
       if (has_props)
         prop_status = svn_wc_status_normal;
 
       /* If the entry has a properties, see if it has local changes. */
       if (has_props)
-        prop_status = prop_modified_p ? svn_wc_status_modified
+        prop_status = info->props_mod ? svn_wc_status_modified
                                       : svn_wc_status_normal;
 
-#ifdef HAVE_SYMLINK
-      if (has_props)
-        SVN_ERR(svn_wc__get_translate_info(NULL, NULL, NULL,
-                                           &wc_special,
-                                           db, local_abspath,
-                                           scratch_pool, scratch_pool));
-      else
-        wc_special = FALSE;
-#endif /* HAVE_SYMLINK */
+      /* ### Don't read properties twice!  Cache wc_special in
+             svn_wc__db_read_children_info. */
 
       /* If the entry is a file, check for textual modifications */
       if (node_status != svn_wc_status_missing
-          && (db_kind == svn_wc__db_kind_file
-              || db_kind == svn_wc__db_kind_symlink)
+          && (info->kind == svn_wc__db_kind_file
+              || info->kind == svn_wc__db_kind_symlink)
 #ifdef HAVE_SYMLINK
-             && (wc_special == (dirent && dirent->special))
+             && (info->special == (dirent && dirent->special))
 #endif /* HAVE_SYMLINK */
           )
         {
@@ -463,8 +514,8 @@ assemble_status(svn_wc_status3_t **statu
           if (dirent
               && dirent->filesize != SVN_INVALID_FILESIZE
               && dirent->mtime != 0
-              && translated_size == dirent->filesize
-              && last_mod_time == dirent->mtime)
+              && info->translated_size == dirent->filesize
+              && info->last_mod_time == dirent->mtime)
             text_modified_p = FALSE;
           else
             {
@@ -488,14 +539,16 @@ assemble_status(svn_wc_status3_t **statu
             }
         }
 #ifdef HAVE_SYMLINK
-      else if (wc_special != (dirent && dirent->special))
+      else if (info->special != (dirent && dirent->special))
         node_status = svn_wc_status_obstructed;
 #endif /* HAVE_SYMLINK */
 
+
       if (text_modified_p)
         text_status = svn_wc_status_modified;
     }
 
+  conflicted = info->conflicted;
   if (conflicted)
     {
       svn_boolean_t text_conflicted, prop_conflicted, tree_conflicted;
@@ -517,7 +570,7 @@ assemble_status(svn_wc_status3_t **statu
             of medium precedence.  They also override any C or M that may
             be in the prop_status field at this point, although they do not
             override a C text status.*/
-      if (db_status == svn_wc__db_status_added)
+      if (info->status == svn_wc__db_status_added)
         {
           svn_wc_schedule_t schedule;
           SVN_ERR(svn_wc__internal_node_get_schedule(&schedule, &copied,
@@ -546,21 +599,26 @@ assemble_status(svn_wc_status3_t **statu
          || (node_status == svn_wc_status_normal))
 
         && (! switched_p)
-        && (! lock) 
+        && (! info->lock) 
         && (! repos_lock)
-        && (! changelist)
+        && (! info->changelist)
         && (! conflicted))
       {
         *status = NULL;
         return SVN_NO_ERROR;
       }
 
+  SVN_ERR(get_repos_root_url_relpath(&repos_relpath, &repos_root_url, info,
+                                     parent_repos_relpath,
+                                     parent_repos_root_url,
+                                     db, local_abspath,
+                                     scratch_pool, scratch_pool));
 
   /* 6. Build and return a status structure. */
 
   stat = apr_pcalloc(result_pool, sizeof(**status));
 
-  switch (db_kind)
+  switch (info->kind)
     {
       case svn_wc__db_kind_dir:
         stat->kind = svn_node_dir;
@@ -573,7 +631,7 @@ assemble_status(svn_wc_status3_t **statu
       default:
         stat->kind = svn_node_unknown;
     }
-  stat->depth = depth;
+  stat->depth = info->depth;
   stat->node_status = node_status;
   stat->text_status = text_status;
   stat->prop_status = prop_status;
@@ -583,24 +641,24 @@ assemble_status(svn_wc_status3_t **statu
   stat->switched = switched_p;
   stat->copied = copied;
   stat->repos_lock = repos_lock;
-  stat->revision = revision;
-  stat->changed_rev = changed_rev;
-  stat->changed_author = changed_author;
-  stat->changed_date = changed_date;
+  stat->revision = info->revnum;
+  stat->changed_rev = info->changed_rev;
+  stat->changed_author = info->changed_author;
+  stat->changed_date = info->changed_date;
 
   stat->ood_kind = svn_node_none;
   stat->ood_changed_rev = SVN_INVALID_REVNUM;
   stat->ood_changed_date = 0;
   stat->ood_changed_author = NULL;
 
-  if (lock)
+  if (info->lock)
     {
       svn_lock_t *lck = apr_pcalloc(result_pool, sizeof(*lck));
       lck->path = repos_relpath;
-      lck->token = lock->token;
-      lck->owner = lock->owner;
-      lck->comment = lock->comment;
-      lck->creation_date = lock->date;
+      lck->token = info->lock->token;
+      lck->owner = info->lock->owner;
+      lck->comment = info->lock->comment;
+      lck->creation_date = info->lock->date;
       stat->lock = lck;
     }
   else
@@ -608,7 +666,7 @@ assemble_status(svn_wc_status3_t **statu
 
   stat->conflicted = conflicted;
   stat->versioned = TRUE;
-  stat->changelist = changelist;
+  stat->changelist = info->changelist;
   stat->repos_root_url = repos_root_url;
   stat->repos_relpath = repos_relpath;
 
@@ -699,6 +757,7 @@ send_status_structure(const struct walk_
                       const char *local_abspath,
                       const char *parent_repos_root_url,
                       const char *parent_repos_relpath,
+                      const struct svn_wc__db_info_t *info,
                       const svn_io_dirent2_t *dirent,
                       svn_boolean_t get_all,
                       svn_wc_status_func4_t status_func,
@@ -711,30 +770,13 @@ send_status_structure(const struct walk_
   /* Check for a repository lock. */
   if (wb->repos_locks)
     {
-      const char *repos_relpath;
-      svn_wc__db_status_t status;
-      svn_boolean_t have_base;
-
-      SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, &repos_relpath, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, &have_base, NULL, NULL, NULL, 
-                                   wb->db, local_abspath,
-                                   scratch_pool, scratch_pool));
-
-      /* A switched path can be deleted: check the right relpath */
-      if (status == svn_wc__db_status_deleted && have_base)
-        SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, NULL,
-                                           NULL, wb->db, local_abspath,
-                                           scratch_pool, scratch_pool));
-
-      if (!repos_relpath && parent_repos_relpath)
-        repos_relpath = svn_relpath_join(parent_repos_relpath,
-                                         svn_dirent_basename(local_abspath,
-                                                             NULL),
-                                         scratch_pool);
-
+      const char *repos_relpath, *repos_root_url;
 
+      SVN_ERR(get_repos_root_url_relpath(&repos_relpath, &repos_root_url,
+                                         info, parent_repos_relpath,
+                                         parent_repos_root_url,
+                                         wb->db, local_abspath,
+                                         scratch_pool, scratch_pool));
       if (repos_relpath)
         {
           /* repos_lock still uses the deprecated filesystem absolute path
@@ -748,7 +790,7 @@ send_status_structure(const struct walk_
 
   SVN_ERR(assemble_status(&statstruct, wb->db, local_abspath,
                           parent_repos_root_url, parent_repos_relpath,
-                          dirent, get_all,
+                          info, dirent, get_all,
                           repos_lock, scratch_pool, scratch_pool));
 
   if (statstruct && status_func)
@@ -910,6 +952,7 @@ get_dir_status(const struct walk_status_
                svn_boolean_t skip_this_dir,
                const char *parent_repos_root_url,
                const char *parent_repos_relpath,
+               const struct svn_wc__db_info_t *dir_info,
                const svn_io_dirent2_t *dirent,
                const apr_array_header_t *ignores,
                svn_depth_t depth,
@@ -931,6 +974,7 @@ handle_dir_entry(const struct walk_statu
                  svn_wc__db_kind_t db_kind,
                  const char *dir_repos_root_url,
                  const char *dir_repos_relpath,
+                 const struct svn_wc__db_info_t *entry_info,
                  svn_io_dirent2_t *dirent,
                  const apr_array_header_t *ignores,
                  svn_depth_t depth,
@@ -963,6 +1007,7 @@ handle_dir_entry(const struct walk_statu
         {
           SVN_ERR(get_dir_status(wb, local_abspath, NULL, FALSE,
                                  dir_repos_root_url, dir_repos_relpath,
+                                 entry_info,
                                  dirent, ignores, depth, get_all, no_ignore,
                                  status_func, status_baton, cancel_func,
                                  cancel_baton,
@@ -975,7 +1020,7 @@ handle_dir_entry(const struct walk_statu
           SVN_ERR(send_status_structure(wb, local_abspath,
                                         dir_repos_root_url,
                                         dir_repos_relpath,
-                                        dirent, get_all,
+                                        entry_info, dirent, get_all,
                                         status_func, status_baton, pool));
         }
     }
@@ -985,7 +1030,7 @@ handle_dir_entry(const struct walk_statu
       SVN_ERR(send_status_structure(wb, local_abspath,
                                     dir_repos_root_url,
                                     dir_repos_relpath,
-                                    dirent, get_all,
+                                    entry_info, dirent, get_all,
                                     status_func, status_baton, pool));
     }
 
@@ -1067,6 +1112,7 @@ get_dir_status(const struct walk_status_
                svn_boolean_t skip_this_dir,
                const char *parent_repos_root_url,
                const char *parent_repos_relpath,
+               const struct svn_wc__db_info_t *dir_info,
                const svn_io_dirent2_t *dirent,
                const apr_array_header_t *ignore_patterns,
                svn_depth_t depth,
@@ -1083,29 +1129,20 @@ get_dir_status(const struct walk_status_
   const char *dir_repos_relpath;
   apr_hash_t *dirents, *nodes, *conflicts, *all_children;
   apr_array_header_t *patterns = NULL;
-  svn_wc__db_status_t dir_status;
-  svn_depth_t dir_depth;
   apr_pool_t *iterpool, *subpool = svn_pool_create(scratch_pool);
   svn_error_t *err;
 
-  /* See if someone wants to cancel this operation. */
   if (cancel_func)
     SVN_ERR(cancel_func(cancel_baton));
 
   if (depth == svn_depth_unknown)
     depth = svn_depth_infinity;
 
-  /* Make our iteration pool. */
   iterpool = svn_pool_create(subpool);
 
-  /* Load list of childnodes. */
-  {
-    const apr_array_header_t *child_nodes;
-
-    SVN_ERR(svn_wc__db_read_children(&child_nodes, wb->db, local_abspath,
-                                     iterpool, iterpool));
-    SVN_ERR(svn_hash_from_cstring_keys(&nodes, child_nodes, subpool));
-  }
+  SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
+                                        wb->db, local_abspath,
+                                        subpool, iterpool));
 
   err = svn_io_get_dirents3(&dirents, local_abspath, FALSE, subpool, subpool);
   if (err
@@ -1118,77 +1155,36 @@ get_dir_status(const struct walk_status_
   else
     SVN_ERR(err);
 
-  SVN_ERR(svn_wc__db_read_info(&dir_status, NULL, NULL, &dir_repos_relpath,
-                               &dir_repos_root_url, NULL, NULL, NULL, NULL,
-                               NULL, &dir_depth, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, wb->db, local_abspath, scratch_pool,
-                               scratch_pool));
-
-  if (dir_repos_relpath == NULL)
-    {
-      if (parent_repos_root_url != NULL)
-        {
-          dir_repos_root_url = parent_repos_root_url;
-          dir_repos_relpath = svn_relpath_join(
-                                    parent_repos_relpath,
-                                    svn_dirent_basename(local_abspath, NULL),
-                                    scratch_pool);
-        }
-      else if (dir_status != svn_wc__db_status_deleted
-               && dir_status != svn_wc__db_status_added)
-        SVN_ERR(svn_wc__db_scan_base_repos(&dir_repos_relpath,
-                                           &dir_repos_root_url,
-                                           NULL, wb->db, local_abspath,
-                                           scratch_pool, scratch_pool));
-      else
-        {
-          dir_repos_relpath = NULL;
-          dir_repos_root_url = NULL;
-        }
-    }
-
+  if (!dir_info)
+    SVN_ERR(read_info(&dir_info, local_abspath, wb->db,
+                      scratch_pool, scratch_pool));
+
+  SVN_ERR(get_repos_root_url_relpath(&dir_repos_relpath, &dir_repos_root_url,
+                                     dir_info, parent_repos_relpath,
+                                     parent_repos_root_url,
+                                     wb->db, local_abspath,
+                                     scratch_pool, scratch_pool));
   if (selected == NULL)
     {
-      const apr_array_header_t *victims;
-      /* Create a hash containing all children */
+      /* Create a hash containing all children.  The source hashes
+         don't all map the same types, but only the keys of the result
+         hash are subsequently used. */
       all_children = apr_hash_overlay(subpool, nodes, dirents);
-
-      SVN_ERR(svn_wc__db_read_conflict_victims(&victims,
-                                               wb->db, local_abspath,
-                                               iterpool, iterpool));
-
-      SVN_ERR(svn_hash_from_cstring_keys(&conflicts, victims, subpool));
-
-      /* Optimize for the no-tree-conflict case */
       if (apr_hash_count(conflicts) > 0)
         all_children = apr_hash_overlay(subpool, conflicts, all_children);
     }
   else
     {
-      const svn_wc_conflict_description2_t *tc;
-      const char *selected_abspath;
-
-      conflicts = apr_hash_make(subpool);
+      /* Create a hash containing just selected */
       all_children = apr_hash_make(subpool);
-
       apr_hash_set(all_children, selected, APR_HASH_KEY_STRING, selected);
-
-      selected_abspath = svn_dirent_join(local_abspath, selected, iterpool);
-
-      SVN_ERR(svn_wc__db_op_read_tree_conflict(&tc, wb->db, selected_abspath,
-                                               iterpool, iterpool));
-
-      /* Note this path if a tree conflict is present.  */
-      if (tc != NULL)
-        apr_hash_set(conflicts, selected, APR_HASH_KEY_STRING, "");
     }
 
   /* If "this dir" has "svn:externals" property set on it, send the name and
      value to wc->external_func along with this directory's depth. (Also,
      we want to track the externals internally so we can report status more
      accurately.) */
-  SVN_ERR(handle_externals(wb, local_abspath, dir_depth, iterpool));
+  SVN_ERR(handle_externals(wb, local_abspath, dir_info->depth, iterpool));
 
   if (!selected)
     {
@@ -1197,7 +1193,7 @@ get_dir_status(const struct walk_status_
         SVN_ERR(send_status_structure(wb, local_abspath,
                                       parent_repos_root_url,
                                       parent_repos_relpath,
-                                      dirent, get_all,
+                                      dir_info, dirent, get_all,
                                       status_func, status_baton,
                                       iterpool));
 
@@ -1215,6 +1211,7 @@ get_dir_status(const struct walk_status_
       apr_ssize_t klen;
       const char *node_abspath;
       svn_io_dirent2_t *dirent_p;
+      const struct svn_wc__db_info_t *info;
 
       svn_pool_clear(iterpool);
 
@@ -1224,32 +1221,24 @@ get_dir_status(const struct walk_status_
 
       dirent_p = apr_hash_get(dirents, key, klen);
 
-      if (apr_hash_get(nodes, key, klen))
+      info = apr_hash_get(nodes, key, klen);
+      if (info)
         {
-          /* Versioned node */
-          svn_wc__db_status_t node_status;
-          svn_wc__db_kind_t node_kind;
-
-          SVN_ERR(svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL,
-                                   wb->db, node_abspath, iterpool, iterpool));
-
-          if (node_status != svn_wc__db_status_not_present
-              && node_status != svn_wc__db_status_excluded
-              && node_status != svn_wc__db_status_absent)
+          if (info->status != svn_wc__db_status_not_present
+              && info->status != svn_wc__db_status_excluded
+              && info->status != svn_wc__db_status_absent)
             {
-              if (depth == svn_depth_files && node_kind == svn_wc__db_kind_dir)
+              if (depth == svn_depth_files && info->kind == svn_wc__db_kind_dir)
                 continue;
 
               /* Handle this entry (possibly recursing). */
               SVN_ERR(handle_dir_entry(wb,
                                        node_abspath,
-                                       node_status,
-                                       node_kind,
+                                       info->status,
+                                       info->kind,
                                        dir_repos_root_url,
                                        dir_repos_relpath,
+                                       info,
                                        dirent_p,
                                        ignore_patterns,
                                        depth == svn_depth_infinity
@@ -1592,6 +1581,7 @@ make_dir_baton(void **dir_baton,
       SVN_ERR(get_dir_status(&eb->wb, local_abspath, NULL, TRUE,
                              status_in_parent->repos_root_url,
                              status_in_parent->repos_relpath,
+                             NULL,
                              NULL /* dirent */, ignores,
                              d->depth == svn_depth_files
                                       ? svn_depth_files
@@ -1765,6 +1755,7 @@ handle_statii(struct edit_baton *eb,
           SVN_ERR(get_dir_status(&eb->wb,
                                  local_abspath, NULL, TRUE,
                                  dir_repos_root_url, dir_repos_relpath,
+                                 NULL,
                                  NULL /* dirent */,
                                  ignores, depth, eb->get_all, eb->no_ignore,
                                  status_func, status_baton,
@@ -2033,7 +2024,7 @@ close_directory(void *dir_baton,
                 {
                   SVN_ERR(get_dir_status(&eb->wb,
                                          eb->target_abspath, NULL, TRUE,
-                                         NULL, NULL, NULL /* dirent */,
+                                         NULL, NULL, NULL, NULL /* dirent */,
                                          eb->ignores,
                                          eb->default_depth,
                                          eb->get_all, eb->no_ignore,
@@ -2415,7 +2406,7 @@ svn_wc_walk_status(svn_wc_context_t *wc_
                          anchor_abspath,
                          target_name,
                          skip_root,
-                         NULL, NULL, /* parent info */
+                         NULL, NULL, NULL, /* parent info */
                          dirent,
                          ignore_patterns,
                          depth,
@@ -2553,6 +2544,7 @@ internal_status(svn_wc_status3_t **statu
   return svn_error_return(assemble_status(status, db, local_abspath,
                                           parent_repos_root_url,
                                           parent_repos_relpath,
+                                          NULL,
                                           dirent,
                                           TRUE /* get_all */,
                                           NULL /* repos_lock */,

Modified: subversion/branches/performance/subversion/libsvn_wc/translate.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/translate.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/translate.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/translate.c Mon Oct 25 17:50:25 2010
@@ -376,6 +376,7 @@ svn_wc__maybe_set_read_only(svn_boolean_
                             apr_pool_t *scratch_pool)
 {
   const svn_string_t *needs_lock;
+  svn_wc__db_status_t status;
   svn_wc__db_lock_t *lock;
   svn_error_t *err;
 
@@ -384,7 +385,7 @@ svn_wc__maybe_set_read_only(svn_boolean_
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  err = svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL,
+  err = svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL,
@@ -399,6 +400,11 @@ svn_wc__maybe_set_read_only(svn_boolean_
   else if (err)
     return svn_error_return(err);
   else if (lock)
+    /* ### Is this "we have the lock?" */
+    return SVN_NO_ERROR;
+
+  /* Files that aren't in the repository yet should be left writable. */
+  if (status == svn_wc__db_status_added)
     return SVN_NO_ERROR;
 
   SVN_ERR(svn_wc__internal_propget(&needs_lock, db, local_abspath,

Modified: subversion/branches/performance/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/update_editor.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/update_editor.c Mon Oct 25 17:50:25 2010
@@ -2925,22 +2925,10 @@ close_directory(void *dir_baton,
          item to write out an old-style props file.  */
       if (new_base_props != NULL)
         {
-          apr_array_header_t *prop_diffs;
-
           SVN_ERR_ASSERT(new_actual_props != NULL);
 
-          /* If the ACTUAL props are the same as the BASE props, then we
-             should "write" a NULL. This will remove the props from the
-             ACTUAL_NODE row, and remove the old-style props file, indicating
-             "no change".  */
-          props = new_actual_props;
-          SVN_ERR(svn_prop_diffs(&prop_diffs, new_actual_props, new_base_props,
-                                 pool));
-          if (prop_diffs->nelts == 0)
-            props = NULL;
-
           SVN_ERR(svn_wc__db_op_set_props(eb->db, db->local_abspath,
-                                          props,
+                                          new_actual_props,
                                           NULL /* conflict */,
                                           NULL /* work_items */,
                                           pool));
@@ -4389,32 +4377,31 @@ close_file(void *file_baton,
       /* We will ALWAYS have properties to save (after a not-dry-run merge).  */
       SVN_ERR_ASSERT(new_base_props != NULL && new_actual_props != NULL);
 
-    /* Merge the text. This will queue some additional work.  */
-    SVN_ERR(merge_file(&all_work_items, &install_pristine, &install_from,
-                       &content_state, fb, new_text_base_sha1_checksum,
-                       pool, scratch_pool));
+      /* Merge the text. This will queue some additional work.  */
+      SVN_ERR(merge_file(&all_work_items, &install_pristine, &install_from,
+                         &content_state, fb, new_text_base_sha1_checksum,
+                         pool, scratch_pool));
 
-    if (install_pristine)
-      {
-        svn_boolean_t record_fileinfo;
+      if (install_pristine)
+        {
+          svn_boolean_t record_fileinfo;
 
-        /* If we are installing from the pristine contents, then go ahead and
-           record the fileinfo. That will be the "proper" values. Installing
-           from some random file means the fileinfo does NOT correspond to
-           the pristine (in which case, the fileinfo will be cleared for
-           safety's sake).  */
-        record_fileinfo = install_from == NULL;
-
-        SVN_ERR(svn_wc__wq_build_file_install(&work_item,
-                                              eb->db,
-                                              fb->local_abspath,
-                                              install_from,
-                                              eb->use_commit_times,
-                                              record_fileinfo,
-                                              pool, pool));
-        all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
-      }
+          /* If we are installing from the pristine contents, then go ahead and
+             record the fileinfo. That will be the "proper" values. Installing
+             from some random file means the fileinfo does NOT correspond to
+             the pristine (in which case, the fileinfo will be cleared for
+             safety's sake).  */
+          record_fileinfo = install_from == NULL;
 
+          SVN_ERR(svn_wc__wq_build_file_install(&work_item,
+                                                eb->db,
+                                                fb->local_abspath,
+                                                install_from,
+                                                eb->use_commit_times,
+                                                record_fileinfo,
+                                                pool, pool));
+          all_work_items = svn_wc__wq_merge(all_work_items, work_item, pool);
+        }
     }
   else
     {
@@ -4587,23 +4574,10 @@ close_file(void *file_baton,
      properties merge. */
   if (! fb->adding_base_under_local_add)
     {
-      apr_hash_t *props;
-      apr_array_header_t *prop_diffs;
-
       SVN_ERR_ASSERT(new_actual_props != NULL);
 
-      /* If the ACTUAL props are the same as the BASE props, then we
-         should "write" a NULL. This will remove the props from the
-         ACTUAL_NODE row, and remove the old-style props file, indicating
-         "no change".  */
-      props = new_actual_props;
-      SVN_ERR(svn_prop_diffs(&prop_diffs, new_actual_props, new_base_props,
-                             pool));
-      if (prop_diffs->nelts == 0)
-        props = NULL;
-
       SVN_ERR(svn_wc__db_op_set_props(eb->db, fb->local_abspath,
-                                      props,
+                                      new_actual_props,
                                       NULL /* conflict */,
                                       NULL /* work_item */,
                                       pool));
@@ -5592,7 +5566,6 @@ svn_wc_add_repos_file4(svn_wc_context_t 
   const char *original_root_url;
   const char *original_repos_relpath;
   const char *original_uuid;
-  apr_hash_t *actual_props;
   svn_revnum_t changed_rev;
   apr_time_t changed_date;
   const char *changed_author;
@@ -5714,25 +5687,6 @@ svn_wc_add_repos_file4(svn_wc_context_t 
                                    entry_props, pool, pool));
   }
 
-  /* Add some work items to install the properties.  */
-  {
-    if (new_props == NULL)
-      {
-        actual_props = NULL;
-      }
-    else
-      {
-        apr_array_header_t *prop_diffs;
-
-        SVN_ERR(svn_prop_diffs(&prop_diffs, new_props, new_base_props,
-                               pool));
-        if (prop_diffs->nelts == 0)
-          actual_props = NULL;
-        else
-          actual_props = new_props;
-      }
-  }
-
   /* Copy NEW_BASE_CONTENTS into a temporary file so our log can refer to
      it, and set TMP_TEXT_BASE_ABSPATH to its path.  Compute its
      NEW_TEXT_BASE_MD5_CHECKSUM and NEW_TEXT_BASE_SHA1_CHECKSUM as we copy. */
@@ -5857,7 +5811,7 @@ svn_wc_add_repos_file4(svn_wc_context_t 
   /* ### if below fails, then the above db change would remain :-(  */
 
   SVN_ERR(svn_wc__db_op_set_props(db, local_abspath,
-                                  actual_props,
+                                  new_props,
                                   NULL /* conflict */,
                                   all_work_items,
                                   pool));

Modified: subversion/branches/performance/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/upgrade.c?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/upgrade.c Mon Oct 25 17:50:25 2010
@@ -1707,6 +1707,7 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
                                     scratch_pool);
   pristine_to = svn_wc__adm_child(local_abspath, PRISTINE_STORAGE_RELPATH,
                                   scratch_pool);
+  SVN_ERR(svn_wc__ensure_directory(pristine_from, scratch_pool));
   SVN_ERR(svn_wc__wq_build_file_move(&work_item, db,
                                      pristine_from, pristine_to,
                                      scratch_pool, scratch_pool));

Modified: subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql?rev=1027203&r1=1027202&r2=1027203&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql Mon Oct 25 17:50:25 2010
@@ -63,7 +63,7 @@ LEFT OUTER JOIN lock ON nodes.repos_id =
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
 
 -- STMT_SELECT_WORKING_NODE
-SELECT presence, kind, checksum, translated_size,
+SELECT op_depth, presence, kind, checksum, translated_size,
   changed_revision, changed_date, changed_author, depth, symlink_target,
   repos_id, repos_path, revision,
   moved_here, moved_to, last_mod_time, properties
@@ -78,6 +78,26 @@ conflict_working, tree_conflict_data, pr
 FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_SELECT_NODE_CHILDREN_INFO
+/* Getting rows in an advantageous order using
+     ORDER BY local_relpath, op_depth DESC
+   turns out to be slower than getting rows in a random order and making the
+   C code handle it. */
+SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision,
+  checksum, translated_size, changed_revision, changed_date, changed_author,
+  depth, symlink_target, last_mod_time, properties, lock_token, lock_owner,
+  lock_comment, lock_date, local_relpath
+FROM nodes
+LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
+  AND nodes.repos_path = lock.repos_relpath
+WHERE wc_id = ?1 AND parent_relpath = ?2;
+
+-- STMT_SELECT_ACTUAL_CHILDREN_INFO
+SELECT prop_reject, changelist, conflict_old, conflict_new,
+conflict_working, tree_conflict_data, properties, local_relpath
+FROM actual_node
+WHERE wc_id = ?1 AND parent_relpath = ?2;
+
 -- STMT_SELECT_REPOSITORY_BY_ID
 SELECT root, uuid FROM repository WHERE id = ?1;
 
@@ -313,10 +333,6 @@ WHERE wc_id = ?1 AND local_relpath = ?2
   AND op_depth = (SELECT MAX(op_depth) FROM nodes
                   WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0);
 
--- STMT_UPDATE_BASE_NODE_PRESENCE_AND_REVNUM
-UPDATE nodes SET presence = ?3, revision = ?4
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
-
 -- STMT_UPDATE_BASE_NODE_PRESENCE_REVNUM_AND_REPOS_PATH
 UPDATE nodes SET presence = ?3, revision = ?4, repos_path = ?5
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
@@ -464,11 +480,12 @@ WHERE wc_id = ?1 AND local_relpath = ?2;
   AND op_depth = (SELECT MAX(op_depth) FROM nodes
                   WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0);
 
--- STMT_SELECT_CHILDREN_OP_DEPTH_RECURSIVE
-SELECT local_relpath, op_depth FROM nodes as node
+-- STMT_SELECT_WORKING_OP_DEPTH_RECURSIVE
+SELECT local_relpath, op_depth, presence FROM nodes as node
 WHERE wc_id = ?1 AND local_relpath LIKE ?2 ESCAPE '#'
   AND op_depth = (SELECT MAX(op_depth) FROM nodes
-                  WHERE wc_id = node.wc_id
+                  WHERE op_depth > 0
+                    AND wc_id = node.wc_id
                     AND local_relpath = node.local_relpath);
 
 -- STMT_UPDATE_OP_DEPTH