You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2009/12/11 21:36:46 UTC

svn commit: r889804 - in /subversion/branches/issue-3550-dev/subversion/libsvn_fs_base: bdb/changes-table.c bdb/changes-table.h bdb/txn-table.c bdb/txn-table.h fs.c fs.h

Author: cmpilato
Date: Fri Dec 11 20:36:45 2009
New Revision: 889804

URL: http://svn.apache.org/viewvc?rev=889804&view=rev
Log:
On the 'issue-3550-dev' branch, add the logic to handle the upgrade of
a pre-existing repository to the format that supports the
feature-in-progress.

* subversion/libsvn_fs_base/fs.h
  (SVN_FS_BASE__FORMAT_NUMBER): Bump to '5'.
  (SVN_FS_BASE__MIN_CHANGES_INFO_FORMAT): New.

* subversion/libsvn_fs_base/fs.c
  (open_databases): Update call to svn_fs_bdb__open_changes_table().
  (txn_body_init_next_changes_key): New.
  (open_unopened_fs_for_upgrade): New helper.
  (base_upgrade): Handle upgrading from a version that lacks support
    for arbitrary changes table keys (and related goodies).

* subversion/libsvn_fs_base/bdb/changes-table.h
  (svn_fs_bdb__open_changes_table): Now accept a 'version' parameter.
  (svn_fs_bdb__changes_init_next_key): New function.

* subversion/libsvn_fs_base/bdb/changes-table.c
  (svn_fs_bdb__open_changes_table): Now accept a 'version' parameter,
    and use it to optionally init the 'next-key' row.
  (svn_fs_bdb__changes_init_next_key): New function.

* subversion/libsvn_fs_base/bdb/txn-table.h
  (svn_fs_bdb__get_next_txn_id): New function.

* subversion/libsvn_fs_base/bdb/txn-table.c
  (svn_fs_bdb__get_next_txn_id): New helper function, cored from ...
  (allocate_txn_id): ... this one, which now employs it.


Modified:
    subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.c
    subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.h
    subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.c
    subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.h
    subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.c
    subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.h

Modified: subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.c?rev=889804&r1=889803&r2=889804&view=diff
==============================================================================
--- subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.c (original)
+++ subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.c Fri Dec 11 20:36:45 2009
@@ -32,6 +32,7 @@
 #include "../err.h"
 #include "../trail.h"
 #include "../id.h"
+#include "../key-gen.h"
 #include "../util/fs_skels.h"
 #include "../../libsvn_fs/fs-loader.h"
 #include "bdb-err.h"
@@ -47,6 +48,7 @@
 int
 svn_fs_bdb__open_changes_table(DB **changes_p,
                                DB_ENV *env,
+                               int version,
                                svn_boolean_t create)
 {
   const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
@@ -63,11 +65,57 @@
                           "changes", 0, DB_BTREE,
                           open_flags, 0666));
 
+  /* If we're creating this table and using a filesystem format that
+     supports the arbitrary changes table keys, init our 'next-key' item. */
+  if (create && (version >= SVN_FS_BASE__MIN_CHANGES_INFO_FORMAT))
+    {
+      DBT key, value;
+      BDB_ERR(changes->put(changes, 0,
+                           svn_fs_base__str_to_dbt(&key, NEXT_KEY_KEY),
+                           svn_fs_base__str_to_dbt(&value, "0"), 0));
+    }
+
   *changes_p = changes;
   return 0;
 }
 
 
+svn_error_t *
+svn_fs_bdb__changes_init_next_key(svn_fs_t *fs,
+                                  const char *initial_value,
+                                  trail_t *trail,
+                                  apr_pool_t *pool)
+{
+  base_fs_data_t *bfd = fs->fsap_data;
+  DBT key, value;
+  int db_err;
+
+  svn_fs_base__trail_debug(trail, "changes", "get");
+  db_err = bfd->changes->get(bfd->changes, trail->db_txn,
+                             svn_fs_base__str_to_dbt(&key, NEXT_KEY_KEY),
+                             svn_fs_base__result_dbt(&value), 0);
+  svn_fs_base__track_dbt(&value, pool);
+
+  /* A not-found error is ideal -- let's add our 'next-key' row and
+     get outta here.  */
+  if (db_err == DB_NOTFOUND)
+    {
+      return BDB_WRAP(fs, _("initializing next changes key"),
+                      (bfd->changes->put(
+                          bfd->changes, trail->db_txn,
+                          svn_fs_base__str_to_dbt(&key, NEXT_KEY_KEY),
+                          svn_fs_base__str_to_dbt(&value, initial_value), 0)));
+    }
+
+  /* If there was some other error, though, we'll propogate that up. */
+  SVN_ERR(BDB_WRAP(fs, "fetching next changes key", db_err));
+  
+  /* If there wasn't an error above, that, too, is a problem. */
+  return svn_error_create(SVN_ERR_FS_CORRUPT, 0,
+                          _("Found unexpected 'next-key' in changes table"));
+}
+
+
 
 /*** Storing and retrieving changes.  ***/
 

Modified: subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.h?rev=889804&r1=889803&r2=889804&view=diff
==============================================================================
--- subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.h (original)
+++ subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/changes-table.h Fri Dec 11 20:36:45 2009
@@ -38,12 +38,23 @@
 
 /* Open a `changes' table in ENV.  If CREATE is non-zero, create one
    if it doesn't exist.  Set *CHANGES_P to the new table.  Return a
-   Berkeley DB error code.  */
+   Berkeley DB error code.  VERSION is the filesystem format version
+   for the filesystem in which this `changes' table is being used.  */
 int svn_fs_bdb__open_changes_table(DB **changes_p,
                                    DB_ENV *env,
+                                   int version,
                                    svn_boolean_t create);
 
 
+
+/* Create a 'next-key' key in the `changes' table with value
+   INITIAL_VALUE as part of TRAIL.  Return SVN_ERR_FS_CORRUPT if the
+   'next-key' row already exists in the `changes' table.  */
+svn_error_t *svn_fs_bdb__changes_init_next_key(svn_fs_t *fs,
+                                               const char *initial_value,
+                                               trail_t *trail,
+                                               apr_pool_t *pool);
+
 /* Add CHANGE as a record to the `changes' table in FS as part of
    TRAIL, keyed on KEY.
 

Modified: subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.c?rev=889804&r1=889803&r2=889804&view=diff
==============================================================================
--- subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.c (original)
+++ subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.c Fri Dec 11 20:36:45 2009
@@ -102,6 +102,30 @@
 }
 
 
+svn_error_t *
+svn_fs_bdb__get_next_txn_id(const char **next_txn_id,
+                            svn_fs_t *fs,
+                            trail_t *trail,
+                            apr_pool_t *pool)
+{
+  base_fs_data_t *bfd = fs->fsap_data;
+  DBT query, result;
+
+  svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY);
+
+  /* Get the current value associated with the `next-key' key in the table.  */
+  svn_fs_base__trail_debug(trail, "transactions", "get");
+  SVN_ERR(BDB_WRAP(fs, "getting next available transaction ID ('next-key')",
+                   bfd->transactions->get(bfd->transactions, trail->db_txn,
+                                          &query,
+                                          svn_fs_base__result_dbt(&result),
+                                          0)));
+  svn_fs_base__track_dbt(&result, trail->pool);
+  *next_txn_id = apr_pstrmemdup(pool, result.data, result.size);
+  return SVN_NO_ERROR;
+}
+
+
 /* Allocate a Subversion transaction ID in FS, as part of TRAIL.  Set
    *ID_P to the new transaction ID, allocated in POOL.  */
 static svn_error_t *
@@ -116,23 +140,11 @@
   char next_key[MAX_KEY_SIZE];
   int db_err;
 
-  svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY);
-
-  /* Get the current value associated with the `next-key' key in the table.  */
-  svn_fs_base__trail_debug(trail, "transactions", "get");
-  SVN_ERR(BDB_WRAP(fs, "allocating new transaction ID (getting 'next-key')",
-                   bfd->transactions->get(bfd->transactions, trail->db_txn,
-                                          &query,
-                                          svn_fs_base__result_dbt(&result),
-                                          0)));
-  svn_fs_base__track_dbt(&result, pool);
-
-  /* Set our return value. */
-  *id_p = apr_pstrmemdup(pool, result.data, result.size);
+  SVN_ERR(svn_fs_bdb__get_next_txn_id(id_p, fs, trail, pool));
 
   /* Bump to future key. */
-  len = result.size;
-  svn_fs_base__next_key(result.data, &len, next_key);
+  len = strlen(*id_p);
+  svn_fs_base__next_key(*id_p, &len, next_key);
   svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY);
   svn_fs_base__str_to_dbt(&result, next_key);
   svn_fs_base__trail_debug(trail, "transactions", "put");

Modified: subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.h?rev=889804&r1=889803&r2=889804&view=diff
==============================================================================
--- subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.h (original)
+++ subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/bdb/txn-table.h Fri Dec 11 20:36:45 2009
@@ -41,6 +41,13 @@
                                         svn_boolean_t create);
 
 
+/* Set *NEXT_TXN_ID to the value of the next available transaction ID
+   in FS, allocated from POOL.  Do this as part of TRAIL.  */
+svn_error_t *svn_fs_bdb__get_next_txn_id(const char **next_txn_id,
+                                         svn_fs_t *fs,
+                                         trail_t *trail,
+                                         apr_pool_t *pool);
+
 /* Create a new transaction in FS as part of TRAIL, with an initial
    root and base root ID of ROOT_ID.  Set *TXN_NAME_P to the name of the
    new transaction, allocated in POOL.  */

Modified: subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.c?rev=889804&r1=889803&r2=889804&view=diff
==============================================================================
--- subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.c Fri Dec 11 20:36:45 2009
@@ -42,6 +42,7 @@
 #include "tree.h"
 #include "id.h"
 #include "lock.h"
+#include "trail.h"
 #define SVN_WANT_BDB
 #include "svn_private_config.h"
 
@@ -584,6 +585,7 @@
                         : "opening 'changes' table"),
                    svn_fs_bdb__open_changes_table(&bfd->changes,
                                                   bfd->bdb->env,
+                                                  format,
                                                   create)));
   SVN_ERR(BDB_WRAP(fs, (create
                         ? "creating 'representations' table"
@@ -820,6 +822,43 @@
   return SVN_NO_ERROR;
 }
 
+/* Trail body function for initializing the `changes' table's 'next-key' 
+   row from the value of the same row in the `transaction' table. */
+static svn_error_t *
+txn_body_init_next_changes_key(void *baton, trail_t *trail)
+{
+  const char *next_txn_id;
+  SVN_ERR(svn_fs_bdb__get_next_txn_id(&next_txn_id, trail->fs,
+                                      trail, trail->pool));
+  return svn_fs_bdb__changes_init_next_key(trail->fs, next_txn_id, 
+                                           trail, trail->pool);
+}
+
+/* Open FS with COMMON_POOL and a subpool of POOL, and set *FS_POOL to
+   to that subpool, iff *FS_POOL is NULL (which indicates the the FS
+   hasn't already been opened).  Otherwise, do nothing.
+   
+   NOTE: By using base_open() here instead of open_databases(), we
+   will end up re-reading the already-updated format file.  For now,
+   though, it's better to use the existing encapsulation of "opening
+   the filesystem" rather than duplicating (or worse, partially
+   duplicating) that logic here.  */
+static svn_error_t *
+open_unopened_fs_for_upgrade(apr_pool_t **fs_pool,
+                             svn_fs_t *fs,
+                             const char *path,
+                             apr_pool_t *pool,
+                             apr_pool_t *common_pool)
+{
+  if (! *fs_pool)
+    {
+      *fs_pool = svn_pool_create(pool);
+      SVN_ERR(base_open(fs, path, *fs_pool, common_pool));
+    }
+  return SVN_NO_ERROR;
+}
+  
+
 static svn_error_t *
 base_upgrade(svn_fs_t *fs, const char *path, apr_pool_t *pool,
              apr_pool_t *common_pool)
@@ -827,6 +866,7 @@
   const char *version_file_path;
   int old_format_number;
   svn_error_t *err;
+  apr_pool_t *fs_pool = NULL;
 
   version_file_path = svn_dirent_join(path, FORMAT_FILE, pool);
 
@@ -845,32 +885,41 @@
   SVN_ERR(svn_io_write_version_file(version_file_path,
                                     SVN_FS_BASE__FORMAT_NUMBER, pool));
 
-  /* Check and see if we need to record the "bump" revision. */
+  /* Maybe record the "bump" revision. */
   if (old_format_number < SVN_FS_BASE__MIN_FORWARD_DELTAS_FORMAT)
     {
-      apr_pool_t *subpool = svn_pool_create(pool);
       svn_revnum_t youngest_rev;
       const char *value;
-
-      /* Open the filesystem in a subpool (so we can control its
-         closure) and do our fiddling.
-
-         NOTE: By using base_open() here instead of open_databases(),
-         we will end up re-reading the format file that we just wrote.
-         But it's better to use the existing encapsulation of "opening
-         the filesystem" rather than duplicating (or worse, partially
-         duplicating) that logic here.  */
-      SVN_ERR(base_open(fs, path, subpool, common_pool));
+      
+      /* Open the FS if it isn't already open. */
+      SVN_ERR(open_unopened_fs_for_upgrade(&fs_pool, fs, path, pool,
+                                           common_pool));
 
       /* Fetch the youngest rev, and record it */
-      SVN_ERR(svn_fs_base__youngest_rev(&youngest_rev, fs, subpool));
-      value = apr_psprintf(subpool, "%ld", youngest_rev);
+      SVN_ERR(svn_fs_base__youngest_rev(&youngest_rev, fs, fs_pool));
+      value = apr_psprintf(fs_pool, "%ld", youngest_rev);
       SVN_ERR(svn_fs_base__miscellaneous_set
               (fs, SVN_FS_BASE__MISC_FORWARD_DELTA_UPGRADE,
-               value, subpool));
-      svn_pool_destroy(subpool);
+               value, fs_pool));
     }
 
+  /* Maybe initialize the next-available `changes' key (to match the
+     next-available `transactions' key). */
+  if (old_format_number < SVN_FS_BASE__MIN_CHANGES_INFO_FORMAT)
+    {
+      /* Open the FS if it isn't already open. */
+      SVN_ERR(open_unopened_fs_for_upgrade(&fs_pool, fs, path, pool,
+                                           common_pool));
+
+      /* Init the next changes key. */
+      SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_init_next_changes_key,
+                                     NULL, TRUE, pool)); 
+   }
+
+  /* If we opened the FS somewhere above, close the pool that holds it. */
+  if (fs_pool)
+    svn_pool_destroy(fs_pool);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.h?rev=889804&r1=889803&r2=889804&view=diff
==============================================================================
--- subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.h (original)
+++ subversion/branches/issue-3550-dev/subversion/libsvn_fs_base/fs.h Fri Dec 11 20:36:45 2009
@@ -44,7 +44,11 @@
    ends.  See the SVN_FS_BASE__MIN_*_FORMAT defines to get a sense of
    what changes and features were added in which versions of this
    back-end's format.  */
-#define SVN_FS_BASE__FORMAT_NUMBER                4
+#define SVN_FS_BASE__FORMAT_NUMBER                5
+
+/* Minimum format number that supports arbitrary changes table keys
+   (and prefolding, etc.) */
+#define SVN_FS_BASE__MIN_CHANGES_INFO_FORMAT      5
 
 /* Minimum format number that supports representation sharing.  This
    also brings in the support for storing SHA1 checksums.   */