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. */