Well, it turns out that BDB 4.1 _doesn't_ hang in
fs-test:undelrify_deltify, it's just incredibly slow. I suspect this is
because we're reading file contents 10 bytes at a time, but I have no
idea why it's so much slower than BDB 4.0.
Here's a second version of this patch, slightly cleaned up. I moved
svn_bdb__check_version into its own file, and I realised there's no need
to remember the compile-time DB version in static variables -- those
defines are constants, anyway. I also reverted the include of
bdb_compat.h from the headers that didn't use any of its features.
Added support for building with both Berkeley DB 4.0.14 and 4.1.24.
Based on this patch by Justin Erenkrantz <jerenkrantz@apache.org>:
http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=22004
[ in subversion/libsvn_fs ]
* bdb/bdb_compat.h: New header. Definitions for BDB 4.0/4.1 compatibility.
* bdb/bdb_compat.c: New file. Implements svn_bdb__check_version.
* bdb/changes-table.c, bdb/copies-table.c, bdb/nodes-table.c, bdb/reps-table.c,
bdb/rev-table.c, bdb/strings-table.c, bdb/txn-table.c:
Include "bdb_compat.h" instead of <db.h>. In calls to DB->open, wrap
the environment and transaction parameter in SVN_BDB_OPEN_PARAMS. Pass
the SVN_BDB_AUTO_COMMIT flag to DB->open and DB->put wherever the
transaction is NULL. Check the BDB version before each call to
db_create.
* bdb/changes-table.h: Include <db.h> instead of "db.h".
* fs.c: Include bdb/bdb_compat.h.
(check_db_version): New function.
(check_already_open): Extract version check into check_db_version.
(svn_fs_create_berkeley, svn_fs_open_berkeley): Call check_db_version.
(cleanup_fs_db, cleanup_fs): Make usage of DB_INCOMPLETE conditional.
* libsvn_fs.dsp: Add bdb/bdb_compat.c.
[top-level]
* subversion/mod_dav_svn/mod_dav_svn.dsp: Add bdb/bdb_compat.c.
--
Brane Čibej <brane_at_xbc.nu> http://www.xbc.nu/brane/
cd c:/Home/brane/src/svn/repo/
subversion/clients/cmdline/Debug/svn.exe diff subversion/libsvn_fs
Index: subversion/libsvn_fs/bdb/txn-table.c
===================================================================
--- subversion/libsvn_fs/bdb/txn-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/txn-table.c (working copy)
@@ -16,8 +16,8 @@
*/
#include <string.h>
-#include <db.h>
#include <assert.h>
+#include "bdb_compat.h"
#include "svn_pools.h"
#include "txn-table.h"
@@ -43,11 +43,14 @@
DB_ENV *env,
int create)
{
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
DB *txns;
+ DB_ERR (svn_bdb__check_version());
DB_ERR (db_create (&txns, env, 0));
- DB_ERR (txns->open (txns, "transactions", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (txns->open (SVN_BDB_OPEN_PARAMS(txns, NULL),
+ "transactions", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
0666));
/* Create the `next-id' table entry. */
@@ -59,7 +62,7 @@
svn_fs__str_to_dbt (&key,
(char *) svn_fs__next_key_key),
svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
}
*transactions_p = txns;
Index: subversion/libsvn_fs/bdb/reps-table.c
===================================================================
--- subversion/libsvn_fs/bdb/reps-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/reps-table.c (working copy)
@@ -15,7 +15,7 @@
* ====================================================================
*/
-#include <db.h>
+#include "bdb_compat.h"
#include "svn_fs.h"
#include "../fs.h"
#include "../util/fs_skels.h"
@@ -35,11 +35,14 @@
DB_ENV *env,
int create)
{
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
DB *reps;
+ DB_ERR (svn_bdb__check_version());
DB_ERR (db_create (&reps, env, 0));
- DB_ERR (reps->open (reps, "representations", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (reps->open (SVN_BDB_OPEN_PARAMS(reps, NULL),
+ "representations", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
0666));
/* Create the `next-key' table entry. */
@@ -51,7 +54,7 @@
(reps, 0,
svn_fs__str_to_dbt (&key, (char *) svn_fs__next_key_key),
svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
}
*reps_p = reps;
Index: subversion/libsvn_fs/bdb/bdb_compat.h
===================================================================
--- subversion/libsvn_fs/bdb/bdb_compat.h (working copy)
+++ subversion/libsvn_fs/bdb/bdb_compat.h (working copy)
@@ -0,0 +1,72 @@
+/* svn_bdb_compat.h --- Compatibility wrapper for different BDB versions.
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+#ifndef SVN_LIBSVN_FS_BDB_COMPAT_H
+#define SVN_LIBSVN_FS_BDB_COMPAT_H
+
+#include <db.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* BDB 4.1 introduced the DB_AUTO_COMMIT flag. Older versions can just
+ use 0 instead. */
+#ifdef DB_AUTO_COMMIT
+#define SVN_BDB_AUTO_COMMIT (DB_AUTO_COMMIT)
+#else
+#define SVN_BDB_AUTO_COMMIT (0)
+#endif
+
+/* DB_INCOMPLETE is obsolete in BDB 4.1. */
+#ifdef DB_INCOMPLETE
+#define SVN_BDB_HAS_DB_INCOMPLETE 1
+#else
+#define SVN_BDB_HAS_DB_INCOMPLETE 0
+#endif
+
+/* In BDB 4.1, DB->open takes a transaction parameter. We'll ignore it
+ when building with 4.0. */
+#if (DB_VERSION_MAJOR > 4) \
+ || (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR >= 1)
+#define SVN_BDB_OPEN_PARAMS(env,txn) (env), (txn)
+#else
+#define SVN_BDB_OPEN_PARAMS(env,txn) (env)
+#endif
+
+
+/* Before calling db_create, we must check that the version of the BDB
+ libraries we're linking with is the same as the one we compiled
+ against, because the DB->open call is not binary compatible between
+ BDB 4.0 and 4.1. This function returns DB_OLD_VERSION if the
+ compile-time and run-time versions of BDB don't match. */
+int svn_bdb__check_version (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_LIBSVN_FS_BDB_COMPAT_H */
+
+
+/*
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: subversion/libsvn_fs/bdb/changes-table.h
===================================================================
--- subversion/libsvn_fs/bdb/changes-table.h (revision 3421)
+++ subversion/libsvn_fs/bdb/changes-table.h (working copy)
@@ -18,7 +18,7 @@
#ifndef SVN_LIBSVN_FS_CHANGES_TABLE_H
#define SVN_LIBSVN_FS_CHANGES_TABLE_H
-#include "db.h"
+#include <db.h>
#include "svn_io.h"
#include "svn_fs.h"
#include "../trail.h"
Index: subversion/libsvn_fs/bdb/copies-table.c
===================================================================
--- subversion/libsvn_fs/bdb/copies-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/copies-table.c (working copy)
@@ -17,7 +17,7 @@
#include <string.h>
-#include <db.h>
+#include "bdb_compat.h"
#include "../fs.h"
#include "../err.h"
#include "../key-gen.h"
@@ -35,11 +35,14 @@
DB_ENV *env,
int create)
{
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
DB *copies;
+ DB_ERR (svn_bdb__check_version());
DB_ERR (db_create (&copies, env, 0));
- DB_ERR (copies->open (copies, "copies", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (copies->open (SVN_BDB_OPEN_PARAMS(copies, NULL),
+ "copies", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
0666));
/* Create the initial `next-id' table entry. */
@@ -50,7 +53,7 @@
svn_fs__str_to_dbt (&key,
(char *) svn_fs__next_key_key),
svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
}
*copies_p = copies;
Index: subversion/libsvn_fs/bdb/strings-table.c
===================================================================
--- subversion/libsvn_fs/bdb/strings-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/strings-table.c (working copy)
@@ -15,7 +15,7 @@
* ====================================================================
*/
-#include <db.h>
+#include "bdb_compat.h"
#include "svn_fs.h"
#include "svn_pools.h"
#include "../fs.h"
@@ -33,17 +33,20 @@
DB_ENV *env,
int create)
{
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
DB *strings;
+ DB_ERR (svn_bdb__check_version());
DB_ERR (db_create (&strings, env, 0));
/* Enable duplicate keys. This allows the data to be spread out across
multiple records. Note: this must occur before ->open(). */
DB_ERR (strings->set_flags (strings, DB_DUP));
- DB_ERR (strings->open (strings, "strings", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
- 0666));
+ DB_ERR (strings->open (SVN_BDB_OPEN_PARAMS(strings, NULL),
+ "strings", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
+ 0666));
if (create)
{
@@ -54,7 +57,7 @@
(strings, 0,
svn_fs__str_to_dbt (&key, (char *) svn_fs__next_key_key),
svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
}
*strings_p = strings;
Index: subversion/libsvn_fs/bdb/rev-table.c
===================================================================
--- subversion/libsvn_fs/bdb/rev-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/rev-table.c (working copy)
@@ -15,7 +15,7 @@
* ====================================================================
*/
-#include <db.h>
+#include "bdb_compat.h"
#include "svn_fs.h"
#include "../fs.h"
#include "../err.h"
@@ -31,11 +31,14 @@
DB_ENV *env,
int create)
{
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
DB *revisions;
+ DB_ERR (svn_bdb__check_version());
DB_ERR (db_create (&revisions, env, 0));
- DB_ERR (revisions->open (revisions, "revisions", 0, DB_RECNO,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (revisions->open (SVN_BDB_OPEN_PARAMS(revisions, NULL),
+ "revisions", 0, DB_RECNO,
+ open_flags | SVN_BDB_AUTO_COMMIT,
0666));
*revisions_p = revisions;
Index: subversion/libsvn_fs/bdb/bdb_compat.c
===================================================================
--- subversion/libsvn_fs/bdb/bdb_compat.c (working copy)
+++ subversion/libsvn_fs/bdb/bdb_compat.c (working copy)
@@ -0,0 +1,37 @@
+/* bdb_compat.c --- Compatibility wrapper for different BDB versions.
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+#include "bdb_compat.h"
+
+int
+svn_bdb__check_version (void)
+{
+ int major, minor;
+
+ db_version(&major, &minor, NULL);
+ if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR)
+ return DB_OLD_VERSION;
+ return 0;
+}
+
+
+
+/*
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: subversion/libsvn_fs/bdb/changes-table.c
===================================================================
--- subversion/libsvn_fs/bdb/changes-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/changes-table.c (working copy)
@@ -15,7 +15,7 @@
* ====================================================================
*/
-#include <db.h>
+#include "bdb_compat.h"
#include <apr_hash.h>
#include <apr_tables.h>
@@ -39,16 +39,19 @@
DB_ENV *env,
int create)
{
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
DB *changes;
+ DB_ERR (svn_bdb__check_version());
DB_ERR (db_create (&changes, env, 0));
/* Enable duplicate keys. This allows us to store the changes
one-per-row. Note: this must occur before ->open(). */
DB_ERR (changes->set_flags (changes, DB_DUP));
- DB_ERR (changes->open (changes, "changes", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (changes->open (SVN_BDB_OPEN_PARAMS(changes, NULL),
+ "changes", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
0666));
*changes_p = changes;
Index: subversion/libsvn_fs/bdb/nodes-table.c
===================================================================
--- subversion/libsvn_fs/bdb/nodes-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/nodes-table.c (working copy)
@@ -17,7 +17,7 @@
#include <string.h>
#include <assert.h>
-#include <db.h>
+#include "bdb_compat.h"
#include "svn_fs.h"
@@ -41,11 +41,14 @@
DB_ENV *env,
int create)
{
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
DB *nodes;
+ DB_ERR (svn_bdb__check_version());
DB_ERR (db_create (&nodes, env, 0));
- DB_ERR (nodes->open (nodes, "nodes", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (nodes->open (SVN_BDB_OPEN_PARAMS(nodes, NULL),
+ "nodes", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
0666));
/* Create the `next-id' table entry (use '1' because '0' is
@@ -58,7 +61,7 @@
svn_fs__str_to_dbt (&key,
(char *) svn_fs__next_key_key),
svn_fs__str_to_dbt (&value, (char *) "1"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
}
*nodes_p = nodes;
Index: subversion/libsvn_fs/fs.c
===================================================================
--- subversion/libsvn_fs/fs.c (revision 3421)
+++ subversion/libsvn_fs/fs.c (working copy)
@@ -34,6 +34,7 @@
#include "dag.h"
#include "svn_private_config.h"
+#include "bdb/bdb_compat.h"
#include "bdb/nodes-table.h"
#include "bdb/rev-table.h"
#include "bdb/txn-table.h"
@@ -45,28 +46,48 @@
/* Checking for return values, and reporting errors. */
-
-/* If FS is already open, then return an SVN_ERR_FS_ALREADY_OPEN
- error. Otherwise, return zero. */
+/* Check that we're using the right Berkeley DB version. */
+/* FIXME: This check should be abstracted into the DB back-end layer. */
static svn_error_t *
-check_already_open (svn_fs_t *fs)
+check_bdb_version (apr_pool_t *pool)
{
int major, minor, patch;
- /* ### check_already_open() doesn't truly have the right semantic for
- ### this, but it is called by both create_berkeley and open_berkeley,
- ### so it happens to be a low-cost point. probably should be
- ### refactored to go elsewhere. note that svn_fs_new() doesn't return
- ### an error, so it isn't quite suitable. */
db_version (&major, &minor, &patch);
+
+ /* First, check that we're using a reasonably correct of Berkeley DB. */
if ((major < SVN_FS_WANT_DB_MAJOR)
|| (major == SVN_FS_WANT_DB_MAJOR && minor < SVN_FS_WANT_DB_MINOR)
|| (major == SVN_FS_WANT_DB_MAJOR && minor == SVN_FS_WANT_DB_MINOR
&& patch < SVN_FS_WANT_DB_PATCH))
- return svn_error_createf (SVN_ERR_FS_GENERAL, 0, 0, fs->pool,
- "bad database version: %d.%d.%d",
+ return svn_error_createf (SVN_ERR_FS_GENERAL, 0, 0, pool,
+ "bad database version: got %d.%d.%d,"
+ " should be at least %d.%d.%d",
+ major, minor, patch,
+ SVN_FS_WANT_DB_MAJOR,
+ SVN_FS_WANT_DB_MINOR,
+ SVN_FS_WANT_DB_PATCH);
+
+ /* Now, check that the version we're running against is the same as
+ the one we compiled with. */
+ if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR)
+ return svn_error_createf (SVN_ERR_FS_GENERAL, 0, 0, pool,
+ "bad database version:"
+ " compiled with %d.%d.%d,"
+ " running against %d.%d.%d",
+ DB_VERSION_MAJOR,
+ DB_VERSION_MINOR,
+ DB_VERSION_PATCH,
major, minor, patch);
+ return SVN_NO_ERROR;
+}
+
+/* If FS is already open, then return an SVN_ERR_FS_ALREADY_OPEN
+ error. Otherwise, return zero. */
+static svn_error_t *
+check_already_open (svn_fs_t *fs)
+{
if (fs->env)
return svn_error_create (SVN_ERR_FS_ALREADY_OPEN, 0, 0, fs->pool,
"filesystem object already open");
@@ -104,6 +125,7 @@
*db_ptr = 0;
db_err = db->close (db, 0);
+#if SVN_BDB_HAS_DB_INCOMPLETE
/* We can ignore DB_INCOMPLETE on db->close and db->sync; it
* just means someone else was using the db at the same time
* we were. See the Berkeley documentation at:
@@ -112,6 +134,7 @@
*/
if (db_err == DB_INCOMPLETE)
db_err = 0;
+#endif /* SVN_BDB_HAS_DB_INCOMPLETE */
SVN_ERR (DB_WRAP (fs, msg, db_err));
}
@@ -141,11 +164,13 @@
{
int db_err = env->txn_checkpoint (env, 0, 0, 0);
+#if SVN_BDB_HAS_DB_INCOMPLETE
while (db_err == DB_INCOMPLETE)
{
apr_sleep (APR_USEC_PER_SEC * 1);
db_err = env->txn_checkpoint (env, 0, 0, 0);
}
+#endif /* SVN_BDB_HAS_DB_INCOMPLETE */
/* If the environment was not (properly) opened, then txn_checkpoint
will typically return EINVAL. Ignore this case.
@@ -383,6 +408,7 @@
svn_error_t *svn_err;
const char *path_native;
+ SVN_ERR (check_bdb_version (fs->pool));
SVN_ERR (check_already_open (fs));
/* Initialize the fs's path. */
@@ -519,6 +545,7 @@
svn_error_t *svn_err;
const char *path_native;
+ SVN_ERR (check_bdb_version (fs->pool));
SVN_ERR (check_already_open (fs));
/* Initialize paths. */
Index: subversion/libsvn_fs/libsvn_fs.dsp
===================================================================
--- subversion/libsvn_fs/libsvn_fs.dsp (revision 3421)
+++ subversion/libsvn_fs/libsvn_fs.dsp (working copy)
@@ -139,6 +139,21 @@
# End Source File
# Begin Source File
+SOURCE=".\bdb\bdb_compat.c"
+
+!IF "$(CFG)" == "libsvn_fs - Win32 Release"
+
+# PROP Intermediate_Dir "Release\obj\bdb"
+
+!ELSEIF "$(CFG)" == "libsvn_fs - Win32 Debug"
+
+# PROP Intermediate_Dir "Debug\obj\bdb"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
SOURCE=".\bdb\copies-table.c"
!IF "$(CFG)" == "libsvn_fs - Win32 Release"
Compilation finished at Tue Oct 22 01:21:39
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Oct 22 01:27:36 2002