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/12/08 22:53:41 UTC

svn commit: r1043705 [2/4] - in /subversion/branches/performance: ./ build/ build/ac-macros/ build/generator/templates/ contrib/hook-scripts/ contrib/server-side/ notes/api-errata/ notes/api-errata/1.7/ subversion/bindings/javahl/native/ subversion/bin...

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs.h?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs.h Wed Dec  8 21:53:38 2010
@@ -133,7 +133,6 @@ extern "C" {
    relate to a particular transaction in a filesystem (as identified
    by transaction id and filesystem UUID).  Objects of this type are
    allocated in their own subpool of the common pool. */
-struct fs_fs_shared_txn_data_t;
 typedef struct fs_fs_shared_txn_data_t
 {
   /* The next transaction in the list, or NULL if there is no following
@@ -172,7 +171,7 @@ typedef struct fs_fs_shared_txn_data_t
 /* Private FSFS-specific data shared between all svn_fs_t objects that
    relate to a particular filesystem, as identified by filesystem UUID.
    Objects of this type are allocated in the common pool. */
-typedef struct
+typedef struct fs_fs_shared_data_t
 {
   /* A list of shared transaction objects for each transaction that is
      currently active, or NULL if none are.  All access to this list,
@@ -204,7 +203,7 @@ typedef struct
 } fs_fs_shared_data_t;
 
 /* Private (non-shared) FSFS-specific data for each svn_fs_t object. */
-typedef struct
+typedef struct fs_fs_data_t
 {
   /* The format number of this FS. */
   int format;
@@ -284,7 +283,7 @@ typedef struct
 
 
 /*** Filesystem Transaction ***/
-typedef struct
+typedef struct transaction_t
 {
   /* property list (const char * name, svn_string_t * value).
      may be NULL if there are no properties.  */
@@ -307,7 +306,7 @@ typedef struct
 /*** Representation ***/
 /* If you add fields to this, check to see if you need to change
  * svn_fs_fs__rep_copy. */
-typedef struct
+typedef struct representation_t
 {
   /* Checksums for the contents produced by this representation.
      This checksum is for the contents the rep shows to consumers,
@@ -354,7 +353,7 @@ typedef struct
 /*** Node-Revision ***/
 /* If you add fields to this, check to see if you need to change
  * copy_node_revision in dag.c. */
-typedef struct
+typedef struct node_revision_t
 {
   /* node kind */
   svn_node_kind_t kind;
@@ -404,7 +403,7 @@ typedef struct
 
 
 /*** Change ***/
-typedef struct
+typedef struct change_t
 {
   /* Path of the change. */
   const char *path;

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c Wed Dec  8 21:53:38 2010
@@ -271,18 +271,17 @@ svn_fs_fs__path_rev_absolute(const char 
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
-  if (ffd->format < SVN_FS_FS__MIN_PACKED_FORMAT)
+  if (ffd->format < SVN_FS_FS__MIN_PACKED_FORMAT
+      || ! is_packed_rev(fs, rev))
     {
       *path = path_rev(fs, rev, pool);
-      return SVN_NO_ERROR;
     }
-
-  if (! is_packed_rev(fs, rev))
+  else
     {
       svn_node_kind_t kind;
 
       /* Initialize the return variable. */
-      *path = path_rev(fs, rev, pool);
+      *path = path_rev_packed(fs, rev, "pack", pool);
 
       /* quick check the path. For revs close to HEAD, this will often
        * be effective (and, hence, efficient). */
@@ -314,8 +313,6 @@ svn_fs_fs__path_rev_absolute(const char 
         }
     }
 
-  *path = path_rev_packed(fs, rev, "pack", pool);
-
   return SVN_NO_ERROR;
 }
 
@@ -1928,7 +1925,14 @@ ensure_revision_exists(svn_fs_t *fs,
    to the revision file for REV.  Return SVN_ERR_FS_NO_SUCH_REVISION if the
    file doesn't exist.  Move the file pointer of OFFSET, if the latter is
    not -1.  Prefer cached file handles that share the same COOKIE (again,
-   if not -1).  Use POOL for allocations. */
+   if not -1).
+
+   TODO: Consider returning an indication of whether this is a packed rev
+         file, so the caller need not rely on is_packed_rev() which in turn
+         relies on the cached FFD->min_unpacked_rev value not having changed
+         since the rev file was opened.
+
+   Use POOL for allocations. */
 static svn_error_t *
 open_pack_or_rev_file(svn_file_handle_cache__handle_t **file,
                       svn_fs_t *fs,
@@ -1937,10 +1941,10 @@ open_pack_or_rev_file(svn_file_handle_ca
                       int cookie,
                       apr_pool_t *pool)
 {
+  fs_fs_data_t *ffd = fs->fsap_data;
   svn_error_t *err;
   const char *path;
   svn_boolean_t retry = FALSE;
-  fs_fs_data_t *ffd = fs->fsap_data;
 
   do
     {
@@ -1964,7 +1968,8 @@ open_pack_or_rev_file(svn_file_handle_ca
           assert(err || svn_file_handle_cache__get_apr_handle(*file));
         }
 
-      if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+      if (err && APR_STATUS_IS_ENOENT(err->apr_err)
+      	  && ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
         {
           /* Could not open the file. This may happen if the
            * file once existed but got packed later. Note that
@@ -1987,10 +1992,10 @@ open_pack_or_rev_file(svn_file_handle_ca
         }
       else
         {
-          return svn_error_return(err);
+          retry = FALSE;
         }
     }
-  while (err);
+  while (retry);
 
   return SVN_NO_ERROR;
 }
@@ -2784,8 +2789,18 @@ get_fs_id_at_offset(svn_fs_id_t **id_p,
    specifies the offset to the root node-id and to the changed path
    information.  Store the root node offset in *ROOT_OFFSET and the
    changed path offset in *CHANGES_OFFSET.  If either of these
-   pointers is NULL, do nothing with it.  If PACKED is true, REV_FILE
-   should be a packed shard file.  Allocate temporary variables from POOL. */
+   pointers is NULL, do nothing with it.
+
+   If PACKED is true, REV_FILE should be a packed shard file.
+   ### There is currently no such parameter.  This function assumes that
+       is_packed_rev(FS, REV) will indicate whether REV_FILE is a packed
+       file.  Therefore FS->fsap_data->min_unpacked_rev must not have been
+       refreshed since REV_FILE was opened if there is a possibility that
+       revision REV may have become packed since then.
+       TODO: Take an IS_PACKED parameter instead, in order to remove this
+       requirement.
+
+   Allocate temporary variables from POOL. */
 static svn_error_t *
 get_root_changes_offset(apr_off_t *root_offset,
                         apr_off_t *changes_offset,
@@ -7331,11 +7346,10 @@ recover_body(void *baton, apr_pool_t *po
       if (ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
         {
           svn_revnum_t min_unpacked_revprop;
-          const char *min_unpacked_revprop_path =
-            svn_dirent_join(fs->path, PATH_MIN_UNPACKED_REVPROP, pool);
 
           SVN_ERR(read_min_unpacked_rev(&min_unpacked_revprop,
-                                        min_unpacked_revprop_path, pool));
+                                        path_min_unpacked_revprop(fs, pool),
+                                        pool));
           if (min_unpacked_revprop == (max_rev + 1))
             uhohs = FALSE;
         }
@@ -7882,6 +7896,31 @@ svn_fs_fs__begin_obliteration_txn(svn_fs
 
 
 /****** Packing FSFS shards *********/
+
+/* Write a file FILENAME in directory FS_PATH, containing a single line
+ * with the number REVNUM in ASCII decimal.  Move the file into place
+ * atomically, overwriting any existing file.
+ *
+ * Similar to write_current(). */
+static svn_error_t *
+write_revnum_file(const char *fs_path,
+                  const char *filename,
+                  svn_revnum_t revnum,
+                  apr_pool_t *scratch_pool)
+{
+  const char *final_path, *tmp_path;
+  svn_stream_t *tmp_stream;
+
+  final_path = svn_dirent_join(fs_path, filename, scratch_pool);
+  SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_path, fs_path,
+                                   svn_io_file_del_none,
+                                   scratch_pool, scratch_pool));
+  SVN_ERR(svn_stream_printf(tmp_stream, scratch_pool, "%ld\n", revnum));
+  SVN_ERR(svn_stream_close(tmp_stream));
+  SVN_ERR(move_into_place(tmp_path, final_path, final_path, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
 /* Pack a single shard SHARD in REVS_DIR, using POOL for allocations.
    CANCEL_FUNC and CANCEL_BATON are what you think they are.
 
@@ -7898,12 +7937,10 @@ pack_shard(const char *revs_dir,
            void *cancel_baton,
            apr_pool_t *pool)
 {
-  const char *tmp_path, *final_path;
   const char *pack_file_path, *manifest_file_path, *shard_path;
   const char *pack_file_dir;
   svn_stream_t *pack_stream, *manifest_stream;
   svn_revnum_t start_rev, end_rev, rev;
-  svn_stream_t *tmp_stream;
   apr_off_t next_offset;
   apr_pool_t *iterpool;
 
@@ -7914,8 +7951,8 @@ pack_shard(const char *revs_dir,
   pack_file_path = svn_dirent_join(pack_file_dir, "pack", pool);
   manifest_file_path = svn_dirent_join(pack_file_dir, "manifest", pool);
   shard_path = svn_dirent_join(revs_dir,
-                             apr_psprintf(pool, "%" APR_INT64_T_FMT, shard),
-                             pool);
+                               apr_psprintf(pool, "%" APR_INT64_T_FMT, shard),
+                               pool);
 
   /* Notify caller we're starting to pack this shard. */
   if (notify_func)
@@ -7971,15 +8008,11 @@ pack_shard(const char *revs_dir,
   SVN_ERR(svn_io_set_file_read_only(manifest_file_path, FALSE, pool));
 
   /* Update the min-unpacked-rev file to reflect our newly packed shard.
-   * (ffd->min_unpacked_rev will be updated by open_pack_or_rev_file().)
-   */
-  final_path = svn_dirent_join(fs_path, PATH_MIN_UNPACKED_REV, iterpool);
-  SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_path, fs_path,
-                                   svn_io_file_del_none, iterpool, iterpool));
-  SVN_ERR(svn_stream_printf(tmp_stream, iterpool, "%ld\n",
-                            (svn_revnum_t) ((shard + 1) * max_files_per_dir)));
-  SVN_ERR(svn_stream_close(tmp_stream));
-  SVN_ERR(move_into_place(tmp_path, final_path, final_path, iterpool));
+   * (This doesn't update ffd->min_unpacked_rev.  That will be updated by
+   * update_min_unpacked_rev() when necessary.) */
+  SVN_ERR(write_revnum_file(fs_path, PATH_MIN_UNPACKED_REV,
+                            (svn_revnum_t)((shard + 1) * max_files_per_dir),
+                            iterpool));
   svn_pool_destroy(iterpool);
 
   /* Finally, remove the existing shard directory. */
@@ -8007,10 +8040,9 @@ pack_revprop_shard(svn_fs_t *fs,
                    apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  const char *shard_path, *final_path, *tmp_path;
+  const char *shard_path;
   svn_revnum_t start_rev, end_rev, rev;
   svn_sqlite__stmt_t *stmt;
-  svn_stream_t *tmp_stream;
   apr_pool_t *iterpool;
 
   shard_path = svn_dirent_join(revprops_dir,
@@ -8039,16 +8071,11 @@ pack_revprop_shard(svn_fs_t *fs,
       SVN_ERR(svn_sqlite__insert(NULL, stmt));
     }
 
-  /* Update the min-unpacked-rev file to reflect our newly packed shard.
-   * (ffd->min_unpacked_rev will be updated by open_pack_or_rev_file().)
-   */
-  final_path = svn_dirent_join(fs_path, PATH_MIN_UNPACKED_REVPROP, iterpool);
-  SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_path, fs_path,
-                                 svn_io_file_del_none, iterpool, iterpool));
-  SVN_ERR(svn_stream_printf(tmp_stream, iterpool, "%ld\n",
-                            (svn_revnum_t) ((shard + 1) * max_files_per_dir)));
-  SVN_ERR(svn_stream_close(tmp_stream));
-  SVN_ERR(move_into_place(tmp_path, final_path, final_path, iterpool));
+  /* Update the min-unpacked-revprop file to reflect our newly packed shard.
+   * (This doesn't update ffd->min_unpacked_revprop.) */
+  SVN_ERR(write_revnum_file(fs_path, PATH_MIN_UNPACKED_REVPROP,
+                            (svn_revnum_t)((shard + 1) * max_files_per_dir),
+                            iterpool));
   svn_pool_destroy(iterpool);
 
   /* Finally, remove the existing shard directory. */
@@ -8086,31 +8113,28 @@ pack_body(void *baton,
   svn_revnum_t min_unpacked_rev;
   svn_revnum_t min_unpacked_revprop;
 
-  SVN_ERR(read_format(&format, &max_files_per_dir,
-                      svn_dirent_join(pb->fs->path, PATH_FORMAT, pool),
+  SVN_ERR(read_format(&format, &max_files_per_dir, path_format(pb->fs, pool),
                       pool));
 
   /* If the repository isn't a new enough format, we don't support packing.
      Return a friendly error to that effect. */
   if (format < SVN_FS_FS__MIN_PACKED_FORMAT)
-    return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
-      _("FS format too old to pack, please upgrade."));
+    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+      _("FSFS format (%d) too old to pack, please upgrade."),
+      format);
 
   /* If we aren't using sharding, we can't do any packing, so quit. */
   if (!max_files_per_dir)
     return SVN_NO_ERROR;
 
   SVN_ERR(read_min_unpacked_rev(&min_unpacked_rev,
-                                svn_dirent_join(pb->fs->path,
-                                                PATH_MIN_UNPACKED_REV, pool),
+                                path_min_unpacked_rev(pb->fs, pool),
                                 pool));
 
   if (format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
     {
       SVN_ERR(read_min_unpacked_rev(&min_unpacked_revprop,
-                                    svn_dirent_join(pb->fs->path,
-                                                    PATH_MIN_UNPACKED_REVPROP,
-                                                    pool),
+                                    path_min_unpacked_revprop(pb->fs, pool),
                                     pool));
     }
   else

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.h?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.h Wed Dec  8 21:53:38 2010
@@ -405,8 +405,14 @@ svn_error_t *svn_fs_fs__move_into_place(
                                         const char *perms_reference,
                                         apr_pool_t *pool);
 
-/* Sets *PATH to the path of REV in FS, whether in a pack file or not.
-   Allocate in POOL. */
+/* Set *PATH to the path of REV in FS, whether in a pack file or not.
+   Allocate *PATH in POOL.
+
+   Note: If the caller does not have the write lock on FS, then the path is
+   not guaranteed to be correct or to remain correct after the function
+   returns, because the revision might become packed before or after this
+   call.  If a file exists at that path, then it is correct; if not, then
+   the caller should call update_min_unpacked_rev() and re-try once. */
 svn_error_t *
 svn_fs_fs__path_rev_absolute(const char **path,
                              svn_fs_t *fs,

Propchange: subversion/branches/performance/subversion/libsvn_fs_fs/temp_serializer.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Dec  8 21:53:38 2010
@@ -1 +1 @@
-/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c:962911-1027198
+/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c:962911-1027198,1039498-1043512

Propchange: subversion/branches/performance/subversion/libsvn_fs_fs/temp_serializer.h
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Dec  8 21:53:38 2010
@@ -34,4 +34,4 @@
 /subversion/branches/tc_url_rev/subversion/libsvn_fs_fs/fs_fs.h:874351-874483
 /subversion/branches/tree-conflicts/subversion/libsvn_fs_fs/fs_fs.h:868291-873154
 /subversion/branches/tree-conflicts-notify/subversion/libsvn_fs_fs/fs_fs.h:873926-874008
-/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h:962911-1027198
+/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h:962911-1027198,1039498-1043512

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/tree.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/tree.c Wed Dec  8 21:53:38 2010
@@ -802,8 +802,8 @@ make_path_mutable(svn_fs_root_t *root,
 
 
 /* Open the node identified by PATH in ROOT.  Set DAG_NODE_P to the
- *node we find, allocated in POOL.  Return the error
- *SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */
+   node we find, allocated in POOL.  Return the error
+   SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */
 static svn_error_t *
 get_dag(dag_node_t **dag_node_p,
         svn_fs_root_t *root,
@@ -1134,7 +1134,7 @@ fs_props_changed(svn_boolean_t *changed_
 
 /* Merges and commits. */
 
-/* Set ARGS->node to the root node of ARGS->root.  */
+/* Set *NODE to the root node of ROOT.  */
 static svn_error_t *
 get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool)
 {
@@ -1556,13 +1556,16 @@ merge(svn_stringbuf_t *conflict_p,
   return SVN_NO_ERROR;
 }
 
-/* Merge changes between an ancestor and BATON->source_node into
-   BATON->txn.  The ancestor is either BATON->ancestor_node, or if
-   that is null, BATON->txn's base node.
-
-   If the merge is successful, BATON->txn's base will become
-   BATON->source_node, and its root node will have a new ID, a
-   successor of BATON->source_node. */
+/* Merge changes between an ancestor and SOURCE_NODE into
+   TXN.  The ancestor is either ANCESTOR_NODE, or if
+   that is null, TXN's base node.
+
+   If the merge is successful, TXN's base will become
+   SOURCE_NODE, and its root node will have a new ID, a
+   successor of SOURCE_NODE.
+
+   If a conflict results, update *CONFLICT to the path in the txn that
+   conflicted; see the CONFLICT_P parameter of merge() for details. */
 static svn_error_t *
 merge_changes(dag_node_t *ancestor_node,
               dag_node_t *source_node,
@@ -1586,13 +1589,8 @@ merge_changes(dag_node_t *ancestor_node,
                        svn_fs_fs__dag_get_id(txn_root_node)))
     {
       /* If no changes have been made in TXN since its current base,
-         then it can't conflict with any changes since that base.  So
-         we just set *both* its base and root to source, making TXN
-         in effect a repeat of source. */
-
-      /* ### kff todo: this would, of course, be a mighty silly thing
-         for the caller to do, and we might want to consider whether
-         this response is really appropriate. */
+         then it can't conflict with any changes since that base.
+         The caller isn't supposed to call us in that case. */
       SVN_ERR_MALFUNCTION();
     }
   else

Propchange: subversion/branches/performance/subversion/libsvn_fs_util/caching.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Dec  8 21:53:38 2010
@@ -34,4 +34,4 @@
 /subversion/branches/tc_url_rev/subversion/libsvn_fs/caching.c:874351-874483
 /subversion/branches/tree-conflicts/subversion/libsvn_fs/caching.c:868291-873154
 /subversion/branches/tree-conflicts-notify/subversion/libsvn_fs/caching.c:873926-874008
-/subversion/trunk/subversion/libsvn_fs_util/caching.c:962911-1027198
+/subversion/trunk/subversion/libsvn_fs_util/caching.c:962911-1027198,1039498-1043512

Modified: subversion/branches/performance/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/load-fs-vtable.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/load-fs-vtable.c Wed Dec  8 21:53:38 2010
@@ -725,12 +725,10 @@ apply_textdelta(svn_txdelta_window_handl
 
   return svn_fs_apply_textdelta(handler, handler_baton,
                                 rb->txn_root, nb->path,
-                                nb->base_checksum ?
                                 svn_checksum_to_cstring(nb->base_checksum,
-                                                        nb->pool) : NULL,
-                                nb->result_checksum ?
+                                                        nb->pool),
                                 svn_checksum_to_cstring(nb->result_checksum,
-                                                        nb->pool) : NULL,
+                                                        nb->pool),
                                 nb->pool);
 }
 
@@ -744,9 +742,8 @@ set_fulltext(svn_stream_t **stream,
 
   return svn_fs_apply_text(stream,
                            rb->txn_root, nb->path,
-                           nb->result_checksum ?
                            svn_checksum_to_cstring(nb->result_checksum,
-                                                   nb->pool) : NULL,
+                                                   nb->pool),
                            nb->pool);
 }
 

Modified: subversion/branches/performance/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/repos.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/repos.c Wed Dec  8 21:53:38 2010
@@ -545,6 +545,7 @@ PREWRITTEN_HOOKS_TEXT
   }  /* end pre-revprop-change hook */
 
 
+#ifdef SVN_WITH_EXPERIMENTAL_OBLITERATE
   /* Pre-obliterate hook. */
   {
     this_path = apr_psprintf(pool, "%s%s",
@@ -617,6 +618,7 @@ PREWRITTEN_HOOKS_TEXT
     SVN_ERR_W(svn_io_file_create(this_path, contents, pool),
               _("Creating pre-obliterate hook"));
   }  /* end pre-obliterate hook */
+#endif
 
 
   /* Pre-lock hook. */
@@ -672,6 +674,8 @@ PREWRITTEN_HOOKS_TEXT
 "REPOS=\"$1\""                                                               NL
 "PATH=\"$2\""                                                                NL
 "USER=\"$3\""                                                                NL
+"COMMENT=\"$4\""                                                             NL
+"STEAL=\"$5\""                                                               NL
 ""                                                                           NL
 "# If a lock exists and is owned by a different person, don't allow it"      NL
 "# to be stolen (e.g., with 'svn lock --force ...')."                        NL
@@ -755,6 +759,8 @@ PREWRITTEN_HOOKS_TEXT
 "REPOS=\"$1\""                                                               NL
 "PATH=\"$2\""                                                                NL
 "USER=\"$3\""                                                                NL
+"TOKEN=\"$4\""                                                               NL
+"BREAK=\"$5\""                                                               NL
 ""                                                                           NL
 "# If a lock is owned by a different person, don't allow it be broken."      NL
 "# (Maybe this script could send email to the lock owner?)"                  NL
@@ -1032,6 +1038,7 @@ PREWRITTEN_HOOKS_TEXT
               _("Creating post-revprop-change hook"));
   } /* end post-revprop-change hook */
 
+#ifdef SVN_WITH_EXPERIMENTAL_OBLITERATE
   /* Post-obliterate hook. */
   {
     this_path = apr_psprintf(pool, "%s%s",
@@ -1089,6 +1096,7 @@ PREWRITTEN_HOOKS_TEXT
     SVN_ERR_W(svn_io_file_create(this_path, contents, pool),
               _("Creating post-obliterate hook"));
   } /* end post-obliterate hook */
+#endif
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/performance/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_repos/rev_hunt.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/performance/subversion/libsvn_repos/rev_hunt.c Wed Dec  8 21:53:38 2010
@@ -1095,8 +1095,8 @@ find_interesting_revisions(apr_array_hea
 
   /* We switch between two pools while looping, since we need information from
      the last iteration to be available. */
-  iterpool = svn_pool_create(result_pool);
-  last_pool = svn_pool_create(result_pool);
+  iterpool = svn_pool_create(scratch_pool);
+  last_pool = svn_pool_create(scratch_pool);
 
   /* The path had better be a file in this revision. */
   SVN_ERR(svn_fs_revision_root(&root, repos->fs, end, scratch_pool));
@@ -1175,6 +1175,7 @@ find_interesting_revisions(apr_array_hea
     }
 
   svn_pool_destroy(iterpool);
+  svn_pool_destroy(last_pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/performance/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/checksum.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/checksum.c Wed Dec  8 21:53:38 2010
@@ -135,6 +135,9 @@ const char *
 svn_checksum_to_cstring(const svn_checksum_t *checksum,
                         apr_pool_t *pool)
 {
+  if (checksum == NULL)
+    return NULL;
+
   switch (checksum->kind)
     {
       case svn_checksum_md5:
@@ -190,9 +193,28 @@ svn_checksum_parse_hex(svn_checksum_t **
                        const char *hex,
                        apr_pool_t *pool)
 {
-  int len;
-  int i;
-  unsigned char is_zeros = '\0';
+  int i, len;
+  char is_nonzero = '\0';
+  char *digest;
+  static const char xdigitval[256] =
+    {
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+       0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,   /* 0-9 */
+      -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,   /* A-F */
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,   /* a-f */
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    };
 
   if (hex == NULL)
     {
@@ -203,23 +225,21 @@ svn_checksum_parse_hex(svn_checksum_t **
   SVN_ERR(validate_kind(kind));
 
   *checksum = svn_checksum_create(kind, pool);
+  digest = (char *)(*checksum)->digest;
   len = DIGESTSIZE(kind);
 
   for (i = 0; i < len; i++)
     {
-      if ((! svn_ctype_isxdigit(hex[i * 2])) ||
-          (! svn_ctype_isxdigit(hex[i * 2 + 1])))
+      char x1 = xdigitval[(unsigned char)hex[i * 2]];
+      char x2 = xdigitval[(unsigned char)hex[i * 2 + 1]];
+      if (x1 == (char)-1 || x2 == (char)-1)
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL);
 
-      ((unsigned char *)(*checksum)->digest)[i] =
-        ((svn_ctype_isalpha(hex[i*2]) ? hex[i*2] - 'a' + 10
-                                      : hex[i*2] - '0') << 4) |
-        (svn_ctype_isalpha(hex[i*2+1]) ? hex[i*2+1] - 'a' + 10
-                                       : hex[i*2+1] - '0');
-      is_zeros |= (*checksum)->digest[i];
+      digest[i] = (x1 << 4) | x2;
+      is_nonzero |= (x1 << 4) | x2;
     }
 
-  if (is_zeros == '\0')
+  if (!is_nonzero)
     *checksum = NULL;
 
   return SVN_NO_ERROR;

Modified: subversion/branches/performance/subversion/libsvn_subr/eol.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/eol.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/eol.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/eol.c Wed Dec  8 21:53:38 2010
@@ -84,7 +84,7 @@ svn_eol__detect_file_eol(const char **eo
       err = svn_io_file_read(file, buf, &nbytes, pool);
       if (err)
         {
-          /* An error occured. We're going to return in any case,
+          /* An error occurred. We're going to return in any case,
            * so reset the file cursor right now. */
           pos = orig_pos;
           SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, pool));

Propchange: subversion/branches/performance/subversion/libsvn_subr/svn_file_handle_cache.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Dec  8 21:53:38 2010
@@ -1 +1 @@
-/subversion/trunk/subversion/libsvn_subr/svn_file_handle_cache.c:962911-1027198
+/subversion/trunk/subversion/libsvn_subr/svn_file_handle_cache.c:962911-1027198,1039498-1043512

Propchange: subversion/branches/performance/subversion/libsvn_subr/svn_temp_serializer.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Dec  8 21:53:38 2010
@@ -1 +1 @@
-/subversion/trunk/subversion/libsvn_subr/svn_temp_serializer.c:962911-1027198
+/subversion/trunk/subversion/libsvn_subr/svn_temp_serializer.c:962911-1027198,1039498-1043512

Modified: subversion/branches/performance/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/entries.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/entries.c Wed Dec  8 21:53:38 2010
@@ -309,165 +309,6 @@ get_base_info_for_deleted(svn_wc_entry_t
         entry->revision = parent_entry->revision;
     }
 
-  /* For deleted nodes, our COPIED flag has a rather complex meaning.
-
-     In general, COPIED means "an operation on an ancestor took care
-     of me." This typically refers to a copy of an ancestor (and
-     this node just came along for the ride). However, in certain
-     situations the COPIED flag is set for deleted nodes.
-
-     First off, COPIED will *never* be set for nodes/subtrees that
-     are simply deleted. The deleted node/subtree *must* be under
-     an ancestor that has been copied. Plain additions do not count;
-     only copies (add-with-history).
-
-     The basic algorithm to determine whether we live within a
-     copied subtree is as follows:
-
-     1) find the root of the deletion operation that affected us
-     (we may be that root, or an ancestor was deleted and took
-     us with it)
-
-     2) look at the root's *parent* and determine whether that was
-     a copy or a simple add.
-
-     It would appear that we would be done at this point. Once we
-     determine that the parent was copied, then we could just set
-     the COPIED flag.
-
-     Not so fast. Back to the general concept of "an ancestor
-     operation took care of me." Further consider two possibilities:
-
-     1) this node is scheduled for deletion from the copied subtree,
-     so at commit time, we copy then delete
-
-     2) this node is scheduled for deletion because a subtree was
-     deleted and then a copied subtree was added (causing a
-     replacement). at commit time, we delete a subtree, and then
-     copy a subtree. we do not need to specifically touch this
-     node -- all operations occur on ancestors.
-
-     Given the "ancestor operation" concept, then in case (1) we
-     must *clear* the COPIED flag since we'll have more work to do.
-     In case (2), we *set* the COPIED flag to indicate that no
-     real work is going to happen on this node.
-
-     Great fun. And just maybe the code reading the entries has no
-     bugs in interpreting that gobbledygook... but that *is* the
-     expectation of the code. Sigh.
-
-     We can get a little bit of shortcut here if THIS_DIR is
-     also schduled for deletion.
-  */
-  if (parent_entry != NULL
-      && parent_entry->schedule == svn_wc_schedule_delete)
-    {
-      /* ### not entirely sure that we can rely on the parent. for
-         ### example, what if we are a deletion of a BASE node, but
-         ### the parent is a deletion of a copied subtree? sigh.  */
-
-      /* Child nodes simply inherit the parent's COPIED flag.  */
-      entry->copied = parent_entry->copied;
-    }
-  else
-    {
-      svn_boolean_t base_replaced;
-      const char *work_del_abspath;
-
-      /* Find out details of our deletion.  */
-      SVN_ERR(svn_wc__db_scan_deletion(NULL,
-                                       &base_replaced,
-                                       NULL,
-                                       &work_del_abspath,
-                                       db, entry_abspath,
-                                       scratch_pool, scratch_pool));
-
-      /* If there is no deletion in the WORKING tree, then the
-         node is a child of a simple explicit deletion of the
-         BASE tree. It certainly isn't copied. If we *do* find
-         a deletion in the WORKING tree, then we need to discover
-         information about the parent.  */
-      if (work_del_abspath != NULL)
-        {
-          const char *parent_abspath;
-          svn_wc__db_status_t parent_status;
-
-          /* The parent is in WORKING except during post-commit when
-             it may have been moved from the WORKING tree to the BASE
-             tree.  */
-          parent_abspath = svn_dirent_dirname(work_del_abspath,
-                                              scratch_pool);
-          SVN_ERR(svn_wc__db_read_info(&parent_status,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       db, parent_abspath,
-                                       scratch_pool, scratch_pool));
-          if (parent_status == svn_wc__db_status_added)
-            SVN_ERR(svn_wc__db_scan_addition(&parent_status,
-                                             NULL,
-                                             NULL, NULL, NULL,
-                                             NULL, NULL, NULL, NULL,
-                                             db,
-                                             parent_abspath,
-                                             scratch_pool, scratch_pool));
-          if (parent_status == svn_wc__db_status_copied
-              || parent_status == svn_wc__db_status_moved_here
-              || parent_status == svn_wc__db_status_normal)
-            {
-              /* The parent is copied/moved here, so WORK_DEL_ABSPATH
-                 is the root of a deleted subtree. Our COPIED status
-                 is now dependent upon whether the copied root is
-                 replacing a BASE tree or not.
-
-                 But: if we are schedule-delete as a result of being
-                 a copied DELETED node, then *always* mark COPIED.
-                 Normal copies have cmt_* data; copied DELETED nodes
-                 are missing this info.
-
-                 Note: MOVED_HERE is a concept foreign to this old
-                 interface, but it is best represented as if a copy
-                 had occurred, so we'll model it that way to old
-                 clients.
-
-                 Note: svn_wc__db_status_normal corresponds to the
-                 post-commit parent that was copied or moved in
-                 WORKING but has now been converted to BASE.
-              */
-              if (SVN_IS_VALID_REVNUM(entry->cmt_rev))
-                {
-                  /* The scan_deletion call will tell us if there
-                     was an explicit move-away of an ancestor (which
-                     also means a replacement has occurred since
-                     there is a WORKING tree that isn't simply
-                     BASE deletions). The call will also tell us if
-                     there was an implicit deletion caused by a
-                     replacement. All stored in BASE_REPLACED.  */
-                  entry->copied = base_replaced;
-                }
-              else
-                {
-                  entry->copied = TRUE;
-                }
-            }
-          else
-            {
-              SVN_ERR_ASSERT(parent_status == svn_wc__db_status_added);
-
-              /* Whoops. WORK_DEL_ABSPATH is scheduled for deletion,
-                 yet the parent is scheduled for a plain addition.
-                 This can occur when a subtree is deleted, and then
-                 nodes are added *later*. Since the parent is a simple
-                 add, then nothing has been copied. Nothing more to do.
-
-                 Note: if a subtree is added, *then* deletions are
-                 made, the nodes should simply be removed from
-                 version control.  */
-            }
-        }
-    }
-
   return SVN_NO_ERROR;
 }
 
@@ -688,9 +529,18 @@ read_one_entry(const svn_wc_entry_t **ne
   else if (status == svn_wc__db_status_deleted)
     {
       svn_node_kind_t path_kind;
+      const char *work_del_abspath;
+
       /* ### we don't have to worry about moves, so this is a delete. */
       entry->schedule = svn_wc_schedule_delete;
 
+      SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, NULL,
+                                       &work_del_abspath,
+                                       db, entry_abspath,
+                                       scratch_pool, scratch_pool));
+      if (work_del_abspath)
+        entry->copied = TRUE;
+
       /* If there is still a directory on-disk we keep it, if not it is
          already deleted. Simple, isn't it? 
          

Modified: subversion/branches/performance/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/node.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/node.c Wed Dec  8 21:53:38 2010
@@ -1273,11 +1273,7 @@ svn_wc__internal_node_get_schedule(svn_w
           if (!work_del_abspath)
             break; /* Base deletion */
 
-          /* We miss the 4th tree to properly find out if this is
-             the root of a working-delete. Only in that case
-             should copied be set to true. See entries.c for details. */
-
-          *copied = FALSE; /* Until we can fix this test */
+          *copied = TRUE;
           break;
         }
       case svn_wc__db_status_added:
@@ -1472,3 +1468,29 @@ svn_wc__node_get_info_bits(apr_time_t *t
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_wc__get_mergeinfo_walk_info(svn_boolean_t *is_present,
+                                svn_boolean_t *is_deleted,
+                                svn_boolean_t *is_absent,
+                                svn_depth_t *depth,
+                                svn_wc_context_t *wc_ctx,
+                                const char *local_abspath,
+                                apr_pool_t *scratch_pool)
+{
+  svn_wc__db_status_t status;
+
+  SVN_ERR(svn_wc__db_read_info(&status,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, depth, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL,
+                               wc_ctx->db, local_abspath,
+                               scratch_pool, scratch_pool));
+
+  *is_present = (status != svn_wc__db_status_not_present);
+  *is_deleted = (status == svn_wc__db_status_deleted);
+  *is_absent = (status == svn_wc__db_status_absent);
+
+  return SVN_NO_ERROR;
+}

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=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/update_editor.c Wed Dec  8 21:53:38 2010
@@ -3460,8 +3460,7 @@ apply_textdelta(void *file_baton,
                                                 fb->edit_baton->db,
                                                 fb->local_abspath,
                                                 pool, pool));
-    recorded_base_checksum
-      = checksum ? svn_checksum_to_cstring(checksum, pool) : NULL;
+    recorded_base_checksum = svn_checksum_to_cstring(checksum, pool);
     if (recorded_base_checksum && expected_base_checksum
         && strcmp(expected_base_checksum, recorded_base_checksum) != 0)
       return svn_error_createf(SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,

Modified: subversion/branches/performance/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/upgrade.c?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/upgrade.c Wed Dec  8 21:53:38 2010
@@ -1134,6 +1134,13 @@ bump_to_21(void *baton, svn_sqlite__db_t
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+bump_to_22(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_22));
+  return SVN_NO_ERROR;
+}
+
 
 struct upgrade_data_t {
   svn_sqlite__db_t *sdb;
@@ -1424,6 +1431,12 @@ svn_wc__upgrade_sdb(int *result_format,
         *result_format = 21;
         /* FALLTHROUGH  */
 
+      case 21:
+        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_22, &bb,
+                                             scratch_pool));
+        *result_format = 22;
+        /* FALLTHROUGH  */
+
       /* ### future bumps go here.  */
 #if 0
       case XXX-1:

Modified: subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql Wed Dec  8 21:53:38 2010
@@ -86,23 +86,22 @@ CREATE TABLE PRISTINE (
      pristine texts referenced from this database. */
   checksum  TEXT NOT NULL PRIMARY KEY,
 
-  /* ### enumerated values specifying type of compression. NULL implies
-     ### that no compression has been applied. */
+  /* Enumerated values specifying type of compression. The only value
+     supported so far is NULL, meaning that no compression has been applied
+     and the pristine text is stored verbatim in the file. */
   compression  INTEGER,
 
-  /* The size in bytes of the file in which the pristine text is stored. */
-  /* ### used to verify the pristine file is "proper". NULL if unknown,
-     ### and (thus) the pristine copy is incomplete/unusable. */
-  size  INTEGER,
+  /* The size in bytes of the file in which the pristine text is stored.
+     Used to verify the pristine file is "proper". */
+  size  INTEGER NOT NULL,
 
   /* ### this will probably go away, in favor of counting references
-     ### that exist in NODES. */
+     ### that exist in NODES. Not yet used; always set to 1. */
   refcount  INTEGER NOT NULL,
 
   /* Alternative MD5 checksum used for communicating with older
-     repositories. Not guaranteed to be unique among table rows.
-     NULL if not (yet) calculated. */
-  md5_checksum  TEXT
+     repositories. Not strictly guaranteed to be unique among table rows. */
+  md5_checksum  TEXT NOT NULL
   );
 
 
@@ -326,42 +325,58 @@ CREATE TABLE NODES (
 
   /* WC state fields */
 
-  /* Is this node "present" or has it been excluded for some reason?
+  /* The tree state of the node.
 
-     In case 'op_depth' is equal to 0, this is part of the BASE tree; in
-     that case, all presence values except 'base-deleted' are allowed.
+     ### This applies to SVN_WC__OP_DEPTH, the intended final code!
 
-     In case 'op_depth' is greater than 0, this is part of a layer of
-     working nodes; in that case, the following presence values apply:
+     In case 'op_depth' is equal to 0, this node is part of the 'BASE'
+     tree.  The 'BASE' represents pristine nodes that are in the
+     repository; it is obtained and modified by commands such as
+     checkout/update/switch.
+
+     In case 'op_depth' is greater than 0, this node is part of a
+     layer of working nodes.  The 'WORKING' tree is obtained and
+     modified by commands like delete/copy/revert.
+
+     The 'BASE' and 'WORKING' trees use the same literal values for
+     the 'presence' but the meaning of each value can vary depending
+     on the tree.
+
+     normal: in the 'BASE' tree this is an ordinary node for which we
+       have full information.  In the 'WORKING' tree it's an added or
+       copied node for which we have full information.
+
+     not-present: in the 'BASE' tree this is a node that is implied to
+       exist by the parent node, but is not present in the working
+       copy.  Typically obtained by delete/commit, or by update to
+       revision in which the node does not exist.  In the 'WORKING'
+       tree this is a copy of a 'not-present' node from the 'BASE'
+       tree, and it will be deleted on commit.  Such a node cannot be
+       copied directly, but can be copied as a descendant.
+
+     incomplete: in the 'BASE' tree this is an ordinary node for which
+       we do not have full information.  Only the name is guaranteed;
+       we may not have all its children, we may not have its checksum,
+       etc.  In the 'WORKING' tree this is a copied node for which we
+       do not have the full information.  This state is generally
+       obtained when an operation was interrupted.
+
+     base-deleted: not valid in 'BASE' tree.  In the 'WORKING' tree
+       this represents a node that is deleted from the tree below the
+       current 'op_depth'.  This state is badly named, it should be
+       something like 'deleted'.
+
+     absent: in the 'BASE' tree this is a node that is excluded by
+       authz.  The name of the node is known from the parent, but no
+       other information is available.  Not valid in the 'WORKING'
+       tree as there is no way to commit such a node.
+
+     excluded: in the 'BASE' tree this node is administratively
+       excluded by the user (sparse WC).  In the 'WORKING' tree this
+       is a copy of an excluded node from the 'BASE' tree.  Such a
+       node cannot be copied directly but can be copied as a
+       descendant. */
 
-     Only allowed values: normal, not-present, incomplete, base-deleted,
-     excluded.  (the others do not make sense for the WORKING tree)
-
-     normal: this node has been added/copied/moved-here. There may be an
-       underlying BASE node at this location, implying this is a replace.
-       Scan upwards from here looking for copyfrom or moved_here values
-       to detect the type of operation constructing this node.
-
-     not-present: the node (or parent) was originally copied or moved-here.
-       A subtree of that source has since been deleted. There may be
-       underlying BASE node to replace. For a move-here or copy-here, the
-       records are simply removed rather than switched to not-present.
-       Note this reflects a deletion only. It is not possible move-away
-       nodes from the WORKING tree. The purported destination would receive
-       a copy from the original source of a copy-here/move-here, or if the
-       nodes were plain adds, those nodes would be shifted to that target
-       for addition.
-
-     incomplete: nodes are being added into the WORKING tree, and the full
-       information about this node is not (yet) present.
-
-     base-deleted: the underlying BASE node has been marked for deletion due
-       to a delete or a move-away (see the moved_to column to determine
-       which), and has not been replaced.
-
-     excluded: this node is administratively excluded (sparse WC). This must
-       be a child (or grandchild etc.) of a copied directory.
-  */
   presence  TEXT NOT NULL,
 
   /* ### JF: For an old-style move, "copyfrom" info stores its source, but a
@@ -638,6 +653,18 @@ PRAGMA user_version = 21;
 
 /* ------------------------------------------------------------------------- */
 
+/* Format 22 simply moves the tree conflict information from the conflict_data
+   column to the tree_conflict_data column. */
+
+-- STMT_UPGRADE_TO_22
+UPDATE actual_node SET tree_conflict_data = conflict_data;
+UPDATE actual_node SET conflict_data = NULL;
+
+PRAGMA user_version = 22;
+
+
+/* ------------------------------------------------------------------------- */
+
 /* Format YYY introduces new handling for conflict information.  */
 -- format: YYY
 
@@ -695,3 +722,9 @@ INSERT INTO ACTUAL_NODE SELECT
 FROM ACTUAL_NODE_BACKUP;
 
 DROP TABLE ACTUAL_NODE_BACKUP;
+
+/* Note: One difference remains between the schemas of an upgraded and a
+ * fresh WC.  While format 22 was current, "NOT NULL" was added to the
+ * columns PRISTINE.size and PRISTINE.md5_checksum.  The format was not
+ * bumped because it is a forward- and backward-compatible change. */
+

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=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql Wed Dec  8 21:53:38 2010
@@ -81,14 +81,14 @@ LIMIT 1;
 
 -- STMT_SELECT_ACTUAL_NODE
 SELECT prop_reject, changelist, conflict_old, conflict_new,
-conflict_working, tree_conflict_data, properties, conflict_data
+conflict_working, tree_conflict_data, properties
 FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
 -- STMT_SELECT_ACTUAL_TREE_CONFLICT
-SELECT conflict_data
+SELECT tree_conflict_data
 FROM actual_node
-WHERE wc_id = ?1 AND local_relpath = ?2 AND conflict_data IS NOT NULL;
+WHERE wc_id = ?1 AND local_relpath = ?2 AND tree_conflict_data IS NOT NULL;
 
 -- STMT_SELECT_NODE_CHILDREN_INFO
 /* Getting rows in an advantageous order using
@@ -191,7 +191,8 @@ SELECT dav_cache FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
 
 -- STMT_SELECT_DELETION_INFO
-SELECT nodes_base.presence, nodes_work.presence, nodes_work.moved_to
+SELECT nodes_base.presence, nodes_work.presence, nodes_work.moved_to,
+       nodes_work.op_depth
 FROM nodes nodes_work
 LEFT OUTER JOIN nodes nodes_base ON nodes_base.wc_id = nodes_work.wc_id
   AND nodes_base.local_relpath = nodes_work.local_relpath
@@ -233,15 +234,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_ACTUAL_CONFLICT_DATA
-UPDATE actual_node SET conflict_data = ?3
-WHERE wc_id = ?1 AND local_relpath = ?2;
-
--- STMT_INSERT_ACTUAL_CONFLICT_DATA
-INSERT INTO actual_node (
-  wc_id, local_relpath, conflict_data, parent_relpath)
-VALUES (?1, ?2, ?3, ?4);
-
 -- STMT_UPDATE_ACTUAL_TREE_CONFLICTS
 UPDATE actual_node SET tree_conflict_data = ?3
 WHERE wc_id = ?1 AND local_relpath = ?2;
@@ -336,18 +328,17 @@ WHERE wc_id = ?1 AND local_relpath = ?2
 -- STMT_DELETE_ACTUAL_NODE_WITHOUT_CONFLICT
 DELETE FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2
-      AND conflict_data IS NULL;
+      AND tree_conflict_data IS NULL;
 
--- STMT_DELETE_NOT_PRESENT_NODES_RECURSIVE
+-- STMT_DELETE_CHILD_NODES_RECURSIVE
 DELETE FROM nodes
 WHERE wc_id = ?1 AND local_relpath LIKE ?2 ESCAPE '#' AND op_depth = ?3
-  AND presence = 'not-present';
+  AND presence = ?4
 
 -- STMT_CLEAR_ACTUAL_NODE_LEAVING_CHANGELIST
 UPDATE actual_node
 SET properties = NULL,
     text_mod = NULL,
-    conflict_data = NULL,
     tree_conflict_data = NULL,
     conflict_old = NULL,
     conflict_new = NULL,
@@ -363,7 +354,6 @@ UPDATE actual_node
 SET properties = NULL,
     text_mod = NULL,
     changelist = NULL,
-    tree_conflict_data = NULL,
     conflict_old = NULL,
     conflict_new = NULL,
     conflict_working = NULL,
@@ -437,10 +427,6 @@ SELECT checksum
 FROM pristine
 WHERE md5_checksum = ?1
 
--- STMT_SELECT_PRISTINE_ROWS
-SELECT checksum
-FROM pristine
-
 -- STMT_SELECT_ANY_PRISTINE_REFERENCE
 SELECT 1 FROM nodes
   WHERE checksum = ?1 OR checksum = ?2
@@ -451,6 +437,22 @@ SELECT 1 FROM actual_node
     OR  right_checksum = ?1 OR right_checksum = ?2
 LIMIT 1
 
+-- STMT_SELECT_UNREFERENCED_PRISTINES
+SELECT checksum
+FROM pristine
+EXCEPT
+SELECT checksum FROM nodes
+  WHERE checksum IS NOT NULL
+EXCEPT
+SELECT older_checksum FROM actual_node
+  WHERE older_checksum IS NOT NULL
+EXCEPT
+SELECT left_checksum FROM actual_node
+  WHERE left_checksum  IS NOT NULL
+EXCEPT
+SELECT right_checksum FROM actual_node
+  WHERE right_checksum IS NOT NULL
+
 -- STMT_DELETE_PRISTINE
 DELETE FROM pristine
 WHERE checksum = ?1
@@ -461,15 +463,16 @@ FROM actual_node
 WHERE wc_id = ?1 AND parent_relpath = ?2 AND
   NOT ((prop_reject IS NULL) AND (conflict_old IS NULL)
        AND (conflict_new IS NULL) AND (conflict_working IS NULL)
-       AND (conflict_data IS NULL))
+       AND (tree_conflict_data IS NULL))
 
 -- STMT_SELECT_ACTUAL_CHILDREN_TREE_CONFLICT
-SELECT local_relpath, conflict_data
+SELECT local_relpath, tree_conflict_data
 FROM actual_node
-WHERE wc_id = ?1 AND parent_relpath = ?2 AND conflict_data IS NOT NULL;
+WHERE wc_id = ?1 AND parent_relpath = ?2 AND tree_conflict_data IS NOT NULL;
 
 -- STMT_SELECT_CONFLICT_DETAILS
-SELECT prop_reject, conflict_old, conflict_new, conflict_working, conflict_data
+SELECT prop_reject, conflict_old, conflict_new, conflict_working,
+    tree_conflict_data
 FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
@@ -523,6 +526,19 @@ SELECT wc_id, local_relpath, ?3 AS op_de
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
 
+-- STMT_INSERT_WORKING_NODE_FROM_NODE
+INSERT OR REPLACE INTO nodes (
+    wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
+    changed_revision, changed_date, changed_author, depth, symlink_target,
+    translated_size, last_mod_time, properties)
+SELECT wc_id, local_relpath, ?3 AS op_depth, parent_relpath, ?4 AS presence,
+       kind, checksum, changed_revision, changed_date, changed_author, depth,
+       symlink_target, translated_size, last_mod_time, properties
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2
+ORDER BY op_depth DESC
+LIMIT 1;
+
 -- STMT_INSERT_WORKING_NODE_FROM_BASE_COPY
 INSERT INTO nodes (
     wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
@@ -715,7 +731,7 @@ WHERE wc_id = ?1 AND (local_relpath = ?2
 SELECT 1
 FROM actual_node
 WHERE wc_id = ?1 AND (local_relpath = ?2 OR local_relpath LIKE ?3 ESCAPE '#')
-  AND conflict_data IS NULL;
+  AND tree_conflict_data IS NULL;
 
 /* ------------------------------------------------------------------------- */
 
@@ -756,6 +772,15 @@ WHERE wc_id = ?1 AND local_relpath = ?2 
 
 /* these are used in upgrade.c  */
 
+-- STMT_UPDATE_ACTUAL_CONFLICT_DATA
+UPDATE actual_node SET conflict_data = ?3
+WHERE wc_id = ?1 AND local_relpath = ?2;
+
+-- STMT_INSERT_ACTUAL_CONFLICT_DATA
+INSERT INTO actual_node (
+  wc_id, local_relpath, conflict_data, parent_relpath)
+VALUES (?1, ?2, ?3, ?4);
+
 -- STMT_SELECT_OLD_TREE_CONFLICT
 SELECT wc_id, local_relpath, tree_conflict_data
 FROM actual_node

Modified: subversion/branches/performance/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc.h?rev=1043705&r1=1043704&r2=1043705&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc.h Wed Dec  8 21:53:38 2010
@@ -129,7 +129,7 @@ extern "C" {
  * Please document any further format changes here.
  */
 
-#define SVN_WC__VERSION 21
+#define SVN_WC__VERSION 22
 
 /* Formats <= this have no concept of "revert text-base/props".  */
 #define SVN_WC__NO_REVERT_FILES 4