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

svn commit: r993141 [16/25] - in /subversion/branches/performance: ./ build/ac-macros/ build/generator/ contrib/server-side/ notes/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/...

Modified: subversion/branches/performance/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/upgrade.c?rev=993141&r1=993140&r2=993141&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/upgrade.c Mon Sep  6 20:02:15 2010
@@ -31,8 +31,6 @@
 
 #include "wc.h"
 #include "adm_files.h"
-#include "lock.h"
-#include "log.h"
 #include "entries.h"
 #include "wc_db.h"
 #include "tree_conflicts.h"
@@ -69,14 +67,7 @@
 
 /* New pristine location */
 #define PRISTINE_STORAGE_RELPATH "pristine"
-
-
-/* Forward declare until we decide to shift/reorder functions.  */
-static svn_error_t *
-migrate_props(const char *wcroot_abspath,
-              svn_sqlite__db_t *sdb,
-              int original_format,
-              apr_pool_t *scratch_pool);
+#define SDB_FILE  "wc.db"
 
 
 /* Read the properties from the file at PROPFILE_ABSPATH, returning them
@@ -96,7 +87,7 @@ read_propfile(apr_hash_t **props,
 
   if (err
       && (APR_STATUS_IS_ENOENT(err->apr_err)
-          || APR_STATUS_IS_ENOTDIR(err->apr_err)))
+          || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
     {
       svn_error_clear(err);
 
@@ -290,60 +281,36 @@ maybe_add_subdir(apr_array_header_t *sub
 }
 
 
-/* Return in CHILDREN, the list of all versioned subdirectories which also
-   exist on disk as directories.  */
+/* Return in CHILDREN, the list of all 1.6 versioned subdirectories
+   which also exist on disk as directories.  */
 static svn_error_t *
 get_versioned_subdirs(apr_array_header_t **children,
-                      svn_wc__db_t *db,
                       const char *dir_abspath,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
 {
-  int wc_format;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_t *entries;
+  apr_hash_index_t *hi;
 
   *children = apr_array_make(result_pool, 10, sizeof(const char *));
 
-  SVN_ERR(svn_wc__db_temp_get_format(&wc_format, db, dir_abspath, iterpool));
-  if (wc_format >= SVN_WC__WC_NG_VERSION)
-    {
-      const apr_array_header_t *all_children;
-      int i;
-
-      SVN_ERR(svn_wc__db_read_children(&all_children, db, dir_abspath,
-                                       scratch_pool, scratch_pool));
-      for (i = 0; i < all_children->nelts; ++i)
-        {
-          const char *name = APR_ARRAY_IDX(all_children, i, const char *);
-
-          svn_pool_clear(iterpool);
-
-          SVN_ERR(maybe_add_subdir(*children, dir_abspath, name,
-                                   result_pool, iterpool));
-        }
-    }
-  else
+  SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath,
+                                   scratch_pool, iterpool));
+  for (hi = apr_hash_first(scratch_pool, entries);
+       hi;
+       hi = apr_hash_next(hi))
     {
-      apr_hash_t *entries;
-      apr_hash_index_t *hi;
-
-      SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath,
-                                       scratch_pool, iterpool));
-      for (hi = apr_hash_first(scratch_pool, entries);
-           hi;
-           hi = apr_hash_next(hi))
-        {
-          const char *name = svn__apr_hash_index_key(hi);
+      const char *name = svn__apr_hash_index_key(hi);
 
-          /* skip "this dir"  */
-          if (*name == '\0')
-            continue;
+      /* skip "this dir"  */
+      if (*name == '\0')
+        continue;
 
-          svn_pool_clear(iterpool);
+      svn_pool_clear(iterpool);
 
-          SVN_ERR(maybe_add_subdir(*children, dir_abspath, name,
-                                   result_pool, iterpool));
-        }
+      SVN_ERR(maybe_add_subdir(*children, dir_abspath, name,
+                               result_pool, iterpool));
     }
 
   svn_pool_destroy(iterpool);
@@ -352,34 +319,34 @@ get_versioned_subdirs(apr_array_header_t
 }
 
 
-/* Return in CHILDREN, the list of all versioned *files* in SDB.
-   These files' existence on disk is not tested.
+/* Return in CHILDREN the names of all versioned *files* in SDB that
+   are children of PARENT_RELPATH.  These files' existence on disk is
+   not tested.
 
-   This set of children is intended for props/text-base upgrades.
-   Subdirectory's properties exist in the subdirs. Non-files have no
-   text bases.
+   This set of children is intended for property upgrades.
+   Subdirectory's properties exist in the subdirs.
 
    Note that this uses just the SDB to locate children, which means
-   that the children must have been upgraded to wc-ng format. Also note
-   that this returns *all* files found in SDB. Typically, this is just
-   one directory's worth since it won't be run on a single-db.  */
+   that the children must have been upgraded to wc-ng format. */
 static svn_error_t *
 get_versioned_files(const apr_array_header_t **children,
+                    const char *parent_relpath,
                     svn_sqlite__db_t *sdb,
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
-  apr_array_header_t *child_relpaths;
+  apr_array_header_t *child_names;
   svn_boolean_t have_row;
 
   /* ### just select 'file' children. do we need 'symlink' in the future?  */
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_ALL_FILES));
+  SVN_ERR(svn_sqlite__bindf(stmt, "s", parent_relpath));
 
   /* ### 10 is based on Subversion's average of 8.5 files per versioned
      ### directory in its repository. maybe use a different value? or
      ### count rows first?  */
-  child_relpaths = apr_array_make(result_pool, 10, sizeof(const char *));
+  child_names = apr_array_make(result_pool, 10, sizeof(const char *));
 
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   while (have_row)
@@ -387,12 +354,13 @@ get_versioned_files(const apr_array_head
       const char *local_relpath = svn_sqlite__column_text(stmt, 0,
                                                           result_pool);
 
-      APR_ARRAY_PUSH(child_relpaths, const char *) = local_relpath;
+      APR_ARRAY_PUSH(child_names, const char *)
+        = svn_relpath_basename(local_relpath, result_pool);
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
 
-  *children = child_relpaths;
+  *children = child_names;
 
   return svn_error_return(svn_sqlite__reset(stmt));
 }
@@ -488,7 +456,6 @@ wipe_obsolete_files(const char *wcroot_a
                                       scratch_pool),
                     FALSE, NULL, NULL, scratch_pool));
 
-#if (SVN_WC__VERSION >= 18)
   /* Remove the old properties files... whole directories at a time.  */
   svn_error_clear(svn_io_remove_dir2(
                     svn_wc__adm_child(wcroot_abspath,
@@ -500,7 +467,21 @@ wipe_obsolete_files(const char *wcroot_a
                                       PROP_BASE_SUBDIR,
                                       scratch_pool),
                     FALSE, NULL, NULL, scratch_pool));
-#endif
+  svn_error_clear(svn_io_remove_file2(
+                     svn_wc__adm_child(wcroot_abspath,
+                                       PROP_WORKING_FOR_DIR,
+                                       scratch_pool),
+                     TRUE, scratch_pool));
+  svn_error_clear(svn_io_remove_file2(
+                     svn_wc__adm_child(wcroot_abspath,
+                                      PROP_BASE_FOR_DIR,
+                                      scratch_pool),
+                     TRUE, scratch_pool));
+  svn_error_clear(svn_io_remove_file2(
+                     svn_wc__adm_child(wcroot_abspath,
+                                      PROP_REVERT_FOR_DIR,
+                                      scratch_pool),
+                     TRUE, scratch_pool));
 
 #if 0
   /* ### this checks for a write-lock, and we are not (always) taking out
@@ -872,9 +853,6 @@ migrate_locks(const char *wcroot_abspath
 
 struct bump_baton {
   const char *wcroot_abspath;
-#ifdef SINGLE_DB
-  const char *single_db_wcroot_abspath;
-#endif
 };
 
 /* */
@@ -913,7 +891,8 @@ bump_to_16(void *baton, svn_sqlite__db_t
 
 /* Migrate the properties for one node (LOCAL_ABSPATH).  */
 static svn_error_t *
-migrate_node_props(const char *wcroot_abspath,
+migrate_node_props(const char *dir_abspath,
+                   const char *new_wcroot_abspath,
                    const char *name,
                    svn_sqlite__db_t *sdb,
                    int original_format,
@@ -925,24 +904,29 @@ migrate_node_props(const char *wcroot_ab
   apr_hash_t *base_props;
   apr_hash_t *revert_props;
   apr_hash_t *working_props;
+  const char *old_wcroot_abspath
+    = svn_dirent_get_longest_ancestor(dir_abspath, new_wcroot_abspath,
+                                      scratch_pool);
+  const char *dir_relpath = svn_dirent_skip_ancestor(old_wcroot_abspath,
+                                                     dir_abspath);
 
   if (*name == '\0')
     {
-      base_abspath = svn_wc__adm_child(wcroot_abspath, PROP_BASE_FOR_DIR,
-                                       scratch_pool);
-      revert_abspath = svn_wc__adm_child(wcroot_abspath, PROP_REVERT_FOR_DIR,
-                                         scratch_pool);
-      working_abspath = svn_wc__adm_child(wcroot_abspath, PROP_WORKING_FOR_DIR,
-                                          scratch_pool);
+      base_abspath = svn_wc__adm_child(dir_abspath,
+                                       PROP_BASE_FOR_DIR, scratch_pool);
+      revert_abspath = svn_wc__adm_child(dir_abspath,
+                                         PROP_REVERT_FOR_DIR, scratch_pool);
+      working_abspath = svn_wc__adm_child(dir_abspath,
+                                          PROP_WORKING_FOR_DIR, scratch_pool);
     }
   else
     {
       const char *basedir_abspath;
       const char *propsdir_abspath;
 
-      propsdir_abspath = svn_wc__adm_child(wcroot_abspath, PROPS_SUBDIR,
+      propsdir_abspath = svn_wc__adm_child(dir_abspath, PROPS_SUBDIR,
                                            scratch_pool);
-      basedir_abspath = svn_wc__adm_child(wcroot_abspath, PROP_BASE_SUBDIR,
+      basedir_abspath = svn_wc__adm_child(dir_abspath, PROP_BASE_SUBDIR,
                                           scratch_pool);
 
       base_abspath = svn_dirent_join(basedir_abspath,
@@ -975,7 +959,8 @@ migrate_node_props(const char *wcroot_ab
                         scratch_pool, scratch_pool));
 
   return svn_error_return(svn_wc__db_upgrade_apply_props(
-                            sdb, wcroot_abspath, name,
+                            sdb, new_wcroot_abspath,
+                            svn_relpath_join(dir_relpath, name, scratch_pool),
                             base_props, revert_props, working_props,
                             original_format,
                             scratch_pool));
@@ -984,7 +969,8 @@ migrate_node_props(const char *wcroot_ab
 
 /* */
 static svn_error_t *
-migrate_props(const char *wcroot_abspath,
+migrate_props(const char *dir_abspath,
+              const char *new_wcroot_abspath,
               svn_sqlite__db_t *sdb,
               int original_format,
               apr_pool_t *scratch_pool)
@@ -1011,22 +997,28 @@ migrate_props(const char *wcroot_abspath
   */
   const apr_array_header_t *children;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  const char *old_wcroot_abspath
+    = svn_dirent_get_longest_ancestor(dir_abspath, new_wcroot_abspath,
+                                      scratch_pool);
+  const char *dir_relpath = svn_dirent_skip_ancestor(old_wcroot_abspath,
+                                                     dir_abspath);
   int i;
 
   /* Migrate the props for "this dir".  */
-  SVN_ERR(migrate_node_props(wcroot_abspath, "", sdb, original_format,
-                             iterpool));
+  SVN_ERR(migrate_node_props(dir_abspath, new_wcroot_abspath, "", sdb,
+                             original_format, iterpool));
 
   /* Iterate over all the files in this SDB.  */
-  SVN_ERR(get_versioned_files(&children, sdb, scratch_pool, iterpool));
+  SVN_ERR(get_versioned_files(&children, dir_relpath, sdb, scratch_pool,
+                              iterpool));
   for (i = 0; i < children->nelts; i++)
     {
       const char *name = APR_ARRAY_IDX(children, i, const char *);
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(migrate_node_props(wcroot_abspath, name, sdb, original_format,
-                                 iterpool));
+      SVN_ERR(migrate_node_props(dir_abspath, new_wcroot_abspath,
+                                 name, sdb, original_format, iterpool));
     }
 
   svn_pool_destroy(iterpool);
@@ -1048,27 +1040,26 @@ bump_to_18(void *baton, svn_sqlite__db_t
 {
   struct bump_to_18_baton *b18 = baton;
 
-#if 0
   /* ### no schema changes (yet)... */
   SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_18));
-#endif
 
-  SVN_ERR(migrate_props(b18->wcroot_abspath, sdb, b18->original_format,
-                        scratch_pool));
+  SVN_ERR(migrate_props(b18->wcroot_abspath, b18->wcroot_abspath, sdb,
+                        b18->original_format, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
 
 static svn_error_t *
-migrate_text_bases(const char *wcroot_abspath,
+migrate_text_bases(const char *dir_abspath,
+                   const char *new_wcroot_abspath,
                    svn_sqlite__db_t *sdb,
                    apr_pool_t *scratch_pool)
 {
   apr_hash_t *dirents;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_hash_index_t *hi;
-  const char *text_base_dir = svn_wc__adm_child(wcroot_abspath,
+  const char *text_base_dir = svn_wc__adm_child(dir_abspath,
                                                 TEXT_BASE_SUBDIR,
                                                 scratch_pool);
 
@@ -1116,7 +1107,7 @@ migrate_text_bases(const char *wcroot_ab
       SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
       SVN_ERR(svn_wc__db_pristine_get_future_path(&pristine_path,
-                                                  wcroot_abspath,
+                                                  new_wcroot_abspath,
                                                   sha1_checksum,
                                                   iterpool, iterpool));
 
@@ -1144,78 +1135,11 @@ bump_to_17(void *baton, svn_sqlite__db_t
   const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath;
 
   SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_17));
-  SVN_ERR(migrate_text_bases(wcroot_abspath, sdb, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-#ifdef SINGLE_DB
-/* Migrate one directory to a Single DB (per WC): if this is a subdirectory,
- * move all of its DB rows and pristine texts to the real WC-root.
- *
- * ### JAF: This is experimental code for others to use or ignore until I
- *          get back to it.  It may need to be re-written in a completely
- *          different way.  Especially, it probably wants to be moved from
- *          the auto-upgrade code path to the manual-upgrade code path.
- *          How to make the caller provide the BATON->wcroot_abspath and
- */
-static svn_error_t *
-bump_to_19(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  struct bump_baton *bb = baton;
-  const char *this_wc_dir_abspath = bb->wcroot_abspath;
-  const char *single_db_wcroot_abspath = bb->single_db_wcroot_abspath;
-  const char *this_wc_dir_relpath
-    = svn_relpath_is_child(single_db_wcroot_abspath, this_wc_dir_abspath,
-                           scratch_pool);
-  const char *parent_wc_dir_relpath
-    = svn_relpath_dirname(this_wc_dir_relpath, scratch_pool);
-  const char *single_db_sdb_abspath;
-  svn_sqlite__stmt_t *stmt;
-
-  /* If this is the single-DB WC root directory, there is nothing to do for
-   * this particular directory. */
-  if (strcmp(this_wc_dir_abspath, single_db_wcroot_abspath) == 0)
-    return SVN_NO_ERROR;
-
-  /* Get the path to the WC-root SDB as a native style path, UTF-8-encoded. */
-  single_db_sdb_abspath = svn_wc__adm_child(single_db_wcroot_abspath, "wc.db",
-                                            scratch_pool);
-  /* ### TODO: convert path to native style */
-
-  /* Attach the single-db so we can write into it. */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_ATTACH_WCROOT_DB));
-  SVN_ERR(svn_sqlite__bindf(stmt, "s", single_db_sdb_abspath));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-
-  /* ### TODO: the REPOSITORY table */
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    STMT_COPY_BASE_NODE_TABLE_TO_WCROOT_DB));
-  SVN_ERR(svn_sqlite__bindf(stmt, "ss", this_wc_dir_relpath, parent_wc_dir_relpath));
-  SVN_ERR(svn_sqlite__update(NULL, stmt));
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    STMT_COPY_WORKING_NODE_TABLE_TO_WCROOT_DB));
-  SVN_ERR(svn_sqlite__bindf(stmt, "ss", this_wc_dir_relpath, parent_wc_dir_relpath));
-  SVN_ERR(svn_sqlite__update(NULL, stmt));
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    STMT_COPY_ACTUAL_NODE_TABLE_TO_WCROOT_DB));
-  SVN_ERR(svn_sqlite__bindf(stmt, "ss", this_wc_dir_relpath, parent_wc_dir_relpath));
-  SVN_ERR(svn_sqlite__update(NULL, stmt));
-
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_COPY_LOCK_TABLE_TO_WCROOT_DB));
-
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_COPY_PRISTINE_TABLE_TO_WCROOT_DB));
-
-  /* ### TODO: move the pristine text files from this_wc_dir_abspath to
-   * single_db_wcroot_abspath. */
+  SVN_ERR(migrate_text_bases(wcroot_abspath, wcroot_abspath, sdb,
+                             scratch_pool));
 
   return SVN_NO_ERROR;
 }
-#endif  /* SINGLE_DB */
 
 
 #if 0 /* ### no tree conflict migration yet */
@@ -1235,6 +1159,13 @@ bump_to_XXX(void *baton, svn_sqlite__db_
 
 #endif /* ### no tree conflict migration yet */
 
+struct upgrade_data_t {
+  svn_sqlite__db_t *sdb;
+  const char *root_abspath;
+  apr_int64_t repos_id;
+  apr_int64_t wc_id;
+};
+
 /* Upgrade the working copy directory represented by DB/DIR_ABSPATH
    from OLD_FORMAT to the wc-ng format (SVN_WC__WC_NG_VERSION)'.
 
@@ -1243,6 +1174,10 @@ bump_to_XXX(void *baton, svn_sqlite__db_
    REPOS_CACHE if it doesn't have a cached entry for this
    repository.
 
+   DATA->SDB will be null if this is the root directory, in which case
+   the db must be created and *DATA filled in, otherwise *DATA refer
+   to the single root db.
+
    Uses SCRATCH_POOL for all temporary allocation.  */
 static svn_error_t *
 upgrade_to_wcng(svn_wc__db_t *db,
@@ -1251,6 +1186,8 @@ upgrade_to_wcng(svn_wc__db_t *db,
                 svn_wc_upgrade_get_repos_info_t repos_info_func,
                 void *repos_info_baton,
                 apr_hash_t *repos_cache,
+                struct upgrade_data_t *data,
+                apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
   const char *logfile_path = svn_wc__adm_child(dir_abspath, ADM_LOG,
@@ -1258,15 +1195,11 @@ upgrade_to_wcng(svn_wc__db_t *db,
   svn_node_kind_t logfile_on_disk;
   apr_hash_t *entries;
   svn_wc_entry_t *this_dir;
-  svn_sqlite__db_t *sdb;
-  apr_int64_t repos_id;
-  apr_int64_t wc_id;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   /* Don't try to mess with the WC if there are old log files left. */
 
   /* Is the (first) log file present?  */
-  SVN_ERR(svn_io_check_path(logfile_path, &logfile_on_disk, iterpool));
+  SVN_ERR(svn_io_check_path(logfile_path, &logfile_on_disk, scratch_pool));
   if (logfile_on_disk == svn_node_file)
     return svn_error_create(SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
                             _("Cannot upgrade with existing logs; please "
@@ -1275,7 +1208,7 @@ upgrade_to_wcng(svn_wc__db_t *db,
   /* Lock this working copy directory, or steal an existing lock. Do this
      BEFORE we read the entries. We don't want another process to modify the
      entries after we've read them into memory.  */
-  SVN_ERR(create_physical_lock(dir_abspath, iterpool));
+  SVN_ERR(create_physical_lock(dir_abspath, scratch_pool));
 
   /* What's going on here?
    *
@@ -1296,13 +1229,13 @@ upgrade_to_wcng(svn_wc__db_t *db,
 
   /***** ENTRIES *****/
   SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath,
-                                   scratch_pool, iterpool));
+                                   scratch_pool, scratch_pool));
 
   this_dir = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING);
   SVN_ERR(ensure_repos_info(this_dir, dir_abspath,
                             repos_info_func, repos_info_baton,
                             repos_cache,
-                            scratch_pool, iterpool));
+                            scratch_pool, scratch_pool));
 
   /* Cache repos UUID pairs for when a subdir doesn't have this information */
   if (!apr_hash_get(repos_cache, this_dir->repos, APR_HASH_KEY_STRING))
@@ -1315,22 +1248,43 @@ upgrade_to_wcng(svn_wc__db_t *db,
                    apr_pstrdup(hash_pool, this_dir->uuid));
     }
 
-  /* Create an empty sqlite database for this directory. */
-  SVN_ERR(svn_wc__db_upgrade_begin(&sdb, &repos_id, &wc_id, dir_abspath,
-                                   this_dir->repos, this_dir->uuid,
-                                   scratch_pool, iterpool));
+  if (!data->sdb)
+    {
+      const char *root_adm_abspath;
 
-  /* Migrate the entries over to the new database.
-     ### We need to think about atomicity here.
+      /* In root wc construst path to temporary root wc/.svn/wcng/.svn
 
-     entries_write_new() writes in current format rather than f12. Thus, this
-     function bumps a working copy all the way to current.  */
-  SVN_ERR(svn_wc__db_temp_reset_format(SVN_WC__VERSION, db, dir_abspath,
-                                       iterpool));
-  SVN_ERR(svn_wc__db_wclock_obtain(db, dir_abspath, 0, FALSE, iterpool));
-  SVN_ERR(svn_wc__write_upgraded_entries(db, sdb, repos_id, wc_id,
-                                         dir_abspath, entries,
-                                         iterpool));
+         ### This should really be in tmp so that 1.6 can cleanup if
+             interrupted, i.e. wc/.svn/tmp/wcng/.svn */
+      data->root_abspath = svn_wc__adm_child(dir_abspath, "wcng", result_pool);
+      root_adm_abspath = svn_wc__adm_child(data->root_abspath, "",
+                                           scratch_pool);
+      SVN_ERR(svn_wc__ensure_directory(root_adm_abspath, scratch_pool));
+
+      /* Create an empty sqlite database for this directory. */
+      SVN_ERR(svn_wc__db_upgrade_begin(&data->sdb,
+                                       &data->repos_id, &data->wc_id,
+                                       data->root_abspath,
+                                       this_dir->repos, this_dir->uuid,
+                                       result_pool, scratch_pool));
+
+      /* Migrate the entries over to the new database.
+         ### We need to think about atomicity here.
+
+         entries_write_new() writes in current format rather than
+         f12. Thus, this function bumps a working copy all the way to
+         current.  */
+      SVN_ERR(svn_wc__db_temp_reset_format(SVN_WC__VERSION, db,
+                                           data->root_abspath, scratch_pool));
+      SVN_ERR(svn_wc__db_wclock_obtain(db, data->root_abspath, 0, FALSE,
+                                       scratch_pool));
+    }
+ 
+  SVN_ERR(svn_wc__write_upgraded_entries(db, data->sdb,
+                                         data->repos_id, data->wc_id,
+                                         dir_abspath, data->root_abspath,
+                                         entries,
+                                         scratch_pool));
 
   /***** WC PROPS *****/
 
@@ -1338,44 +1292,51 @@ upgrade_to_wcng(svn_wc__db_t *db,
   if (old_format != SVN_WC__WCPROPS_LOST)
     {
       apr_hash_t *all_wcprops;
+      const char *old_wcroot_abspath
+        = svn_dirent_get_longest_ancestor(dir_abspath, data->root_abspath,
+                                          scratch_pool);
+      const char *dir_relpath = svn_dirent_skip_ancestor(old_wcroot_abspath,
+                                                         dir_abspath);
 
       if (old_format <= SVN_WC__WCPROPS_MANY_FILES_VERSION)
         SVN_ERR(read_many_wcprops(&all_wcprops, dir_abspath,
-                                  iterpool, iterpool));
+                                  scratch_pool, scratch_pool));
       else
         SVN_ERR(read_wcprops(&all_wcprops, dir_abspath,
-                             iterpool, iterpool));
+                             scratch_pool, scratch_pool));
 
-      SVN_ERR(svn_wc__db_upgrade_apply_dav_cache(sdb, all_wcprops, iterpool));
+      SVN_ERR(svn_wc__db_upgrade_apply_dav_cache(data->sdb, dir_relpath,
+                                                 all_wcprops, scratch_pool));
     }
 
-  SVN_ERR(migrate_text_bases(dir_abspath, sdb, iterpool));
+  SVN_ERR(migrate_text_bases(dir_abspath, data->root_abspath, data->sdb,
+                             scratch_pool));
 
-#if (SVN_WC__VERSION >= 18)
   /* Upgrade all the properties (including "this dir").
 
      Note: this must come AFTER the entries have been migrated into the
      database. The upgrade process needs the children in BASE_NODE and
      WORKING_NODE, and to examine the resultant WORKING state.  */
-  SVN_ERR(migrate_props(dir_abspath, sdb, old_format, iterpool));
-#endif
+  SVN_ERR(migrate_props(dir_abspath, data->root_abspath, data->sdb, old_format,
+                        scratch_pool));
 
   /* All done. DB should finalize the upgrade process now.  */
-  SVN_ERR(svn_wc__db_upgrade_finish(dir_abspath, sdb, iterpool));
-
-  /* All subdir access batons (and locks!) will be closed. Of course, they
-     should have been closed/unlocked just after their own upgrade process
-     has run.  */
-  /* ### well, actually.... we don't recursively delete subdir locks here,
-     ### we rely upon their own upgrade processes to do it. */
-  SVN_ERR(svn_wc__db_wclock_release(db, dir_abspath, iterpool));
-
-  /* Zap all the obsolete files. This removes the old-style lock file.  */
-  wipe_obsolete_files(dir_abspath, iterpool);
+  SVN_ERR(svn_wc__db_upgrade_finish(dir_abspath, data->sdb, scratch_pool));
 
-  /* ### need to (eventually) delete the .svn subdir.  */
+  /* Zap all the obsolete files. This removes the old-style lock file.
+     In single-db we should postpone this until we have processed all
+     entries files into the single-db, otherwise an interrupted
+     upgrade is nasty.  Perhaps add a wq item?  If we do postpone then
+     perhaps we should still remove the lock otherwise the user has to
+     use 1.6 to cleanup. */
+  wipe_obsolete_files(dir_abspath, scratch_pool);
+
+  /* Remove the admin dir in subdirectories of the root. */
+  if (!svn_dirent_is_ancestor(dir_abspath, data->root_abspath))
+    svn_error_clear(svn_io_remove_dir2(svn_wc__adm_child(dir_abspath, NULL,
+                                                         scratch_pool),
+                                       FALSE, NULL, NULL, scratch_pool));
 
-  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -1446,7 +1407,6 @@ svn_wc__upgrade_sdb(int *result_format,
         *result_format = 16;
         /* FALLTHROUGH  */
 
-#if (SVN_WC__VERSION > 16)
       case 16:
         {
           const char *pristine_dir;
@@ -1464,9 +1424,7 @@ svn_wc__upgrade_sdb(int *result_format,
 
         *result_format = 17;
         /* FALLTHROUGH  */
-#endif
 
-#if (SVN_WC__VERSION > 17)
       case 17:
         {
           struct bump_to_18_baton b18;
@@ -1481,16 +1439,13 @@ svn_wc__upgrade_sdb(int *result_format,
 
         *result_format = 18;
         /* FALLTHROUGH  */
-#endif
 
 #if (SVN_WC__VERSION > 18)
       case 18:
-        /* Merge all subdirectory DBs and pristines into the WC-root. */
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_19, &bb,
-                                             scratch_pool));
-
-        *result_format = 19;
-        /* FALLTHROUGH  */
+        return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                 _("The working copy '%s' is at format 18; "
+                                   "use 'tools/dev/wc-ng/bump-to-19.py' to "
+                                   "upgrade it"), wcroot_abspath);
 #endif
 
       /* ### future bumps go here.  */
@@ -1504,6 +1459,17 @@ svn_wc__upgrade_sdb(int *result_format,
 #endif
     }
 
+#ifdef SVN_DEBUG
+  if (*result_format != start_format)
+    {
+      int schema_version;
+      SVN_ERR(svn_sqlite__read_schema_version(&schema_version, sdb, scratch_pool));
+
+      /* If this assertion fails the schema isn't updated correctly */
+      SVN_ERR_ASSERT(schema_version == *result_format);
+    }
+#endif
+
   /* Zap anything that might be remaining or escaped our notice.  */
   wipe_obsolete_files(wcroot_abspath, scratch_pool);
 
@@ -1518,6 +1484,7 @@ upgrade_working_copy(svn_wc__db_t *db,
                      svn_wc_upgrade_get_repos_info_t repos_info_func,
                      void *repos_info_baton,
                      apr_hash_t *repos_cache,
+                     struct upgrade_data_t *data,
                      svn_cancel_func_t cancel_func,
                      void *cancel_baton,
                      svn_wc_notify_func2_t notify_func,
@@ -1536,14 +1503,24 @@ upgrade_working_copy(svn_wc__db_t *db,
   SVN_ERR(svn_wc__db_temp_get_format(&old_format, db, dir_abspath,
                                      iterpool));
 
-  SVN_ERR(get_versioned_subdirs(&subdirs, db, dir_abspath,
+  if (old_format >= SVN_WC__WC_NG_VERSION)
+    {
+      if (notify_func)
+        notify_func(notify_baton,
+                    svn_wc_create_notify(dir_abspath, svn_wc_notify_skip,
+                                         iterpool),
+                iterpool);
+      return SVN_NO_ERROR;
+    }
+
+  /* At present upgrade_to_wcng removes the entries file so get the
+     children before calling it. */
+  SVN_ERR(get_versioned_subdirs(&subdirs, dir_abspath,
                                 scratch_pool, iterpool));
 
-  /* Upgrade this directory first. */
-  if (old_format < SVN_WC__WC_NG_VERSION)
-    SVN_ERR(upgrade_to_wcng(db, dir_abspath, old_format,
-                            repos_info_func, repos_info_baton,
-                            repos_cache, iterpool));
+  SVN_ERR(upgrade_to_wcng(db, dir_abspath, old_format,
+                          repos_info_func, repos_info_baton,
+                          repos_cache, data, scratch_pool, iterpool));
 
   if (notify_func)
     notify_func(notify_baton,
@@ -1551,7 +1528,6 @@ upgrade_working_copy(svn_wc__db_t *db,
                                      iterpool),
                 iterpool);
 
-  /* Now recurse. */
   for (i = 0; i < subdirs->nelts; ++i)
     {
       const char *child_abspath = APR_ARRAY_IDX(subdirs, i, const char *);
@@ -1560,7 +1536,7 @@ upgrade_working_copy(svn_wc__db_t *db,
 
       SVN_ERR(upgrade_working_copy(db, child_abspath,
                                    repos_info_func, repos_info_baton,
-                                   repos_cache,
+                                   repos_cache, data,
                                    cancel_func, cancel_baton,
                                    notify_func, notify_baton,
                                    iterpool));
@@ -1572,6 +1548,44 @@ upgrade_working_copy(svn_wc__db_t *db,
 }
 
 
+/* Return TRUE if LOCAL_ABSPATH is a pre-1.7 working copy root, FALSE
+   otherwise. */
+static svn_boolean_t
+is_old_wcroot(const char *local_abspath,
+              apr_pool_t *scratch_pool)
+{
+  apr_hash_t *entries;
+  const char *parent_abspath, *name;
+  svn_wc_entry_t *entry;
+  svn_error_t *err = svn_wc__read_entries_old(&entries, local_abspath,
+                                              scratch_pool, scratch_pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return FALSE;
+    }
+
+  svn_dirent_split(&parent_abspath, &name, local_abspath, scratch_pool);
+
+  err = svn_wc__read_entries_old(&entries, parent_abspath,
+                                 scratch_pool, scratch_pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return TRUE;
+    }
+
+  entry = apr_hash_get(entries, name, APR_HASH_KEY_STRING);
+  if (!entry
+      || entry->absent
+      || (entry->deleted && entry->schedule != svn_wc_schedule_add))
+    {
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 svn_error_t *
 svn_wc_upgrade(svn_wc_context_t *wc_ctx,
                const char *local_abspath,
@@ -1584,9 +1598,7 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
                apr_pool_t *scratch_pool)
 {
   svn_wc__db_t *db;
-#if 0
-  svn_boolean_t is_wcroot;
-#endif
+  struct upgrade_data_t data = { NULL };
 
   /* We need a DB that does not attempt an auto-upgrade, nor require
      running a stale work queue. We'll handle everything manually.  */
@@ -1594,25 +1606,46 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
                           NULL /* ### config */, FALSE, FALSE,
                           scratch_pool, scratch_pool));
 
-  /* ### this expects a wc-ng working copy. sigh. fix up soonish...  */
-#if 0
-  SVN_ERR(svn_wc__strictly_is_wc_root(&is_wcroot, wc_ctx, local_abspath,
-                                      scratch_pool));
-  if (!is_wcroot)
-    return svn_error_create(
+  if (!is_old_wcroot(local_abspath, scratch_pool))
+    return svn_error_createf(
       SVN_ERR_WC_INVALID_OP_ON_CWD, NULL,
-      _("'svn upgrade' can only be run from the root of the working copy."));
-#endif
+      _("Cannot upgrade '%s' as it is not a pre-1.7 working copy root"),
+      svn_dirent_local_style(local_abspath, scratch_pool));
 
   /* Upgrade this directory and/or its subdirectories.  */
   SVN_ERR(upgrade_working_copy(db, local_abspath,
                                repos_info_func, repos_info_baton,
-                               apr_hash_make(scratch_pool),
+                               apr_hash_make(scratch_pool), &data,
                                cancel_func, cancel_baton,
                                notify_func, notify_baton,
                                scratch_pool));
 
+  SVN_ERR(svn_wc__db_wclock_release(db, data.root_abspath, scratch_pool));
+  SVN_ERR(svn_wc__db_drop_root(db, data.root_abspath, scratch_pool));
+  SVN_ERR(svn_sqlite__close(data.sdb));
+  {
+    const char *pristine_from = svn_wc__adm_child(data.root_abspath,
+                                                  PRISTINE_STORAGE_RELPATH,
+                                                  scratch_pool);
+    const char *pristine_to = svn_wc__adm_child(local_abspath,
+                                                PRISTINE_STORAGE_RELPATH,
+                                                scratch_pool);
+    SVN_ERR(svn_io_file_rename(pristine_from, pristine_to, scratch_pool));
+  }
+  {
+    const char *db_from = svn_wc__adm_child(data.root_abspath, SDB_FILE,
+                                            scratch_pool);
+    const char *db_to = svn_wc__adm_child(local_abspath, SDB_FILE,
+                                          scratch_pool);
+    SVN_ERR(svn_io_file_rename(db_from, db_to, scratch_pool));
+  }
+  {
+    SVN_ERR(svn_io_remove_dir2(data.root_abspath, FALSE, NULL, NULL,
+                               scratch_pool));
+  }
+
   SVN_ERR(svn_wc__db_close(db));
 
   return SVN_NO_ERROR;
 }
+

Modified: subversion/branches/performance/subversion/libsvn_wc/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/util.c?rev=993141&r1=993140&r2=993141&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/util.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/util.c Mon Sep  6 20:02:15 2010
@@ -61,41 +61,7 @@ svn_wc__ensure_directory(const char *pat
   else if (kind == svn_node_none)
     {
       /* The dir doesn't exist, and it's our job to change that. */
-      svn_error_t *err = svn_io_dir_make(path, APR_OS_DEFAULT, pool);
-
-      if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
-        {
-          /* Tried to create the dir, and encountered some problem
-             other than non-existence of intermediate dirs.  We can't
-             ensure the desired directory's existence, so just return
-             the error. */
-          return err;
-        }
-      else if (err && APR_STATUS_IS_ENOENT(err->apr_err))
-        /* (redundant conditional and comment) */
-        {
-          /* Okay, so the problem is a missing intermediate
-             directory.  We don't know which one, so we recursively
-             back up one level and try again. */
-          const char *shorter = svn_dirent_dirname(path, pool);
-
-          /* Clear the error. */
-          svn_error_clear(err);
-
-          if (shorter[0] == '\0')
-            {
-              /* A weird and probably rare situation. */
-              return svn_error_create(APR_EGENERAL, NULL,
-                                      _("Unable to make any directories"));
-            }
-          else  /* We have a valid path, so recursively ensure it. */
-            {
-              SVN_ERR(svn_wc__ensure_directory(shorter, pool));
-              return svn_wc__ensure_directory(path, pool);
-            }
-        }
-
-      SVN_ERR(err);
+      SVN_ERR(svn_io_make_dir_recursively(path, pool));
     }
   else  /* No problem, the dir already existed, so just leave. */
     SVN_ERR_ASSERT(kind == svn_node_dir);

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=993141&r1=993140&r2=993141&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql Mon Sep  6 20:02:15 2010
@@ -76,6 +76,124 @@ CREATE UNIQUE INDEX I_LOCAL_ABSPATH ON W
 
 /* ------------------------------------------------------------------------- */
 
+/*
+The BASE_NODE table:
+
+  BASE is what we get from the server.  It is the *absolute* pristine copy.
+  You need to use checkout, update, switch, or commit to alter your view of
+  the repository.
+
+  In the BASE tree, each node corresponds to a particular node-rev in the
+  repository.  It can be a mixed-revision tree.  Each node holds either a
+  copy of the node-rev as it exists in the repository (if presence ==
+  'normal'), or a place-holder (if presence == 'absent' or 'excluded' or
+  'not-present').
+                                                  [Quoted from wc_db.h]
+
+Overview of BASE_NODE columns:
+
+  Indexing columns: (wc_id, local_relpath, parent_relpath)
+
+  (presence)
+
+    - The Node-Rev, Content and Last-Change column groups take one of the
+      states shown in the table below, according to the 'presence':
+
+      'presence'      Meaning       Node-Rev?     Content?  Last-Change?
+      ----------      -----------   -----------   --------  ------------
+      normal      =>  Present       Existing      Yes       Yes
+      incomplete  =>  Incomplete    Existing[*]   No[*]     No
+      absent      =>  Unauthz       Existing      No        No
+      excluded    =>  Unwanted      Existing      No        No
+      not-present =>  Nonexistent   Nonexistent   No        No
+
+    - [*] If presence==incomplete, this node refers to an existing node-rev
+      but its Content is not stored.  This is intended to be a temporary
+      state, during an update.  Node-Rev is sometimes specified as just a
+      revnum.  Sometimes the Content is specified as kind==dir with a depth,
+      but in this case there is no guarantee about rows representing the
+      children.
+
+  Node-Rev columns: (repos_id, repos_relpath, revnum)
+
+    - Always points to the corresponding repository node-rev.
+
+    - Points to an existing node-rev, unless presence==not-present in which
+      case it points to a nonexistent node-rev.
+
+    - ### A comment on 'repos_id' and 'repos_relpath' says they may be null;
+      is this true and wanted?
+
+    - ### A comment on 'revnum' says, "this could be NULL for non-present
+      nodes -- no info"; is this true and wanted?
+
+  Content columns: (kind, properties, depth, target, checksum)
+                    ----  ----------  -----  ------  --------
+                    'dir'    Yes      Yes    null    null
+                'symlink'    Yes      null   Yes     null
+                   'file'    Yes      null   null    Yes
+                'unknown'    null     null   null    null
+
+    - The Content columns take one of the states shown in the table above.
+      If Content is present, a copy of the Node-Rev's content is stored
+      locally according to one of the first three rows in the table above,
+      otherwise kind==unknown and the other columns are null.
+
+    - If kind==dir, the children are represented by the existence of other
+      BASE_NODE rows.  For each immediate child of 'repos_relpath'@'revnum'
+      that is included by 'depth', a BASE_NODE row exists with its
+      'local_relpath' being this node's 'local_relpath' plus the child's
+      basename.  (Rows may also exist for additional children which are
+      outside the scope of 'depth' or do not exist as children of this
+      node-rev in the repository, including 'externals' and paths updated to
+      a revision in which they do exist.)  There is no distinction between
+      depth==immediates and depth==infinity here.
+
+    - If kind==symlink, the target path is contained in 'target'.
+
+    - If kind==file, the content is contained in the Pristine Store,
+      referenced by its SHA-1 checksum 'checksum'.
+
+  Last-Change columns: (changed_rev, changed_date, changed_author)
+
+    - Last-Change info is present iff presence==normal, otherwise null.
+
+    - Specifies the revision in which the content was last changed before
+      Node-Rev, following copies and not counting the copy operation itself
+      as a change.
+
+    - Does not specify the revision in which this node first appeared at
+      the repository path 'repos_relpath', which could be more recent than
+      the last change of this node's content.
+
+    - Includes a copy of the corresponding date and author rev-props.
+
+  Working file status: (translated_size, last_mod_time)
+
+    - Present iff kind==file and node has no WORKING_NODE row, otherwise
+      null.  (If kind==file and node has a WORKING_NODE row, the info is
+      recorded in that row).  ### True?
+
+    - Records the status of the working file on disk, for the purpose of
+      detecting quickly whether that file has been modified.
+
+    - Logically belongs to the ACTUAL_NODE table but is recorded in the
+      BASE_NODE and WORKING_NODE tables instead to avoid the overhead of
+      storing an ACTUAL_NODE row for each unmodified file.
+
+    - Records the actual size and mod-time of the disk file at the time when
+      its content was last determined to be logically unmodified relative to
+      its base, taking account of keywords and EOL style.
+
+  (dav_cache)
+
+  (incomplete_children)
+
+    - Obsolete, unused.
+
+  (file_external)
+*/
+
 CREATE TABLE BASE_NODE (
   /* specifies the location of this node in the local filesystem. wc_id
      implies an absolute path, and local_relpath is relative to that
@@ -83,8 +201,8 @@ CREATE TABLE BASE_NODE (
   wc_id  INTEGER NOT NULL REFERENCES WCROOT (id),
   local_relpath  TEXT NOT NULL,
 
-  /* the repository this node is part of, and the relative path [to its
-     root] within revision "revnum" of that repository.  These may be NULL,
+  /* The repository this node is part of, and the relative path (from its
+     root) within revision "revnum" of that repository.  These may be NULL,
      implying they should be derived from the parent and local_relpath.
      Non-NULL typically indicates a switched node.
 
@@ -137,12 +255,19 @@ CREATE TABLE BASE_NODE (
   /* for kind==symlink, this specifies the target. */
   symlink_target  TEXT,
 
+  /* The mod-time of the working file when it was last determined to be
+     logically unmodified relative to its base, taking account of keywords
+     and EOL style.
+
+     NULL if this node is not a file or if this info has not yet been
+     determined.
+   */
   /* ### Do we need this?  We've currently got various mod time APIs
      ### internal to libsvn_wc, but those might be used in answering some
      ### question which is better answered some other way. */
   last_mod_time  INTEGER,  /* an APR date/time (usec since 1970) */
 
-  /* serialized skel of this node's properties. could be NULL if we
+  /* serialized skel of this node's properties. NULL if we
      have no information about the properties (a non-present node). */
   properties  BLOB,
 
@@ -339,13 +464,20 @@ CREATE TABLE WORKING_NODE (
 
   /* should the node on disk be kept after a schedule delete?
 
-     ### Bert points out that this can disappear once we get centralized 
-     ### with our metadata.  The entire reason for this flag to exist is
-     ### so that the admin area can exist for the commit of a the delete,
+     ### Bert points out that this can disappear once we get to single-db. 
+     ### The entire reason for this flag to exist is
+     ### so that the admin area can exist for the commit of a delete,
      ### and so the post-commit cleanup knows not to actually delete the dir
      ### from disk (which is why the flag is only ever set on the this_dir
-     ### entry in WC-OLD.)  In the New World, we don't need to keep the old
-     ### admin area around, so this flag can disappear. */
+     ### entry in WC-OLD.)  With single-db, we don't need to keep the old
+     ### admin area around, so this flag can disappear.
+     ### neels: In contrast, the --keep-local commandline option will not
+     ### disappear. The user will still be able to do
+     ### 'svn delete --keep-local' and keep the to-be-unversioned paths
+     ### in the file system. It just won't be necessary to remember the
+     ### keep-local-ness here, because we either delete the file system paths
+     ### right away during 'svn delete' or we don't at all. There won't be a
+     ### "second pass" for file system deletion at commit time anymore. */
   keep_local  INTEGER,
 
   PRIMARY KEY (wc_id, local_relpath)
@@ -609,6 +741,217 @@ CREATE TABLE NODE_DATA (
 CREATE INDEX I_NODE_PARENT ON NODE_DATA (wc_id, parent_relpath);
 CREATE INDEX I_NODE_PATH ON NODE_DATA (wc_id, local_relpath);
 
+/* ------------------------------------------------------------------------- */
+
+/* The NODES table describes the way WORKING nodes are layered on top of
+   BASE nodes and on top of other WORKING nodes, due to nested tree structure
+   changes. The layers are modelled using the "op_depth" column.
+
+   Each row in BASE_NODE has an associated row NODE_DATA. Additionally, each
+   row in WORKING_NODE has one or more associated rows in NODE_DATA.
+
+   This table contains full node descriptions for nodes in either the BASE
+   or WORKING trees as described in notes/wc-ng/design. Fields relate
+   both to BASE and WORKING trees, unless documented otherwise.
+
+   ### This table is to be integrated into the SCHEMA statement as soon
+       the experimental status of NODES is lifted.
+   ### This table superseeds NODE_DATA
+
+   For illustration, with a scenario like this:
+
+     # (0)
+     svn rm foo
+     svn cp ^/moo foo   # (1)
+     svn rm foo/bar
+     touch foo/bar
+     svn add foo/bar    # (2)
+
+   , these are the NODES for the path foo/bar (before single-db, the
+   numbering of op_depth is still a bit different):
+
+   (0)  BASE_NODE ----->  NODES (op_depth == 0)
+   (1)                    NODES (op_depth == 1) ( <----_ )
+   (2)                    NODES (op_depth == 2)   <----- WORKING_NODE
+
+   0 is the original data for foo/bar before 'svn rm foo' (if it existed).
+   1 is the data for foo/bar copied in from ^/moo/bar.
+   2 is the to-be-committed data for foo/bar, created by 'svn add foo/bar'.
+
+   An 'svn revert foo/bar' would remove the NODES of (2).
+
+ */
+-- STMT_CREATE_NODES
+CREATE TABLE NODES (
+  /* Working copy location related fields */
+
+  wc_id  INTEGER NOT NULL REFERENCES WCROOT (id),
+  local_relpath  TEXT NOT NULL,
+
+  /* Contains the depth (= number of path segments) of the operation
+     modifying the working copy tree structure. All nodes below the root
+     of the operation (aka operation root, aka oproot) affected by the
+     operation will be assigned the same op_depth.
+
+     op_depth == 0 designates the initial checkout; the BASE tree.
+
+   */
+  op_depth INTEGER NOT NULL,
+
+  /* parent's local_relpath for aggregating children of a given parent.
+     this will be "" if the parent is the wcroot.  Since a wcroot will
+     never have a WORKING node the parent_relpath will never be null,
+     except when op_depth == 0 and the node is a wcroot. */
+  parent_relpath  TEXT,
+
+
+  /* Repository location fields */
+
+  /* When op_depth == 0, these fields refer to the repository location of the
+     BASE node, the location of the initial checkout.
+
+     When op_depth != 0, they indicate where this node was copied/moved from.
+     In this case, the fields are set only on the root of the operation,
+     and are NULL for all children. */
+  repos_id  INTEGER REFERENCES REPOSITORY (id),
+  repos_path  TEXT,
+  revision  INTEGER,
+
+
+  /* WC state fields */
+
+  /* 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.
+
+
+     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:
+
+     Is this node "present" or has it been excluded for some reason?
+     Only allowed values: normal, not-present, incomplete, base-deleted.
+     (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.  */
+  presence  TEXT NOT NULL,
+
+  /* NULL depth means "default" (typically svn_depth_infinity) */
+  /* ### depth on WORKING? seems this is a BASE-only concept. how do
+     ### you do "files" on an added-directory? can't really ignore
+     ### the subdirs! */
+  /* ### maybe a WC-to-WC copy can retain a depth?  */
+  depth  TEXT,
+
+  /* ### JF: For an old-style move, "copyfrom" info stores its source, but a
+     new WC-NG "move" is intended to be a "true rename" so its copyfrom
+     revision is implicit, being in effect (new head - 1) at commit time.
+     For a (new) move, we need to store or deduce the copyfrom local-relpath;
+     perhaps add a column called "moved_from". */
+
+  /* Boolean value, specifying if this node was moved here (rather than just
+     copied). The source of the move is specified in copyfrom_*.  */
+  moved_here  INTEGER,
+
+  /* If the underlying node was moved away (rather than just deleted), this
+     specifies the local_relpath of where the BASE node was moved to.
+     This is set only on the root of a move, and is NULL for all children.
+
+     Note that moved_to never refers to *this* node. It always refers
+     to the "underlying" node, whether that is BASE or a child node
+     implied from a parent's move/copy.  */
+  moved_to  TEXT,
+
+  /* Repository state fields */
+
+  /* the kind of the new node. may be "unknown" if the node is not present. */
+  kind  TEXT NOT NULL,
+
+  /* If this node was moved here or copied here, then the following fields may
+     have information about their source node. See BASE_NODE.changed_* for
+     more information.
+
+     For an added or not-present node, these are null.  */
+  changed_revision  INTEGER,
+  changed_date      INTEGER,  /* an APR date/time (usec since 1970) */
+  changed_author    TEXT,
+
+  /* The SHA-1 checksum of the pristine text, if this node is a file and was
+     moved here or copied here, else NULL. */
+  checksum  TEXT,
+
+  /* serialized skel of this node's properties. NULL if we
+     have no information about the properties (a non-present node). */
+  properties  BLOB,
+
+
+  /* Various cache fields */
+
+  /* The size in bytes of the working file when it had no local text
+     modifications. This means the size of the text when translated from
+     repository-normal format to working copy format with EOL style
+     translated and keywords expanded according to the properties in the
+     "properties" column of this row.
+
+     NULL if this node is not a file or if the size has not (yet) been
+     computed. */
+  translated_size  INTEGER,
+
+  /* The mod-time of the working file when it was last determined to be
+     logically unmodified relative to its base, taking account of keywords
+     and EOL style. This value is used in the change detection heuristic
+     used by the status command.
+
+     NULL if this node is not a file or if this info has not yet been
+     determined.
+   */
+  last_mod_time  INTEGER,  /* an APR date/time (usec since 1970) */
+
+  /* serialized skel of this node's dav-cache.  could be NULL if the
+     node does not have any dav-cache. */
+  dav_cache  BLOB,
+
+  /* for kind==symlink, this specifies the target. */
+  symlink_target  TEXT,
+
+  /* The serialized file external information. */
+  /* ### hack.  hack.  hack.
+     ### This information is already stored in properties, but because the
+     ### current working copy implementation is such a pain, we can't
+     ### readily retrieve it, hence this temporary cache column.
+     ### When it is removed, be sure to remove the extra column from
+     ### the db-tests.
+
+     ### Note: This is only here as a hack, and should *NOT* be added
+     ### to any wc_db APIs.  */
+  file_external  TEXT,
+
+
+  PRIMARY KEY (wc_id, local_relpath, op_depth)
+
+  );
+
+CREATE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath);
+CREATE INDEX I_NODES_PATH ON NODES (wc_id, local_relpath);
+
 
 
 /* ------------------------------------------------------------------------- */
@@ -724,6 +1067,14 @@ PRAGMA user_version = 17;
 
 /* ------------------------------------------------------------------------- */
 
+/* Format 18 involves no schema changes, it moves the property data from files
+   into the database. */
+
+-- STMT_UPGRADE_TO_18
+PRAGMA user_version = 18;
+
+/* ------------------------------------------------------------------------- */
+
 /* Format YYY introduces new handling for conflict information.  */
 -- format: YYY
 

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=993141&r1=993140&r2=993141&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql Mon Sep  6 20:02:15 2010
@@ -77,6 +77,15 @@ insert or replace into base_node (
 values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
         ?15, ?16, ?17);
 
+-- STMT_INSERT_NODE
+insert or replace into nodes (
+  wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
+  revision, presence, depth, kind, changed_revision, changed_date,
+  changed_author, checksum, properties, translated_size, last_mod_time,
+  dav_cache, symlink_target )
+values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
+        ?15, ?16, ?17, ?18, ?19);
+
 -- STMT_INSERT_NODE_DATA
 insert or replace into node_data (
    wc_id, local_relpath, op_depth, parent_relpath, presence, kind,
@@ -94,8 +103,13 @@ values (?1, ?2, ?3, 'incomplete', 'unkno
 -- STMT_INSERT_BASE_NODE_INCOMPLETE_DIR
 insert or ignore into base_node (
   wc_id, local_relpath, repos_id, repos_relpath, parent_relpath, presence,
-  kind, revnum)
-values (?1, ?2, ?3, ?4, ?5, 'incomplete', 'dir', ?6);
+  kind, revnum, depth)
+values (?1, ?2, ?3, ?4, ?5, 'incomplete', 'dir', ?6, ?7);
+
+-- STMT_INSERT_BASE_NODE_DATA_INCOMPLETE_DIR
+insert or ignore into node_data (
+  wc_id, local_relpath, op_depth, parent_relpath, presence, kind, depth)
+values (?1, ?2, 0, ?3, 'incomplete', 'dir', ?4);
 
 -- STMT_INSERT_WORKING_NODE_INCOMPLETE
 INSERT OR IGNORE INTO WORKING_NODE (
@@ -347,8 +361,10 @@ WHERE wc_id = ?1 AND local_relpath = ?2;
 -- STMT_UPDATE_NODE_WORKING_EXCLUDED
 UPDATE NODE_DATA SET presence = 'excluded', depth = NULL
 WHERE wc_id = ?1 AND local_relpath = ?2 AND
-      op_depth IN (SELECT MAX(op_depth) FROM NODE_DATA
-                   WHERE wc_id = ?1 AND local_relpath = ?2);
+      op_depth IN (SELECT op_depth FROM NODE_DATA
+                   WHERE wc_id = ?1 AND local_relpath = ?2
+                   ORDER BY op_depth DECSC
+                   LIMIT 1);
 
 -- STMT_UPDATE_BASE_PRESENCE
 update base_node set presence= ?3
@@ -482,12 +498,24 @@ WHERE wc_id = ?1 AND local_dir_relpath L
 /* translated_size and last_mod_time are not mentioned here because they will
    be tweaked after the working-file is installed.
    ### what to do about file_external?  */
+/* ### NODE_DATA the fields 'presence', 'kind', 'properties', 'changed_rev',
+   'changed_date', 'changed_author', 'depth', 'symlink_target' - but not:
+   'repos_id', 'repos_relpath', 'dav_cache' - will move to the NODE_DATA
+   table, meaning we can't use this query anymore; we need 2, wrapped in a
+   transaction. */
 INSERT OR REPLACE INTO BASE_NODE (
   wc_id, local_relpath, parent_relpath, presence, kind, revnum, changed_rev,
   changed_author, properties, repos_id, repos_relpath, checksum, changed_date,
   depth, symlink_target, dav_cache)
 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16);
 
+-- STMT_APPLY_CHANGES_TO_BASE_NODE_DATA
+INSERT OR REPLACE INTO NODE_DATA (
+  wc_id, local_relpath, op_depth, parent_relpath, presence, kind,
+  changed_revision, changed_author, properties, checksum,
+  changed_date, depth, symlink_target)
+VALUES (?1, ?2, 0, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12);
+
 -- STMT_INSERT_WORKING_NODE_FROM_BASE_NODE
 INSERT INTO WORKING_NODE (
     wc_id, local_relpath, parent_relpath, presence, kind, checksum,
@@ -498,6 +526,25 @@ SELECT wc_id, local_relpath, parent_relp
     symlink_target, last_mod_time FROM BASE_NODE
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_INSERT_WORKING_NODE_DATA_FROM_BASE_NODE_1
+/* ### NODE_DATA  This statement and the statement below (_2) need to
+   be executed in a single transaction */
+INSERT INTO NODE_DATA (
+    wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
+    changed_revision, changed_date, changed_author, depth, symlink_target )
+SELECT wc_id, local_relpath, ?4 as op_depth, parent_relpath, ?3 AS presence,
+       kind, checksum, changed_revision, changed_date,
+       changed_author, depth, symlink_target
+FROM NODE_DATA
+WHERE wc_id = ?1 AND local_relpath = ?2 and op_depth = 0;
+
+-- STMT_INSERT_WORKING_NODE_DATA_FROM_BASE_NODE_2
+INSERT INTO WORKING_NODE (
+    wc_id, local_relpath, parent_relpath, translated_size, last_mod_time )
+SELECT wc_id, local_relpath, parent_relpath, translated_size, last_mod_time
+FROM BASE_NODE
+WHERE wc_id = ?1 AND local_relpath = ?2;
+
 -- STMT_INSERT_WORKING_NODE_NORMAL_FROM_BASE_NODE
 INSERT INTO WORKING_NODE (
     wc_id, local_relpath, parent_relpath, presence, kind, checksum,
@@ -510,6 +557,32 @@ SELECT wc_id, local_relpath, parent_relp
     repos_relpath, revnum FROM BASE_NODE
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+
+-- STMT_INSERT_WORKING_NODE_DATA_NORMAL_FROM_BASE_NODE_1
+INSERT INTO NODE_DATA (
+    wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
+    changed_revision, changed_date, changed_author, depth, symlink_target,
+    properties, original_repos_id, original_repos_path, original_revision )
+SELECT n.wc_id, n.local_relpath, ?3 as op_depth, n.parent_relpath, 'normal',
+    n.kind,
+    n.checksum, n.changed_revision, n.changed_date, n.changed_author, n.depth,
+    n.symlink_target, n.properties, b.repos_id as original_repos_id,
+    b.repos_relpath as original_repos_relpath, b.revnum as original_revision
+FROM BASE_NODE as b INNER JOIN NODE_DATA as n
+     ON b.wc_id = n.wc_id
+     AND b.local_relpath = n.local_relpath
+     AND n.op_depth = 0
+WHERE n.wc_id = ?1 AND n.local_relpath = ?2;
+
+
+-- STMT_INSERT_WORKING_NODE_DATA_NORMAL_FROM_BASE_NODE_2
+INSERT INTO WORKING_NODE (
+    wc_id, local_relpath, parent_relpath, translated_size, last_mod_time )
+SELECT wc_id, local_relpath, parent_relpath, translated_size, last_mod_time
+FROM BASE_NODE
+WHERE wc_id = ?1 AND local_relpath = ?2;
+
+
 -- STMT_INSERT_WORKING_NODE_NOT_PRESENT_FROM_BASE_NODE
 INSERT INTO WORKING_NODE (
     wc_id, local_relpath, parent_relpath, presence, kind, changed_rev,
@@ -520,6 +593,28 @@ SELECT wc_id, local_relpath, parent_relp
     repos_relpath, revnum FROM BASE_NODE
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+
+-- STMT_INSERT_WORKING_NODE_DATA_NOT_PRESENT_FROM_BASE_NODE_1
+INSERT INTO NODE_DATA (
+    wc_id, local_relpath, op_depth, parent_relpath, presence, kind,
+    changed_revision, changed_date, changed_author, original_repos_id,
+    original_repos_path, original_revision )
+SELECT wc_id, local_relpath, ?3 as op_depth, parent_relpath, 'not-present',
+       kind, changed_rev, changed_date, changed_author, repos_id,
+       repos_relpath, revnum
+FROM BASE_NODE as b INNER JOIN NODE_DATA as n
+     ON b.local_relpath = n.local_relpath
+     AND b.wc_id = n.wc_id
+     AND n.op_depth = 0
+WHERE n.wc_id = ?1 AND n.local_relpath = ?2;
+
+
+-- STMT_INSERT_WORKING_NODE_DATA_NOT_PRESENT_FROM_BASE_NODE_2
+INSERT INTO WORKING_NODE (
+    wc_id, local_relpath, parent_relpath)
+VALUES (?1, ?2, ?3);
+
+
 -- ### the statement below should be setting copyfrom_revision!
 -- STMT_UPDATE_COPYFROM
 UPDATE WORKING_NODE set copyfrom_repos_id = ?3, copyfrom_repos_path = ?4
@@ -537,6 +632,9 @@ SELECT 0 FROM BASE_NODE WHERE wc_id = ?1
 UNION
 SELECT 1 FROM WORKING_NODE WHERE wc_id = ?1 AND local_relpath = ?2;
 
+
+/* ### Why can't this query not just use the BASE repository
+   location values, instead of taking 3 additional parameters?! */
 -- STMT_INSERT_WORKING_NODE_COPY_FROM_BASE
 INSERT OR REPLACE INTO WORKING_NODE (
     wc_id, local_relpath, parent_relpath, presence, kind, checksum,
@@ -549,6 +647,31 @@ SELECT wc_id, ?3 AS local_relpath, ?4 AS
     ?7 AS copyfrom_repos_path, ?8 AS copyfrom_revnum FROM BASE_NODE
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+
+-- STMT_INSERT_WORKING_NODE_DATA_COPY_FROM_BASE_1
+INSERT OR REPLACE INTO NODE_DATA (
+    wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
+    changed_revision, changed_date, changed_author, depth, symlink_target,
+    properties, original_repos_id, original_repos_path, original_revision )
+SELECT n.wc_id, ?3 AS local_relpath, ?4 AS op_depth, ?5 AS parent_relpath,
+       ?6 AS presence, n.kind, n.checksum, n.changed_revision, n.changed_date,
+       n.changed_author, n.depth, n.symlink_target, n.properties,
+       ?7 AS original_repos_id, ?8 AS original_repos_path,
+       ?9 AS original_revision
+FROM BASE_NODE AS b INNER JOIN NODE_DATA AS n
+     ON b.wc_id = n.wc_id
+     AND b.local_relpath = n.local_relpath
+     AND n.op_depth = 0
+WHERE n.wc_id = ?1 AND n.local_relpath = ?2;
+
+-- STMT_INSERT_WORKING_NODE_DATA_COPY_FROM_BASE_2
+INSERT OR REPLACE INTO WORKING_NODE (
+   wc_id, local_relpath, parent_relpath, translated_size, last_mod_time )
+SELECT wc_id, local_relpath, parent_relpath, translated_size, last_mod_time
+FROM BASE_NODE
+WHERE wc_id = ?1 AND local_relpath = ?2;
+
+
 -- STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING
 INSERT OR REPLACE INTO WORKING_NODE (
     wc_id, local_relpath, parent_relpath, presence, kind, checksum,
@@ -561,6 +684,34 @@ SELECT wc_id, ?3 AS local_relpath, ?4 AS
     ?7 AS copyfrom_repos_path, ?8 AS copyfrom_revnum FROM WORKING_NODE
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+
+-- STMT_INSERT_WORKING_NODE_DATA_COPY_FROM_WORKING_1
+INSERT OR REPLACE INTO NODE_DATA (
+    wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
+    changed_revision, changed_date, changed_author, depth, symlink_target,
+    properties, original_repos_id, original_repos_path, original_revision )
+SELECT n.wc_id, ?3 AS local_relpath, ?4 AS op_depth, ?5 AS parent_relpath,
+       ?6 AS presence, n.kind, n.checksum, n.changed_revision, n.changed_date,
+       n.changed_author, n.depth, n.symlink_target, n.properties,
+       ?7 AS original_repos_id, ?8 AS original_repos_path,
+       ?9 as original_revision
+FROM WORKING_NODE AS w INNER JOIN NODE_DATA AS n
+     ON w.wc_id = n.wc_id
+     AND w.local_relpath = n.local_relpath
+WHERE w.wc_id = ?1 AND w.local_relpath = ?2
+ORDER BY n.op_depth
+LIMIT 1;
+
+-- STMT_INSERT_WORKING_NODE_DATA_COPY_FROM_WORKING_2
+/* ### there's probably no need to set translated_size and last_mod_time,
+   they are probably set again later (after re-expanding the base) */
+INSERT OR REPLACE INTO WORKING_NODE (
+    wc_id, local_relpath, parent_relpath, translated_size, last_mod_time )
+SELECT wc_id, ?3 as local_relpath, ?4 as parent_relpath,
+       translated_size, last_mod_time
+FROM WORKING_NODE
+WHERE wc_id = ?1 AND local_relpath = ?2;
+
 -- STMT_INSERT_ACTUAL_NODE_FROM_ACTUAL_NODE
 INSERT OR REPLACE INTO ACTUAL_NODE (
      wc_id, local_relpath, parent_relpath, properties,
@@ -597,6 +748,19 @@ insert or replace into base_node (
 values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
   ?15, ?16);
 
+-- STMT_INSERT_BASE_NODE_DATA_FOR_ENTRY_1
+insert or replace into base_node (
+  wc_id, local_relpath, parent_relpath, repos_id, repos_relpath, revnum,
+  translated_size, last_mod_time )
+values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);
+
+-- STMT_INSERT_BASE_NODE_DATA_FOR_ENTRY_2
+/* The BASE tree has a fixed op_depth '0' */
+insert or replace into node_data (
+  wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
+  changed_revision, changed_date, changed_author, depth, properties )
+values (?1, ?2, 0, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11);
+
 -- STMT_INSERT_WORKING_NODE
 insert or replace into working_node (
   wc_id, local_relpath, parent_relpath, presence, kind,
@@ -607,6 +771,22 @@ insert or replace into working_node (
 values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
   ?15, ?16, ?17, ?18, ?19, ?20);
 
+-- STMT_INSERT_WORKING_NODE_DATA_1
+insert or replace into node_data (
+  wc_id, local_relpath, op_depth, parent_relpath, presence, kind,
+  original_repos_id, original_repos_path, original_revision, checksum,
+  changed_revision, changed_date, changed_author, depth, properties,
+  symlink_target )
+values (?1,  ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9,
+        ?10, ?11, ?12, ?13, ?14, ?15, ?16 );
+
+-- STMT_INSERT_WORKING_NODE_DATA_2
+insert or replace into working_node (
+  wc_id, local_relpath, parent_relpath, moved_here, moved_to, translated_size,
+  last_mod_time, keep_local )
+values (?1,  ?2, ?3, ?4, ?5, ?6, ?7, ?8 );
+
+
 -- STMT_INSERT_ACTUAL_NODE
 insert or replace into actual_node (
   wc_id, local_relpath, parent_relpath, properties, conflict_old,
@@ -657,97 +837,18 @@ values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, 
 update actual_node set tree_conflict_data = null;
 
 -- STMT_SELECT_ALL_FILES
+/* Should this select on wc_id as well? */
 SELECT local_relpath FROM BASE_NODE
-WHERE kind = 'file'
+WHERE kind = 'file' AND parent_relpath = ?1
 UNION
 SELECT local_relpath FROM WORKING_NODE
-WHERE kind = 'file';
+WHERE kind = 'file' AND parent_relpath = ?1;
 
 -- STMT_PLAN_PROP_UPGRADE
 SELECT 0, presence, wc_id FROM BASE_NODE WHERE local_relpath = ?1
 UNION ALL
 SELECT 1, presence, wc_id FROM WORKING_NODE WHERE local_relpath = ?1;
 
--- STMT_ATTACH_WCROOT_DB
-/* ?1 is the path to the WC-root DB file to attach. */
-ATTACH ?1 AS root;
-
--- STMT_COPY_BASE_NODE_TABLE_TO_WCROOT_DB
-/* Copy BASE_NODE to WC-root DB: first the '' row, then the rest. */
-/* ?1 is the wc_relpath of the subdirectory that we're processing. */
-/* ?2 is the wc_relpath of the parent of the subdir we're processing. */
-INSERT INTO root.BASE_NODE (
-    wc_id, local_relpath, repos_id, repos_relpath, parent_relpath,
-    presence,
-    revnum, kind, checksum, translated_size, changed_rev, changed_date,
-    changed_author, depth, last_mod_time, properties )
-SELECT wc_id, ?1,
-    repos_id, repos_relpath, ?2 AS parent_relpath, presence,
-    revnum, kind, checksum, translated_size, changed_rev, changed_date,
-    changed_author, depth, last_mod_time, properties FROM BASE_NODE
-WHERE local_relpath = '';
-INSERT INTO root.BASE_NODE (
-    wc_id, local_relpath, repos_id, repos_relpath, parent_relpath,
-    presence,
-    revnum, kind, checksum, translated_size, changed_rev, changed_date,
-    changed_author, depth, last_mod_time, properties )
-SELECT wc_id, ?1 || '/' || local_relpath,
-    repos_id, repos_relpath, ?1 AS parent_relpath, presence,
-    revnum, kind, checksum, translated_size, changed_rev, changed_date,
-    changed_author, depth, last_mod_time, properties FROM BASE_NODE
-WHERE local_relpath != '';
-
--- STMT_COPY_WORKING_NODE_TABLE_TO_WCROOT_DB
-INSERT INTO root.WORKING_NODE (
-    wc_id, local_relpath, parent_relpath, presence, kind, checksum,
-    translated_size, changed_rev, changed_date, changed_author, depth,
-    symlink_target, last_mod_time, properties, copyfrom_repos_id,
-    copyfrom_repos_path, copyfrom_revnum )
-SELECT wc_id, ?1, ?2 AS parent_relpath,
-    presence, kind, checksum,
-    translated_size, changed_rev, changed_date, changed_author, depth,
-    symlink_target, last_mod_time, properties, copyfrom_repos_id,
-    copyfrom_repos_path, copyfrom_revnum FROM WORKING_NODE
-WHERE local_relpath = '';
-INSERT INTO root.WORKING_NODE (
-    wc_id, local_relpath, parent_relpath, presence, kind, checksum,
-    translated_size, changed_rev, changed_date, changed_author, depth,
-    symlink_target, last_mod_time, properties, copyfrom_repos_id,
-    copyfrom_repos_path, copyfrom_revnum )
-SELECT wc_id, ?1 || '/' || local_relpath, ?1 AS parent_relpath,
-    presence, kind, checksum,
-    translated_size, changed_rev, changed_date, changed_author, depth,
-    symlink_target, last_mod_time, properties, copyfrom_repos_id,
-    copyfrom_repos_path, copyfrom_revnum FROM WORKING_NODE
-WHERE local_relpath != '';
-/* TODO - maybe: WHERE kind != 'subdir'; */
-
--- STMT_COPY_ACTUAL_NODE_TABLE_TO_WCROOT_DB
-INSERT INTO root.ACTUAL_NODE (
-    wc_id, local_relpath, parent_relpath, properties,
-    conflict_old, conflict_new, conflict_working,
-    prop_reject, changelist, text_mod, tree_conflict_data )
-SELECT wc_id, ?1, ?2 AS parent_relpath, properties,
-     conflict_old, conflict_new, conflict_working,
-     prop_reject, changelist, text_mod, tree_conflict_data FROM ACTUAL_NODE
-WHERE local_relpath = '';
-INSERT INTO root.ACTUAL_NODE (
-    wc_id, local_relpath, parent_relpath, properties,
-    conflict_old, conflict_new, conflict_working,
-    prop_reject, changelist, text_mod, tree_conflict_data )
-SELECT wc_id, ?1 || '/' || local_relpath, ?1 AS parent_relpath, properties,
-     conflict_old, conflict_new, conflict_working,
-     prop_reject, changelist, text_mod, tree_conflict_data FROM ACTUAL_NODE
-WHERE local_relpath != '';
-
--- STMT_COPY_LOCK_TABLE_TO_WCROOT_DB
-INSERT INTO root.LOCK
-SELECT * FROM LOCK;
-
--- STMT_COPY_PRISTINE_TABLE_TO_WCROOT_DB
-INSERT INTO root.PRISTINE
-SELECT * FROM PRISTINE;
-
 
 /* ------------------------------------------------------------------------- */
 

Modified: subversion/branches/performance/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc.h?rev=993141&r1=993140&r2=993141&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc.h Mon Sep  6 20:02:15 2010
@@ -50,7 +50,6 @@ extern "C" {
                                                file */
 
 
-
 
 /* We can handle this format or anything lower, and we (should) error
  * on anything higher.
@@ -72,7 +71,8 @@ extern "C" {
  * == 1.3.x shipped with format 4
  *
  * The change from 4 to 5 was the addition of support for replacing files
- * with history.
+ * with history (the "revert base"). This was introduced in 1.4.0, but
+ # buggy until 1.4.6.
  *
  * The change from 5 to 6 was the introduction of caching of property
  * modification state and certain properties in the entries file.
@@ -119,12 +119,27 @@ extern "C" {
  * bases into the Pristine Store (the PRISTINE table and '.svn/pristine'
  * dir), and removed the '/.svn/text-base' dir.
  *
+ * The change from 17 to 18 moved the properties from separate files in the
+ * props and prop-base directory (and .svn for the dir itself) into the
+ * wc.db file, and then removes the props and prop-base dir.
+ *
+ * The change from 18 to 19 introduces the 'single DB' per working copy.
+ * All metadata is held in a single '.svn/wc.db' in the root directory of
+ * the working copy.
+ *
  * == 1.7.x shipped with format ???
  *
  * Please document any further format changes here.
  */
 
-#define SVN_WC__VERSION 17
+#define SVN_WC__VERSION 19
+
+/* ### SVN_WC__SINGLE_DB and SINGLE_DB were both used in development
+   ### and will both disappear before the final 1.7 release. */
+#if SVN_WC__VERSION >= 19
+#define SVN_WC__SINGLE_DB
+#define SINGLE_DB
+#endif
 
 
 /* Formats <= this have no concept of "revert text-base/props".  */
@@ -294,12 +309,6 @@ struct svn_wc_traversal_info_t
 #define SVN_WC__ADM_FORMAT              "format"
 #define SVN_WC__ADM_ENTRIES             "entries"
 #define SVN_WC__ADM_TMP                 "tmp"
-#define SVN_WC__ADM_TEXT_BASE           "text-base"
-#define SVN_WC__ADM_PROPS               "props"
-#define SVN_WC__ADM_PROP_BASE           "prop-base"
-#define SVN_WC__ADM_DIR_PROPS           "dir-props"
-#define SVN_WC__ADM_DIR_PROP_BASE       "dir-prop-base"
-#define SVN_WC__ADM_DIR_PROP_REVERT     "dir-prop-revert"
 #define SVN_WC__ADM_PRISTINE            "pristine"
 #define SVN_WC__ADM_NONEXISTENT_PATH    "nonexistent-path"
 
@@ -470,17 +479,21 @@ svn_wc__walker_default_error_handler(con
  * @c svn_depth_infinity, @c svn_depth_empty, @c svn_depth_files,
  * @c svn_depth_immediates, or @c svn_depth_unknown.
  *
+ * If @a read_base is TRUE, always read the depth data from BASE_NODE
+ * instead of from WORKING when that exists.
+ *
  * Allocations are done in POOL.
  */
 svn_error_t *
 svn_wc__ambient_depth_filter_editor(const svn_delta_editor_t **editor,
                                     void **edit_baton,
-                                    const svn_delta_editor_t *wrapped_editor,
-                                    void *wrapped_edit_baton,
+                                    svn_wc__db_t *db,
                                     const char *anchor_abspath,
                                     const char *target,
-                                    svn_wc__db_t *db,
-                                    apr_pool_t *pool);
+                                    svn_boolean_t read_base,
+                                    const svn_delta_editor_t *wrapped_editor,
+                                    void *wrapped_edit_baton,
+                                    apr_pool_t *result_pool);
 
 
 /* Similar to svn_wc_conflicted_p3(), but with a wc_db parameter in place of
@@ -609,6 +622,18 @@ svn_wc__internal_node_get_schedule(svn_w
                                    const char *local_abspath,
                                    apr_pool_t *scratch_pool);
 
+/* Internal version of svn_wc__node_get_copyfrom_info */
+svn_error_t *
+svn_wc__internal_get_copyfrom_info(const char **copyfrom_root_url,
+                                   const char **copyfrom_repos_relpath,
+                                   const char **copyfrom_url,
+                                   svn_revnum_t *copyfrom_rev,
+                                   svn_boolean_t *is_copy_target,
+                                   svn_wc__db_t *db,
+                                   const char *local_abspath,
+                                   apr_pool_t *result_pool,
+                                   apr_pool_t *scratch_pool);
+
 
 
 /* Upgrade the wc sqlite database given in SDB for the wc located at
@@ -645,6 +670,15 @@ svn_wc__check_wc_root(svn_boolean_t *wc_
                       const char *local_abspath,
                       apr_pool_t *scratch_pool);
 
+/* Ensure LOCAL_ABSPATH is still locked in DB.  Returns the error
+ * SVN_ERR_WC_NOT_LOCKED if this is not the case.
+ */
+svn_error_t *
+svn_wc__write_check(svn_wc__db_t *db,
+                    const char *local_abspath,
+                    apr_pool_t *scratch_pool);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */